三、Windows键盘快捷键—处理菜单项
当然,如果POPPAD2程序不使用子窗口编辑控件,那么我们将面临一些问题,这涉及如何完成「Edit」菜单中的「Undo」、「Cut」、「Copy」、「Paste」、「Clear」和「Select All」选项。正是编辑控件使得这种处理变得容易,因为对于每一个选项我们只需向编辑控件发送一个消息即可:
case IDM_UNDO : SendMessage (hwndEdit, WM_UNDO, 0, 0) ; return 0 ; case IDM_CUT : SendMessage (hwndEdit, WM_CUT, 0, 0) ; return 0 ; case IDM_COPY : SendMessage (hwndEdit, WM_COPY, 0, 0) ; return 0 ; case IDM_PASTE : SendMessage (hwndEdit, WM_PASTE, 0, 0) ; return 0 ; case IDM_DEL : SendMessage (hwndEdit, WM_DEL, 0, 0) ; return 0 ; case IDM_SELALL : SendMessage (hwndEdit, EM_SETSEL, 0, -1) ; return 0 ;
注意,我们可以更进一步简化这些处理-只要使IDM_UNDO、IDM_CUT等等的值等于相对应的窗口消息WM_UNDO、WM_CUT的值。
「File」弹出式菜单上的「About」选项启动一个简单的消息框:
case IDM_ABOUT : MessageBox (hwnd, TEXT ("POPPAD2 (c) Charles Petzold, 1998"), szAppName, MB_OK | MB_ICONINFORMATION) ; return 0 ;
在下一章中,我们将把它变成一个对话框。当您从菜单中选择「Help」选项或者按下F1快捷键时,同样可以启动一个消息框。
「Exit」选项向窗口消息处理程序发送一个WM_CLOSE消息:
case IDM_EXIT : SendMessage (hwnd, WM_CLOSE, 0, 0) ; return 0 ;
这正是DefWindowProc收到一个wParam等于SC_CLOSE的WM_SYSCOMMAND消息时所完成的工作。
在前面的那些程序中,我们没有在窗口消息处理程序中处理WM_CLOSE消息,而只是简单地把它送给DefWindowProc。DefWindowProc对WM_CLOSE的处理非常简单:呼叫DestroyWindow函数。可以不把WM_CLOSE消息送给DefWindowProc,而让POPPAD2来处理它。这个事实到目前为止并不重要,但是在第十一章中当POPPAD可以真正编辑文字时,它就变得非常重要了。
case WM_CLOSE : if (IDYES == AskConfirmation (hwnd)) DestroyWindow (hwnd) ; return 0 ;
AskConfirmation是POPPAD2中的一个函数,它显示一个请求确认关闭程序的消息框:
AskConfirmation (HWND hwnd) { return MessageBox (hwnd, TEXT ("Really want to close Poppad2?"), szAppName, MB_YESNO | MB_ICONQUESTION) ; }
如果选择了Yes按钮的话,消息框(以及AskConfirmation函数)将传回IDYES。只有这样,程序才会呼叫DestroyWindow,否则,程序不会结束。
如果要在程序结束之前确认使用者真的要结束程序,那么您还必须处理WM_QUERYENDSESSION消息。当使用者要关闭Windows时,Windows开始向每个窗口消息处理程序发送一个WM_QUERYENDSESSION消息。如果有任何一个窗口消息处理程序处理这个消息后传回0,那么Windows将不会结束。我们如下处理了WM_QUERYENDSESSION:
case WM_QUERYENDSESSION : if (IDYES == AskConfirmation (hwnd)) return 1 ; else return 0 ;
如果要在程序结束之前要求使用者的确认,必须处理WM_CLOSE和WM_QUERYENDSESSION这两个消息,这就是为什么我们使POPPAD2中的「Exit」菜单选项只向窗口消息处理程序发送一个WM_CLOSE消息的原因。这样做,我们避免了在别处进行请求确认的动作。
如果要处理WM_QUERYENDSESSION消息,那么您也许还会对WM_ENDSESSION消息感兴趣。Windows把这个消息发送给先前收到WM_QUERYENDSESSION消息的每个窗口消息处理程序。如果由于另一个程序从WM_QUERYENDSESSION传回了0而不能结束Windows的执行,那么WM_ENDSESSION的wParam参数为0。WM_ENDSESSION消息实际上回答了这个问题:我告诉过Windows可以把我结束掉,但是我真的被结束掉了吗?
尽管在POPPAD2的「File」菜单中我加上了常见的「New」、「Open」、「Save」和「Save As」选项,但是它们现在并不起作用。要处理这些命令,我们需要使用对话框。现在是讨论对话框的时机,也是您准备学习它们的时候了。