Pseudo-subclassing: EventHWnd() ?

Windows specific forum
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Pseudo-subclassing: EventHWnd() ?

Post by mesozorn »

I notice that after calling say Event=WaitWindowEvent(), under Windows in this instance Event would be filled with the pertinent event message/uMsg (such as #WM_Keydown or whatever) and values for EventwParam() and EventlParam() are also filled and returned (yes, I know these aren't supported in the documentation but they work and are used in many examples). These are of course three of the four arguments or values returned by a standard WindowProc for any control. The fourth one being hWnd.

My question is, is there any way to extract the equivalent of EventHWnd() following on a WaitWindowEvent() ? EventGadget() only works on events that generate type #PB_Event_Gadget, but if the event is something like #WM_Mousemove, or the control was created using CreateWindow_() instead of a native PB command, then EventGadget() won't be useful.

Is there any way at all to get the hWnd of the control that generated the event under these circumstances, other than actual full subclassing?

Thanks...
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Pseudo-subclassing: EventHWnd() ?

Post by netmaestro »

For a toplevel window your process owns, EventWindow() will give the window number and WindowID on that will give the hwnd. For gadgets created with CreateWindowEx_() the hMenu value you supplied at creation will be returned by EventGadget().
BERESHEIT
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: Pseudo-subclassing: EventHWnd() ?

Post by mesozorn »

Hmm.. what about for a gadget created with native PB commands, but an event which does not produce #PB_Event_Gadget? For example the event #WM_Keydown in association with a StringGadget? Or any other such similar examples? I could get the Message, wParam and lParam, but what about the hWnd? EventGadget() would not be filled in this case at the juncture that #WM_Keydown occurred. Could the Handle be captured directly in such cases?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8452
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: Pseudo-subclassing: EventHWnd() ?

Post by netmaestro »

EventGadget() would not be filled in this case at the juncture that #WM_Keydown occurred
If a stringgadget receives a wm_keydown message it will be found in the event loop and EventGadget() will return the #gadget. But if you want to do anything serious at all, a subclass is all-encompassing and really quite simple to implement. I don't understand the concept of trying to avoid it.
BERESHEIT
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: Pseudo-subclassing: EventHWnd() ?

Post by mesozorn »

Oh I actually use subclassing quite a bit and generally have no desire to avoid it. However there are some specific situations where I want to affect the behaviour of a broad set of existing gadgets without going back and subclassing each and every one of them. In which case this alternate approach comes in handy.

I've been testing this and while events like #WM_Keydown do work as mentioned (to my surprise), some others like #WM_Mousemove aren't so identical. If for example I subclass a ButtonGadget and capture the #WM_MOUSEMOVE event/message within it, it successfully activates whenever I move the mouse over the button. But if I try to capture it using WaitWindowEvent(), it doesn't work until after the first time I've clicked on the button to activate it. I'll post example code shortly to illustrate.

I do understand the value and usefulness of subclassing, but I also know there are times when I prefer to circumvent it and take a different approach.
mesozorn
Enthusiast
Enthusiast
Posts: 171
Joined: Fri Feb 20, 2009 2:23 am

Re: Pseudo-subclassing: EventHWnd() ?

Post by mesozorn »

Okay here are the examples. This first one, the subclassing version, works properly:

Code: Select all

 
Global oldproc
 Procedure.i ButtonMouseMove(hWnd, uMsg, wParam, lParam)
    Select uMsg
      Case #WM_MOUSEMOVE
        Debug "Button mousemove"
    EndSelect
    ProcedureReturn CallWindowProc_(oldproc, hWnd, uMsg, wParam, lParam)
 EndProcedure
 
 If OpenWindow(0, 0, 0, 500, 500, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(1, 100,  100, 50, 30, "Hello")
    oldproc = SetWindowLong_(GadgetID(1), #GWL_WNDPROC, @buttonmousemove())
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 EndIf
However this version below doesn't function properly, because EventGadget() is only filled when the button is actually clicked, not when #WM_Mousemove occurs:

Code: Select all

   If OpenWindow(0, 0, 0, 500, 500, "", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ButtonGadget(1, 100,  100, 50, 30, "Hello")
    Repeat 
    e = WaitWindowEvent()
    If e=#WM_MOUSEMOVE And IsGadget(EventGadget()) And EventGadget()=1
      Debug GadgetID(EventGadget())
    EndIf
    Until e = #PB_Event_CloseWindow
  EndIf
Is there any way to capture the GadgetID/hWnd of the Button when #WM_Mousemove occurs, without subclassing? Again, WaitwindowEvent() itself returns the message, wParam and lParam values, but not hWnd. And EventGadget() does not get filled by some Windows messages like this one. I fully recognize the value of the subclassing approach, but is there any way conceivable that the other approach can be feasibly used if desired?

By the way, I know that for this specific example there are workarounds like using WindowFromPoint_() etc, but I'm looking for an all-around solution that will allow me to get the equivalent of the non-existent EventHWnd() for absolutely any MSG returned by WaitWindowEvent(), and not dependent on the specific type of message.

Thanks..
Post Reply