WndProc for buttons

Started by
6 comments, last by Koen 21 years, 2 months ago
I need to know the status of the mouse at all times (movement, mousebutton pressed, released,...), even when it''s over a button. This means I''ve changed the window procedure for the buttons from the default (as specified in the "button" window class) to my own WndProc. When WndProc gets a message it does all necessary processing, and then passes the message on to the old window procedure (the one from the "button" class). Unfortunatly this causes the button to only generate a WM_COMMAND message when it''s double-clicked. I don''t see how this is possible: eventually all the messages get passed on to the default-button-handler, so I would expect a single click to be enough (as it should be). Does anyone know what I might be doing wrong? Thanks.
Advertisement
what technique are you using to use your own wndproc for the button window? the normal technique is called subclassing and involves replacing the window''s wndproc entry via a setwindowlong call with your own wndproc. but before you do that you save off the current wndproc to a variable of your own using getwindowlong. then instead of calling defwindowproc at the bottom of your wndproc you call callwindowproc using the previously saved off wndproc address in the call. also make sure that you do very little returns from your own wndproc. there''s actually very little reason to have any returns ever in a wndproc. you really only need them if you want to completely override the default msg processing.

just to be clear, by "your own wndproc" i mean the one you wrote specifically for button window msg processing, not a generic one that you might use for a main window.
I am saving the standard button wndproc to a variable and I am calling that one as the default (CallWindowProc(...)) and after processing other messages.
And I'm actually passing messages to objects (UIWindow, UIButton,... all (indirectly) derived from UIComponent). Example:
A wM_SIZE message enters my own (generic) wndproc. I look for the UIComponent that has the correct hWnd and call it's processWM_SIZE(LPARAM,WPARAM) method. Every processXX_XYZ() is declared at the level of UIComponent (virtual, offcourse). Most of these functions are implemented using processDefault(). This is also a virtual function that calls DefWindowProc or the "previously saved procedure", depending on the type of the component.
WM_SIZE gets specific processing in UIWindow. UIWindow:: processWM_SIZE generates an event (in this case UIWindowListener::windowRestored(), UIWindowListener::windowMaximized(),...).

Now, the example I'm having a problem with. In the generic wndproc there is the next piece of code:
if(messg==WM_LBUTTONDOWN)	{	return(c->processWM_LBUTTONDOWN(wParam,lParam));	//c is of type UIComponent* ,so this is a polymorphic call}  

I've put a breakpoint inside this if-construction. When I press the button:
LRESULT CALLBACK UIComponent:: processWM_LBUTTONDOWN(WPARAM wParam, LPARAM lParam)	{	//	...	//	unimportant app related stuff	//	...	return(processDefault(WM_LBUTTONDOWN,wParam,lParam));}  

and then (UIChildControl is the superclass for all controls that have their own
message handler (buttons, editcontrols,...):
LRESULT CALLBACK UIChildControl:: processDefault(UINT messg,WPARAM wParam,LPARAM lParam)	{	return CallWindowProc(getOldWindowProc(),getHWND(),messg,wParam,lParam);}	  

and finally:
WNDPROC UIChildControl::getOldWindowProc()	{	return _old;}  

_old is set right after CreateWindow executes:
void UIChildControl::setOldWindowProc()	{	_old=(WNDPROC) SetWindowLong (getHWND(), GWL_WNDPROC,(LPARAM) WndProc);}  

Releasing the mousebutton is almost the same (WM_LBUTTONDOWN -> WM_LBUTTONUP). But no WM_COMMAND is being sent.

[edited by - Koen on January 24, 2003 6:33:51 AM]
ughhh. ok, all that looks fine so i can only think of one obvious question to ask.

once the button has been subclassed, are ALL of the msgs that go into the subclassed wndproc ending up as CallWindowProc calls? everyone, not just the ones that require special processing? it sounded like this was the case from your description, given your use of a virtualized processDefault function, but i couldn''t tell for sure from your code snippets.

the only reason i ask is i guess it''s possible for something, another msg maybe, to be used by the button''s system class''s wndproc when determining whether to send out a WM_COMMAND / BN_CLICK notification msg. maybe a WM_TIMER msg that''s used for single click/double click differentiation. if the WM_TIMER does not get passed along to the system class''s wndproc then the button would still think it''s in "possible double click" mode. so a subsequent WM_LBUTTONUP would not trigger it to send a WM_COMMAND / BN_CLICK notification.

anyway, just a stab in the dark. i really can''t think of anything else.
Yeah I checked that to.
Messages that don't get processed by WndProc automatically go to c->processDefault(). For a childcontrol this means CallWindowProc(_old,...).
What bothers me is that doubleclicking does generate a WM_COMMAND. How is that possible? Another problem is that the buttons and editcontrols don't seem to send mouse messages (WM_MOUSEMOVE, WM_LBUTTONDOWN, ...) to WndProc.

[edited by - Koen on January 24, 2003 10:09:35 AM]
have you looked at this using a msg spy utility, like spy++? you should be able to do a process spy which will get you all msgs and also indicate what window''s receiving what.
No, I haven''t. Actually, I don''t even know spy++. But I am certainly going to give it a try. Thanks.
Ok, now i feel really dumb. WM_MOUSEMOVE and all other mouse-related messages came through just fine, I just forgot to register the listeners (java-style).
But that still doesn''t explain why WM_COMMAND only gets sent when I doubleclick a button.

This topic is closed to new replies.

Advertisement