tags:

views:

956

answers:

2

I have been reading the MSDN documentation on subclassing and I have been successful in handling events in a subclass

My issue is with passing messages back to the original WndProc.

As an example, if I have a window, with a sub-classed groupbox control and a button as a child of that groupbox, I want to handle the button event in the original window procedure, not the subclassed groupbox procedure.

Essentially, I want an empty subclass procedure:

LRESULT FAR PASCAL SubClassFunc(HWND hwnd,
                     UINT uMsg,
       WPARAM wParam,
       LPARAM lParam)
{
    return CallWindowProc(oldProc, hwnd, uMsg, wParam, lParam);
}

Where oldProc is:

FARPROC oldProc = (FARPROC)SetClassLong(group_box, GCL_WDPROC, (DWORD)SubCLassFunc);

And where the window and groupbox and button are:

HWND window = CreateWindowEx(
 WS_EX_WINDOWEDGE, 
 appname,
 TEXT("Subclass Test"),
 WS_VISIBLE |WS_OVERLAPPEDWINDOW,
 CW_USEDEFAULT,
 CW_USEDEFAULT,
 300,
 400,
 NULL,
 NULL,
 hInstance,
 0);

HWND group_box = CreateWindowEx(
 0,
 TEXT("BUTTON"),
 TEXT("Group Box"),
 WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
 8,
 8,
 275,
 350,
 window,
 NULL,
 hInstance,
 0);

HWND push_button = CreateWindowEx(
 0,
 TEXT("BUTTON"),
 TEXT("Push Button"),
 WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_VCENTER,
 50,
 100,
 100,
 25,
 group_box,
 (HMENU)PUSH_BUTTON,
 hInstance,
 0);

I can handle the button events in the SubClassFunc, but what I want to do is pass them back to the window WndProc. It seems that CallWindowProc isn't doing this, or I may be totally wrong in how CallWindowProc works.

+2  A: 

The button notifications are sent to the button's parent, which is the group box. Because you've subclassed the group box, your SubClassFunc receives these messages, which then passes them to the group box's original window procedure using CallWindowProc.

If you want the button notifications to go to the parent window (i.e, window in your code), you could either set the button's parent to window instead of group_box, or use PostMessage from within SubClassFunc to post the message (WM_COMMAND or WM_NOTIFY as appropriate) to window.

Also, I see that you're using SetClassLong to set the window procedure. What this does is replace the window procedure for the entire BUTTON class, but only for windows that are subsequently created. Any BUTTON windows created before calling SetClassLong will not be subclassed. You may want to consider using SetWindowLong instead, to subclass individual windows rather than the entire class.

Edit: The group box's original window procedure doesn't send WM_COMMAND messages to its parent. This is explained in Charles Petzold's Programming Windows book:

The group box, which has the BS_GROUPBOX style, is an oddity in the button class. It neither processes mouse or keyboard input, nor sends WM_COMMAND messages to its parent.

You should find that button notifications don't get through to window even if you don't subclass the group box.

I hope this helps!

ChrisN
A: 

I suspect if you remove the subclass all together the button events will still not reach the original window procedure as you expect.

Since you have an subclass procedure doing nothing more than calling CallWindowProc the window is effectively not subclasses.

My suggestion would be to use the Spy++ tool to see which window is getting the button event messages.

One of the more difficult aspects of Win32 programming is determining which window gets which message and Spy++ is invaluable when it comes to figuring out this information.

jussij