Sign in to follow this  
Followers 0
Clark

I'm confused by WM_NOTIFY

3 posts in this topic

Hi all

I suspect I am not the only AutoIT beginner who is confused by how WM_NOTIFY works.

I've reviewed some of the code examples on the forum, checked out the MSDN entry here http://msdn.microsoft.com/en-us/library/windows/desktop/bb775583(v=vs.85).aspx , read a further MSDN article on the use of WM_NOTIFY here http://blogs.msdn.com/b/oldnewthing/archive/2009/08/21/9877791.aspx , but still am not getting it, except (perhaps) at a conceptual level.

So, at a conceptual level I think what is happening is that a mouse click (for example) will update an in memory array structure called NMHDR with the handle to the window it was clicked in, the control id of the window it was clicked in, and the notification code which I assume will tell me whether right click, left click, double-click, etc.

Back to AutoIT, in order to query the NMHDR array we create a user defined function using GUIRegisterMSG. What I understand this to mean is that when Windows sends a message via WM_NOTIFY, the user defined function will be called. Is that right?

Even if I have everything above correct, I still don't understand most of the code I see on this forum as to how it works.

Let me post a relatively random sample I pulled from here:

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
Local $iIDFrom, $iCode, $tNMHDR, $tInfo

$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
$iCode = DllStructGetData($tNMHDR, "Code")

Switch $iIDFrom
Case $listview
Switch $iCode
Case $NM_CLICK, $NM_RCLICK
$tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam)

If DllStructGetData($tInfo, "Item") > -1 Then
_GUICtrlMenu_TrackPopupMenu($hMenu, $GUI)
EndIf
EndSwitch
EndSwitch

Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY

The first thing I don't understand is why the function has so many calling parameters. According to MSDN WM_NOTIFY only takes two parameters - the control id of the calling control, and a pointer to NMHDR.

Secondly, what are the various structures that are being referenced in the three DLLStructCreate calls? They appear to be related to NMHDR but I'm not understanding the finer detail here.

The function then goes on to deal with clicks in a listview only, and then is looking for a left mouse click or right mouse click (right?). The next two functions I don't get at all. Another DLLStructCreate which allows a struct read to ensure that the user has clicked on a menu subitem?

The function then returns $GUI_RUNDEFMSG, which I don't see defined or updated anywhere in either the function or the overarching program.

--------------

So, am I on the right track here, or am I way off beam?

I would like to understand this a lot better so if someone could shed some detailed and clear instruction it would be very much appreciated.

TIA

Clark

Share this post


Link to post
Share on other sites



I'm no expert on any of this so take this with that understanding.

First, the 4 parameters are used in this function because GUIRegisterMsg sends up to 4 parameters to a function when one of the Windows messages are received/detected. The first one is the handle of the window that sent the message, the second is the message it sent, the third and fourth are Windows message specific and varies between the different messages.

Then, it's creating a struct to handle the message pointer referenced by the lparam, the $tagNMHDR is a string defined elsewhere in the UDF, that tells the struct what to expect for values in each position. It splits those values off from the struct and puts them into variables in the lines below it.

$GUI_RUNDEFMSG tells the function to return the Windows message information back to the script rather than discarding it and not notifying the window that the message was sent in the first place.

From the help file:

!!! If you want AutoIt to run its internal handler for a message, return the variable $GUI_RUNDEFMSG (in GUIConstantsEx.au3) from the function (see also examples) !!!

I.e. if you want to return earlier than the user function ends and also proceed the AutoIt internal message handler.

1 person likes this

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

Thanks for that Brewman

I didn't think to look in the include files for references to the structures. I found $tagNMHDR but not $tNMHDR - I will keep looking.

I'm still not getting the program flow though. If my understanding as written in my first post is correct, surely the following code would write to the console when I click the mouse in the main window?

#include 
#include 
#include 
#include 

;Global Enum $idOpen = 1000, $idSave, $idInfo

Global $GUI

_Main()

Func _Main()
; Create GUI
$GUI = GUICreate("Menu", 400, 300)

; Register message handlers
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
GUISetState()

; Loop until user exits
Do
Until GUIGetMsg() = $GUI_EVENT_CLOSE
EndFunc ;==>_Main

Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
Local $iIDFrom, $iCode, $tNMHDR, $tInfo
$tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
$iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
$iCode = DllStructGetData($tNMHDR, "Code")
ConsoleWrite("iIDFrom = " & $iIDFrom & @CRLF)
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_NOTIFY

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0