MFC对话框中的OnCancel虚拟方法在如下三个时机被调用:
1、对话框按IDCANCEL按钮,直接通过CDialog的ON_COMMAND(IDCANCEL, &CDialog::OnCancel)的消息映射,触发对OnCancel的调用;
2、按ESC按键,在CDialog::PreTranslateMessage中,调用CWnd::PreTranslateInput,进而调用CWnd::IsDialogMessage,接下来调用Windows API ::IsDialogMessage。在::IsDialogMessage处理中,应该(无法查看Windows源码,根据调试跟踪推测)SendMessage WM_COMMAND,ID为IDCANCEL,直接调用OnCancel;
3、按对话框右上角“X”按钮,缺省的OnClose会调用CWnd::Default,继而调用CWnd::DefWindowProc,进一步调用::CallWindowProc(m_pfnSuper, m_hWnd, nMsg, wParam, lParam),推测CallWindowProc(无法查看Windows源码,根据调试跟踪推测)会投递(即PostMessage)一条WM_COMMAND消息,ID为IDCANCEL,从而触发OnCancel被调用。
补充:
对于1、IDCANCEL按钮的WM_COMMAND消息是子窗口(按钮)向父窗口发送消息(SendMessage),所以不经过CDialog::PreTranslateMessage,直接经过CDialog::OnCommand调用OnCancel;
对于2、由于是SendMessage,也不再次经过CDialog::PreTranslateMessage,直接经过CDialog::OnCommand调用OnCancel;
对于3、由于是投递的WM_COMMAND消息并且是顶级窗口的消息,会经过CWinApp::PreTranslateMessage,再流经CDialog::PreTranslateMessage,最后通过CDialog::OnCommand调用OnCancel。
实验表明:如果是普通的框架窗口,处理OnClose的缺省操作会调用DestroyWindow关闭窗口,对于对话框窗口,是投递WM_COMMAND,控件ID是IDCANCEL。