[solved] OnMessage() monitoring in Class

Get help with using AutoHotkey and its commands and hotkeys
User avatar
Learning one
Posts: 122
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

[solved] OnMessage() monitoring in Class

02 Apr 2015, 19:07

Let's say a have a class and I want to monitor WM_LBUTTONDOWN message. It can be done like this (run the script, click&drag gui please and it will update x,y coords info):

Code: [Select all] [Expand] [Download] (Script.ahk)GeSHi © Codebox Plus

It's not the best way, but never mind... What I would like to know is how to include that WM_LBUTTONDOWN message monitoring in the class itself? Below is a not working code, but it will give you idea of what I would like to do.

Code: [Select all] [Expand] [Download] (Script.ahk)GeSHi © Codebox Plus

I would also like to have some check like
if (A_Gui = hwnd of any window which belongs to object derived from TestClass)
--> do stuff...
else
--> this is a window which doesn't belong to object derived from TestClass - do nothing, don't interfere

I also tried to use WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) as a method instead of just WM_LBUTTONDOWN() (no params) but I can't register it via OnMessage() because it has 5 params; 4 + one hidden; "this"... and the limit for OnMessage is 4. My plan was to compare 4. parameter; hwnd with A_Gui and if they match, do stuff... - or is this nonsense - they will always match in WM_LBUTTONDOWN case?

Thanks in advance.
Last edited by Learning one on 08 Apr 2015, 15:06, edited 2 times in total.
lexikos
Posts: 5943
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: OnMessage() monitoring in Class

02 Apr 2015, 19:37

Pass this.WM_LBUTTONDOWN.Bind(this) to OnMessage. Bind requires v1.1.20+.

but I can't register it via OnMessage() because it has 5 params
Even if you could register it, OnMessage still wouldn't pass the this parameter. So instead of passing the method, you pass a bound function which (when called) passes this for you.
User avatar
Learning one
Posts: 122
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

Re: OnMessage() monitoring in Class

03 Apr 2015, 04:34

Thank you Lexikos! I passed this.WM_LBUTTONDOWN.Bind(this) to OnMessage().
I also replaced Tooltipwith MsgBox, uncommented ;Test2 := new TestClass("Test2", 450, 400), and added 3. line: Test3 := new TestClass("Test3", 600, 400) so code now looks like this;

Code: [Select all] [Expand] [Download] (Script.ahk)GeSHi © Codebox Plus

Now, when I derived 3 objects from TextClass, if I click & drag any single Gui (which "belongs" to object derived from TextClass), MsgBox will show 3 times. At first, I was expecting it will show only once...
Should I rewrite WM_LBUTTONDOWN() method and "filter" that like this:

Code: [Select all] [Download] (Script.ahk)GeSHi © Codebox Plus

;class TestClass {
WM_LBUTTONDOWN() {
PostMessage, 0xA1, 2
KeyWait, LButton
if (A_Gui = this.hwnd) {
WinGetPos, x,y,,, % "ahk_id " this.hwnd
GuiControl, % this.hwnd ":", % this.hPos, % x ", " y
MsgBox,,, % this.Name, 0.5
}
}
;}
Or like this:

Code: [Select all] [Download] (Script.ahk)GeSHi © Codebox Plus

;class TestClass {
WM_LBUTTONDOWN(wParam, lParam, msg, hwnd) {
PostMessage, 0xA1, 2
KeyWait, LButton
if (hwnd = this.hwnd) {
WinGetPos, x,y,,, % "ahk_id " this.hwnd
GuiControl, % this.hwnd ":", % this.hPos, % x ", " y
MsgBox,,, % this.Name, 0.5
}
}
;}
Which one is OK? Do you suggest some other approach? Thank you.
lexikos
Posts: 5943
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: OnMessage() monitoring in Class

03 Apr 2015, 21:43

Neither!

You called OnMessage(0x201, fn), which means "call fn whenever any window belonging to the script receives the message 0x201". If you call it three times with three different function objects, all three will be called whenever any window receives that message.

You do not want to post the 0xA1 message three times every time the button is clicked, do you?

If the WM_LBUTTONDOWN method is called for a particular GUI, presumably you only want to handle messages received by that GUI. So you should return immediately if hwnd != this.hwnd, before doing anything else. If you've handled the message, you should return an integer to let AutoHotkey know it doesn't need to call any other handlers.

The method will be called once for each GUI, and each one will have to check if it is the intended recipient. If there is usually only one GUI this is fine, but if there can be many it could be very inefficient. An alternative would be to register the message handler only once for that class (not for each instance), and have it resolve the GUI object by HWND.

Note that even if A_Gui is a HWND, A_Gui and the HWND parameter can differ if you clicked on a control which accepts mouse input.
User avatar
Learning one
Posts: 122
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

Re: OnMessage() monitoring in Class

05 Apr 2015, 21:29

Lexikos, thanks for your answer and sorry for my late reply. I'll have more more than one derived object and therefore more than one GUI too, so I registred message handler only once for that class, as you suggested. Is this code OK now? If not, could you please show me how would you do it - I'm running out of ideas what to do to do it right.

Code: [Select all] [Expand] [Download] (Script.ahk)GeSHi © Codebox Plus

just me
Posts: 5397
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: OnMessage() monitoring in Class

06 Apr 2015, 03:08

What I would do in this case:

Code: [Select all] [Expand] [Download] GeSHi © Codebox Plus

lexikos
Posts: 5943
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: OnMessage() monitoring in Class

06 Apr 2015, 21:22

Both seem adequate.

Having the GUI close itself when the script releases its reference to the GUI mightn't be appropriate. You could instead store the GUI object (as a normal, counted reference) in the array when the GUI is shown and remove it when the GUI is closed, but Destroy it only when the last reference is released (assuming the object provides some way to show the GUI again). So long as the GUI is visible, the user can interact with it and cause the WM_LBUTTONDOWN method to be called, even if there are no external references to the object. If you use this model, the circular reference isn't a problem as you want the GUI object to remain alive while the GUI is visible.

If you're storing the GUI objects in an array, you may as well use array[hwnd] := object to facilitate mapping HWND to object. Just be sure to use .Delete(hwnd) (v1.1.21+) or .Remove(hwnd, "") and not .Remove(hwnd).
User avatar
Learning one
Posts: 122
Joined: 04 Oct 2013, 13:59
Location: Croatia
Contact:

Re: [solved] OnMessage() monitoring in Class

08 Apr 2015, 16:12

Just me, Lexikos, thank you for your help! :)
I think I'll end up with something like this;

Code: [Select all] [Expand] [Download] (Script.ahk)GeSHi © Codebox Plus


[solved]

Return to “Ask For Help”

Who is online

Users browsing this forum: lha34599 and 24 guests