Take the 2-minute tour ×

When a standard window control (e.g. an "EDIT" control) is created, its WNDPROC is defined as part of the window class (i.e. "EDIT" has a specific WNDPROC that is designed to make the window display & behave as an edit-control).

MFC allows you to interact with such controls via their wrapper classes, such as a CEdit wrappers the specialized messages for an "EDIT" window control.

MFC further allows you to bind an instance of an "EDIT" window to a C++ subclass of CEdit, say a CMyEdit, where you can override inherited virtual functions of CEdit and CWnd, and you can define a message table to gain access / override messages sent to the window instance itself.

There is CWnd::Default(), which calls this->DefWndProc with the current message arguments. This appears to lookup the WNDPROC for the HWND it is associated with. So is this the correct answer: call DefWndProc() (or equally, Default()), which will hand it off to the WNDPROC of the windows control?

Obviously, this is different than other message table handlers which can return FALSE to indicate that they didn't handle the message, and MFC will automatically route the message up the class inheritance hierarchy to the next message handler for this message, or, I assume, to Default() to be handled by the native WNDPROC?

If I define an arbitrary message handler, say for WM_SETTEXT, what is the correct way to pass this message on to the "EDIT" WNDPROC?

I'd also love to know if there is a way to pass the message up to a superclass (C++ class hierarchy) for handling? Many OnXXX style handlers do have a way to do so, but is there a mechanism that works for ON_MESSAGE handlers?

class CDynamicMenuControlEdit : public CEdit  
    LRESULT OnSetText(WPARAM wParam, LPARAM lParam);

BEGIN_MESSAGE_MAP(CDynamicMenuControlEdit, CEdit)

LRESULT CDynamicMenuControlEdit::OnSetText(
    WPARAM wParam,          // not used; must be zero
    LPARAM lParam           // window-text string (LPCTSTR)
    if (m_bHasFocus)
        // do normal thing 
        // !!! THIS IS MY QUESTION: IS THIS CALLING EDIT's WNDPROC, or ::DefWinProc()? !!!
        return DefWindowProc(WM_SETTEXT, wParam, lParam);
share|improve this question
Something tells me that we need @RaymondChen in this question. –  Nik Bougalis Mar 6 '13 at 17:26
Or @Joseph M. Newcomer –  Mordachai Mar 6 '13 at 18:35
add comment

2 Answers

You're doing it right. CWnd::DefWindowProc() uses the WINDOWPROC you subclassed from and will call the EDIT window's window procedure.

share|improve this answer
How would it be different in this particular instance for him to call Default()? –  Nik Bougalis Mar 6 '13 at 17:25
Looking at wincore.cpp, Default and DefWindowProc() are identical in my example, because I pass the same args to DefWindowProc() as Default() would, and default calls DefWindowProc() so exactly the same results. –  Mordachai Mar 6 '13 at 18:28
I'm more confused about the distinction between ON_MESSAGE being a message sink vs. other ON_WM_xxx which have a BOOL result to indicate if your handler handled the message or if it should propagate up the message table chain. Or how one would even accomplish that for my example (i.e. if my subclass wants to punt up the message handler chain- how?). And verify that my example calls the WNDPROC that was there prior to MFC's WNDPROC subclassing (hooking). –  Mordachai Mar 6 '13 at 18:28
I'm not sure if I understand your question. In a thread, you can only subclass a window via MFC once. So when a message comes in to a subclassed window, it tries to find a MFC message handler. If it finds one, it calls it. If it doesn't find one, it calls the default window procedure from which MFC had subclassed from. Generally, if you want to punt up the MFC chain, you call the baseclass directly--CSomeBaseClass::OnSetText(wParam, lParam). –  Joe Willcoxson Mar 7 '13 at 15:32
add comment

Calling Default() will cause the "normal" processing that would have happened in response to a message to occur. I'm not entirely clear on what you are trying to achieve, but it seems to me that calling Default() is what you want to do.

If you look at a lot of the handlers from Windows messages in the CWnd handlers (and handlers from classes derived from CWnd such as CEdit) you will see that they call Default().

Word to the wise, that Default() will actually use whatever parameters the original message had - you cannot change them.

share|improve this answer
At an abstract/general level, yes Default() will do the "normal" thing. It sounds like that means that the WNDPROC that MFC hooked will be called, as opposed to ::DefWindowProc being called (we want window class "EDIT"'s WNDPROC to be called, not the global generic default window proc!) However, I'd like confirmation on that, and clarification on what would be the right way to cause the next message handler in the MFC message table chain to be called if my ON_MESSAGE handler wants to punt? –  Mordachai Mar 6 '13 at 18:31
add comment

Your Answer


