Replace the WM_COMMAND Case

Replace the WM_COMMAND case so that it processes all File-menu commands except Print. The New command should clear the current filename and empty the edit control if there is any text in it. The Open command should retrieve the selected filename, open the file, and fill the edit control. The Save command should write the contents of the edit control back to the current file. Finally, the Save As command should prompt the user for a filename and write the contents of the edit control.

If the user chooses the New command and there is text in the current file that has been modified, you should prompt the user with a message box to determine whether the changes should be saved. Add the following statements to the WM_COMMAND case:

case IDM_NEW:

if(!QuerySaveFile(hWnd))

return (NULL);

bChanges = FALSE;

FileName[0] = 0;

SetNewBuffer(hWnd, NULL, Untitled);

break;

The locally defined QuerySaveFile function checks the file for changes and prompts the user to save the changes. If the changes are saved, the filename is cleared and the editing buffer is emptied by using the locally-defined SetNewBuffer function.

If the user chooses the Open command and there is text in the current file that has been modified, you should prompt the user to determine whether the changes should be saved before opening the new file. Add the following statements to the WM_COMMAND case:

case IDM_OPEN:

if(!QuerySaveFile(hWnd))

return(NULL);

lpOpenDlg = MakeProcInstance((FARPROC) OpenDlg, hInst);

hFile = DialogBox(hInst, “Open”, hWnd, lpOpenDlg);

FreeProcInstance(lpOpenDlg);

if(!hFile)

return(NULL);

hEditBuffer =

LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,

FileStatus.st_size+1);

if(!hEditBuffer) {

MessageBox(hWnd, “Not enough memory.”,

NULL, MB_OK | MB_ICONHAND);

return(NULL);

}

hSaveCursor = SetCursor(hHourGlass);

pEditBuffer = LocalLock(hEditBuffer);

IOStatus = read(hFile, pEditBuffer, FileStatus.st_size);

close(hFile);

if(IOStatus != FileStatus.st_size) {

sprintf(str, “Error reading %s.”, FileName);

SetCursor(hSaveCursor); /* Remove the hourglass */

MessageBox(hWnd, str, NULL,

MB_OK | MB_ICONEXCLAMATION);

}

LocalUnlock(hEditBuffer);

sprintf(str, “EditFile - %s”, FileName);

SetNewBuffer(hWnd, hEditBuffer, str);

SetCursor(hSaveCursor); /* Restore the cursor */

break;

When the IDM_OPEN case is processed, the QuerySaveFile function checks the existing file for changes before displaying the Open dialog box. The DialogBox function returns a file handle to the open file. This handle is created in the OpenDlg dialog function. If the file can't be opened, the function returns NULL and processing ends. Otherwise, the LocalAlloc function allocates the space needed to load the file into memory. The amount of space needed is determined by the FileStatus structure, which is filled with information about the open file by the OpenDlg dialog function. If there is no available memory, a message box is displayed an the new buffer, and the C run-time read function copies the contents of the file into memory. If the file was not read completely, a message box is displayed. SetCursor restores the cursor before the MessageBox function is called. The LocalUnlock function unlocks the editing buffer, and after a new window caption is created, the locally defined SetNewBuffer function changes the editing buffer and caption.

If the user chooses the Save command and there is no current filename, carry out the same action as the Save As command. Add the following statements to the WM_COMMAND case:

case IDM_SAVE:

if(!FileName[0])

goto saveas;

if(bChanges)

SaveFile(hWnd);

break;

The IDM_SAVE case checks for a filename and, if none exists, skips to the IDM_SAVEAS case. If a filename does exist, the locally defined SaveFile function saves the file only if changes have been made to it.

The Save As command should always prompt for a filename. You should save the file only if the user gives a valid filename. Add the following statements to the WM_COMMAND case:

case IDM_SAVEAS:

saveas:

lpSaveAsDlg = MakeProcInstance(SaveAsDlg, hInst);

Success = DialogBox(hInst, “SaveAs”, hWnd, lpSaveAsDlg);

FreeProcInstance(lpSaveAsDlg);

if(Success == IDOK) {

sprintf(str, “EditFile - %s”, FileName);

SetWindowText(hWnd, str);

SaveFile(hWnd);

}

break; /* User canceled */

The DialogBox function displays the Save As dialog box. The MakeProcInstance and FreeProcInstance functions create and free the procedure-instance address for the SaveAsDlg dialog function. The DialogBox function returns IDOK from the SaveAsDlg dialog function if the user enters a valid filename. The SetWindowText function then changes the window caption, and the SaveFile function saves the contents of the editing buffer to the file.

The Exit command should now prompt the user to determine whether the current file should be saved. Also, to keep track of the changes to the file, you should process notification messages from the edit-control window. Modify the IDM_EXIT case and add the IDC_EDIT case to the WM_COMMAND case, as follows:

case IDM_EXIT:

QuerySaveFile(hWnd);

DestroyWindow(hWnd);

break;

case IDC_EDIT:

if(HIWORD(lParam) == EN_CHANGE)

bChanges = TRUE;

return(NULL);