Using the ‘Open File’ and ‘Save File’ dialogs, GetOpenFileName and GetSaveFileName APIs

Recently, someone on the MSDN forum asked if there are any built-in ‘Open File’ and ‘Save File’ dialogs available in the Windows Mobile platform. The answer, of course, is yes. The APIs that get the task done are GetOpenFileName() and GetSaveFileName(). These APIs allow the user to select directories or files for opening or saving. I wrote a small application to demonstrate how to use these APIs. The application has a multiline edit control and menu options for opening or saving text files (see video at the end). When you open a text file, the files contents are shown on the edit control, and saving to a file writes the contents of the edit control to a user selected text file. Pretty simple.

First, lets take a look at GetOpenFileName() API, the DoOpenFile() method in the application reads the contents of the file and writes it to the edit control, here is the function: (error checking is left out, as usual)

1. Get the full path to the file
2. Read the contents of the file into a buffer
3. Convert the buffer into wide char
4. Display the wide chars on the edit control

BOOL DoOpenFile(HWND hDlg)
{
    TCHAR   szFile[MAX_PATH] = TEXT("\0");
    char    *szFileContent = NULL;
    OPENFILENAME   ofn;
    HANDLE hFile = INVALID_HANDLE_VALUE;
    DWORD dwFileSize = 0, bytesToRead = 0, bytesRead = 0;
   
    memset( &(ofn), 0, sizeof(ofn));
    ofn.lStructSize   = sizeof(ofn);
    ofn.hwndOwner = hDlg;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFilter = TEXT("Txt (*.txt)\0 *.txt\0");  
    ofn.lpstrTitle = TEXT("Open File");
    ofn.Flags = OFN_EXPLORER;

    //get the filename the user wants to open
    if (GetOpenFileName(&ofn))
    {
        //ofn.lpstrFile contains the full path to the file, get a handle to it
        hFile = CreateFile(ofn.lpstrFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

        if (hFile == INVALID_HANDLE_VALUE)
            return FALSE;

        //get file size in bytes
        dwFileSize = GetFileSize(hFile, NULL);

        szFileContent = (char*)malloc(dwFileSize+1);
       
        memset(szFileContent, 0, dwFileSize+1);

        //read the files contents into a buffer
        if (ReadFile(hFile, szFileContent, dwFileSize, &bytesRead, NULL))
        {
            TCHAR *wszTemp = NULL;
            HWND hEdit = NULL;

            wszTemp = (TCHAR*)malloc(bytesRead*sizeof(TCHAR));

            //convert the chars in buffer to wide chars
            mbstowcs(wszTemp, szFileContent, bytesRead);
            hEdit = GetDlgItem(hDlg, IDC_EDIT);

            //set the content of edit control
            SetWindowText(hEdit, wszTemp);

            free(wszTemp);
        }

        //free resources
        free(szFileContent);
        CloseHandle(hFile);
    }

    return TRUE;
}

The APIs and the OPENFILENAME structure are explained well in the MSDN documentation, so I am not going to repeat the same things here. Follow the links.

The DoSaveFile() method in the application allows the user to save the contents of edit control into a file, here is the code:

1. Get the full path to the file
2. Read the contents of edit control into a wide char buffer
3. Convert the wide char into char (multibyte string)
4. Write the chars to the file

BOOL DoSaveFile(HWND hDlg)
{
    TCHAR   szFile[MAX_PATH] = TEXT("\0");
    OPENFILENAME   ofn;
    HANDLE hFile = INVALID_HANDLE_VALUE;
   
    memset( &(ofn), 0, sizeof(ofn));
    ofn.lStructSize   = sizeof(ofn);
    ofn.hwndOwner = hDlg;
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrFilter = TEXT("Text (*.txt)\0*.txt\0");  
    ofn.lpstrTitle = TEXT("Save File As");
    ofn.Flags = OFN_HIDEREADONLY;
    ofn.lpstrDefExt = TEXT("txt");

    //get the filename the user wants to save to
    if (GetSaveFileName(&ofn))
    {
        HWND hEdit = NULL;
        DWORD dwTextLen = 0, bytesWritten = 0;
        TCHAR *wszEditText = NULL;
        char *szEditText = NULL;

        //ofn.lpstrFile contains the full path of the file, get a handle to it
        hFile = CreateFile(ofn.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

        if (hFile == INVALID_HANDLE_VALUE)
            return FALSE;

        hEdit = GetDlgItem(hDlg, IDC_EDIT);

        //get the text length of the edit controls contents
        dwTextLen = GetWindowTextLength(hEdit);

        wszEditText = (TCHAR*)malloc((dwTextLen+1)*sizeof(TCHAR));

        memset(wszEditText, 0, (dwTextLen+1)*sizeof(TCHAR));

        //read edit controls contents into buffer
        GetWindowText(hEdit, wszEditText, dwTextLen+1);

        szEditText = (char*)malloc(dwTextLen+1);
       
        //convert the wide char read from edit control to char
        wcstombs(szEditText, wszEditText, dwTextLen);

        //save the contents into file
        if (WriteFile(hFile, szEditText, dwTextLen, &bytesWritten, NULL))
        {
        }

        //free resources
        free(wszEditText);
        free(szEditText);
        CloseHandle(hFile);
    }
   
    return TRUE;
}

Here is a video demo of how things work,  

 

Leave a Reply

Your email address will not be published. Required fields are marked *