Of course, if we were not using a child window edit control for POPPAD2, we would now be faced with the problems involved with actually implementing the Undo, Cut, Copy, Paste, Clear, and Select All options from the Edit menu. But the edit control makes this process easy, because we merely send the edit control a message for each of these options:
case IDM_UNDO :
SendMessage (hwndEdit, WM_UNDO, 0, 0L) ;
return 0 ;
case IDM_CUT :
SendMessage (hwndEdit, WM_CUT, 0, 0L) ;
return 0 ;
case IDM_COPY :
SendMessage (hwndEdit, WM_COPY, 0, 0L) ;
return 0 ;
case IDM_PASTE :
SendMessage (hwndEdit, WM_PASTE, 0, 0L) ;
return 0 ;
case IDM_CLEAR :
SendMessage (hwndEdit, WM_CLEAR, 0, 0L) ;
return 0 ;
case IDM_SELALL :
SendMessage (hwndEdit, EM_SETSEL, 0,
MAKELONG (0, 32767)) ;
return 0 ;
Notice that we could have simplified this even further by making the values of IDM_UNDO, IDM_CUT, and so forth equal to the values of the corresponding window messages WM_UNDO, WM_CUT, and so forth.
The About option for the File popup invokes a simple message box:
case IDM_ABOUT :
MessageBox (hwnd,
"POPPAD2 (c) Charles Petzold, 1990",
szAppName, MB_OK | MB_ICONINFORMATION) ;
break ;
In Chapter 10 we'll make this a dialog box.
The Exit option sends the window procedure a WM_CLOSE message:
case IDM_EXIT :
SendMessage (hwnd, WM_CLOSE, 0, 0L) ;
return 0 ;
That is precisely what DefWindowProc does when it receives a WM_SYSCOMMAND message with wParam equal to SC_CLOSE.
In previous programs we have not processed the WM_CLOSE messages in our window procedure but have simply passed them to DefWindowProc. DefWindowProc does something very simple with WM_CLOSE: It calls the DestroyWindow function. Rather than send WM_CLOSE messages to DefWindowProc, however, POPPAD2 processes them. This fact is not so important now, but it will become very important in Chapter 10 when POPPAD can actually edit files:
case WM_CLOSE :
if (IDYES == AskConfirmation (hwnd))
DestroyWindow (hwnd) ;
return 0 ;
AskConfirmation is a function in POPPAD2 that displays a message box asking for confirmation to close the program:
AskConfirmation (HWND hwnd)
{return MessageBox (hwnd, "Really want to close POPPAD2?",
szAppName, MB_YESNO | MB_ICONQUESTION) ;
}The message box (as well as the AskConfirmation function) returns IDYES if the Yes button is selected. Only then does POPPAD2 call DestroyWindow. Otherwise, the program is not terminated.
If you want confirmation before terminating a program, you must also process WM_QUERYENDSESSION messages. Windows begins sending every window procedure a WM_QUERYENDSESSION message when the user chooses Close from the MS-DOS Executive system menu. If any window procedure returns 0 from this message, the Windows session is not terminated. Here's how we handle WM_QUERYENDSESSION:
case WM_QUERYENDSESSION :
if (IDYES == AskConfirmation (hwnd))
return 1L ;
else
return 0 ;
The WM_CLOSE and WM_QUERYENDSESSION messages are the only two messages you have to process if you want to ask for user confirmation before ending a program. That's why we made the Exit menu option in POPPAD2 send the window procedure a WM_CLOSE message—by doing so, we avoided having to ask for confirmation at yet a third point.
If you process WM_QUERYENDSESSION messages, you may also be interested in the WM_ENDSESSION message. Windows sends this message to every window procedure that has previously received a WM_QUERYENDSESSION message. The wParam parameter is 0 if the session fails to terminate because another program has returned 0 from WM_QUERYENDSESSION. The WM_ENDSESSION message essentially answers the question: I told Windows it was OK to terminate me, but did I really get terminated?
Although I've included the normal New, Open, Save, and Save As options in POPPAD2's File menu, they are currently nonfunctional. To process these commands, we need to use dialog boxes. You're now ready to learn about them.