Date: | November 12, 2003 / year-entry #126 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20031112-00/?p=41863 |
Comments: | 2 |
Summary: | In the discussion following my entry about dialog procedure return values, somebody suggested an alternate dialog design where you just call DefDlgProc to do default actions (the same way you write window procedures and DefWindowProc) rather than returning TRUE/FALSE. So let's do that. In fact, we're going to do it twice. I'll cover one method... |
In the discussion following my entry about dialog procedure return
values, somebody suggested an alternate dialog design where
you just call So let's do that. In fact, we're going to do it twice. I'll cover one method today and cover an entirely different method later this week. Each method consists of a simple kernel of an idea; the rest is just scaffolding to make the kernel work.
The first way uses a recursive call from the
dialog procedure back into
The kernel
is to "subvert the recursive call". Here's the flow diagram, for those who prefer pictures: Message delivered -> DefDlgProc -> your dialog procedure decide what to do want to do the default action -> DefDlgProc -> your dialog procedure detect recursion <- return FALSE DefDlgProc sees FALSE performs default behavior <- returns result of default behavior you do other stuff (perhaps modify default behavior after it occurred) set DWLP_MSGRESULT to desired result <- return TRUE retrieve DWLP_MSGRESULT <- return it as message result Given this sketch, you should be able to write it up yourself. Here's what I came up with. I call it a Wndproc-Like Dialog: class WLDialogBox { public: virtual LRESULT WLDlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefDlgProcEx(hdlg, uMsg, wParam, lParam, &m_fRecursing); } INT_PTR DoModal(HINSTANCE hinst, LPCTSTR pszTemplate, HWND hwndParent) { m_fRecursing = FALSE; return DialogBoxParam(hinst, pszTemplate, hwndParent, s_DlgProc, (LPARAM)this); } private: static INT_PTR CALLBACK s_DlgProc( HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_INITDIALOG) { SetWindowLongPtr(hdlg, DWLP_USER, lParam); } WLDialogBox *self = (WLDialogBox*)GetWindowLongPtr( hdlg, DWLP_USER); if (!self) { return FALSE; } CheckDefDlgRecursion(&self->m_fRecursing); return SetDlgMsgResult(hdlg, uMsg, self->WLDlgProc( hdlg, uMsg, wParam, lParam)); } private: BOOL m_fRecursing; }; Let's walk through this class.
The
I could have had a separate
The
The
The last method is Here's a sample program that illustrates the use of this class: class SampleWLDlg : public WLDialogBox { LRESULT WLDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { HANDLE_MSG(hdlg, WM_COMMAND, OnCommand); HANDLE_MSG(hdlg, WM_SETCURSOR, OnSetCursor); } return __super::WLDlgProc(hdlg, uMsg, wParam, lParam); }; void OnCommand(HWND hdlg, int id, HWND hwndCtl, UINT codeNotify) { switch (id) { case IDCANCEL: MessageBox(hdlg, TEXT("Bye"), TEXT("Title"), MB_OK); EndDialog(hdlg, 1); break; } } BOOL OnSetCursor(HWND hdlg, HWND hwndCursor, UINT codeHitTest, UINT msg) { if (codeHitTest == HTCAPTION) { SetCursor(LoadCursor(NULL, IDC_SIZEALL)); return TRUE; } return FORWARD_WM_SETCURSOR(hdlg, hwndCursor, codeHitTest, msg, __super::WLDlgProc); } }; int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR lpCmdLine, int nShowCmd) { SampleWLDlg dlg; dlg.DoModal(hinst, MAKEINTRESOURCE(1), NULL); return 0; } 1 DIALOGEX DISCARDABLE 0, 0, 200,200 STYLE DS_SHELLFONT | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "sample" FONT 8, "MS Shell Dlg" BEGIN DEFPUSHBUTTON "&Bye",IDCANCEL,"Button",WS_TABSTOP,7,4,50,14 END
To illustrate a custom return value, I override the
Observe that in two places, we invoked
the default handler by calling
If your compiler doesn't support typedef WLDialogBox super;
and using Exercise: Does the |
Comments (2)
Comments are closed. |
I thought that DefDlgProc does not only pass message on to the dialog proc but also generates new ones like WM_INITDIALOG. What happens when these messages are sent to DefDlgProc?
And wouldn’t it be simpler to just subclass the dialog and handle the messages before they arrive at DefDlgProc?
PingBack from http://www.shugye.com/2007/11/why-do-we-even-have-the-defwindowproc-function-%e4%b8%ba%e4%bb%80%e4%b9%88%e6%88%91%e4%bb%ac%e9%9c%80%e8%a6%81defwindowproc-%e5%87%bd%e6%95%b0-48.html