Jump to content

Trouble with DllCall and PostMessage


sosad
 Share

Go to solution Solved by sosad,

Recommended Posts

Hello guys,

about three years back I wrote a script to help me change model parameters quickly in my CAD-Software. It was neccessary to use simulated input for updating values and selecting certain parts of the model. There are several different windows that require input (including the 3D-preview which I can not target using controlsend()).

In order to get the job done I used DllCalls to post window messages to the different windows an the compiled script still works like a charm.

Recently I tried to add some new functionality to the script but the simulating input part no longer works. Even recompiling the old code won't work, while the already compile script works just fine.

I spend some time trying to find out whats wrong and managed to narrow it down to the DllCall and PostMessage e.g.:

DllCall("user32.dll", "int", "PostMessage", "HWND", $GUI_Main, "UINT", $WM_LBUTTONDOWN, "WPARAM", 0, "LPARAM", BitOR( 75 * 0x10000, BitAND(150, 0xFFFF)))

Long story short, I think the Message is posted to the target window, but not recognized as a Keyboard / Mouse event.

I've made an example to demonstrate my problem:

;change EventMode
Opt("GUIOnEventMode", 1)

;set constants myself to make sure they are correct
Static $GUI_Event_Close = -3
Static $WM_LBUTTONDOWN = 0x0201         ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms645607%28v=vs.85%29.aspx
Static $WM_LBUTTONUP = 0x0202           ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms645608%28v=vs.85%29.aspx

;create a sample GUI
Global $GUI_Main = GUICreate("PostMessage Testscript", 300, 100)
Global $GUI_Button1 = GUICtrlCreateButton("press this to initate a click", 5, 5, 290, 42)
Global $GUI_Button2 = GUICtrlCreateButton("this should be clicked automatically", 5, 53, 290, 42)

;register events
GUISetOnEvent($GUI_Event_Close, "EventHandler")
GUICtrlSetOnEvent($GUI_Button1, "EventHandler")
GUICtrlSetOnEvent($GUI_Button2, "EventHandler")

;Custom Events - uncomment these to check if Events occure
;GUIRegisterMsg($WM_LBUTTONDOWN, "CatchWindowMessage")
;GUIRegisterMsg($WM_LBUTTONUP, "CatchWindowMessage")

;show the gui
GUISetState()

;wait for input
While 1
    Sleep(250)
WEnd

;...^^
Func EventHandler()
    Switch @GUI_CtrlId
        Case $GUI_Button1
            ;Send a MouseButtonDown Event followed by ButtonUp at coords x = 150, y = 75 (relative to client area): 
            ;PostMessage    http://msdn.microsoft.com/en-us/library/windows/desktop/ms644944%28v=vs.85%29.aspx
            DllCall("user32.dll", "int", "PostMessage", "HWND", $GUI_Main, "UINT", $WM_LBUTTONDOWN, "WPARAM", 0, "LPARAM", BitOR( 75 * 0x10000, BitAND(150, 0xFFFF)))
            Sleep(50)
            DllCall("user32.dll", "int", "PostMessage", "HWND", $GUI_Main, "UINT", $WM_LBUTTONUP, "WPARAM", 0, "LPARAM", BitOR( 75 * 0x10000, BitAND(150, 0xFFFF)))
        Case $GUI_Button2
            MsgBox(0,"PostMessage Testscript","Button 2 was clicked")
        Case $GUI_Event_Close
            Exit
    EndSwitch
EndFunc

;just to log incomming window events
Func CatchWindowMessage($a_HWnD, $a_MsgID, $a_wParam, $a_lParam)
    ConsoleWrite("Event occured:" & @CRLF & "MsgID: " & $a_MsgID & @CRLF & "wParam: " & $a_wParam & @CRLF & "lParam:    " & $a_lParam & @CRLF & @CRLF)
EndFunc

In this example, if the first button is clicked I would expect the second button to be clicked automatically, too. However this is not the case (neither in x64 nor in x86 mode). Still, the message is posted, which can be prooven by uncommenting the custom events.

I'm totally lost on this one, can anybody tell me what's going wrong here?

I'm running the latest version of autoit on a win7 64bit machine.

Thanks in advance

Link to comment
Share on other sites

  • Solution

Have you tried using the standard _WinAPI_PostMessage() UDF?

 

Yes, sadly the result doesn't change.

I do believe my DllCall is correct, since the event is recognized if i register it. However since those are standard events they should be handled by default (by windows itself) or at least they were in the past.

The code worked just fine when I compiled it 3 years ago... I'm lost.

Edit:

No I'm not lost, I'm stupid. Turns Out I need to use the handle of the control I want to postMessages to, not the parent window. I should have known that.

In case anyone is interested, the example above works correctly if recoded like this:

;change EventMode
Opt("GUIOnEventMode", 1)

;set constants myself to make sure they are correct
Static $GUI_Event_Close = -3
Static $WM_LBUTTONDOWN = 0x0201         ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms645607%28v=vs.85%29.aspx
Static $WM_LBUTTONUP = 0x0202           ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms645608%28v=vs.85%29.aspx

;create a sample GUI
Global $GUI_Main = GUICreate("PostMessage Testscript", 300, 100)
Global $GUI_Button1 = GUICtrlCreateButton("press this to initate a click", 5, 5, 290, 42)
Global $GUI_Button2 = GUICtrlCreateButton("this should be clicked automatically", 5, 53, 290, 42)

;register events
GUISetOnEvent($GUI_Event_Close, "EventHandler")
GUICtrlSetOnEvent($GUI_Button1, "EventHandler")
GUICtrlSetOnEvent($GUI_Button2, "EventHandler")

;Custom Events - uncomment these to check if Events occure
GUIRegisterMsg($WM_LBUTTONDOWN, "CatchWindowMessage")
GUIRegisterMsg($WM_LBUTTONUP, "CatchWindowMessage")

;show the gui
GUISetState()

;wait for input
While 1
    Sleep(250)
WEnd

;...^^
Func EventHandler()
    Switch @GUI_CtrlId
        Case $GUI_Button1
            ;Send a MouseButtonDown Event followed by ButtonUp at coords x = 150, y = 75 (relative to client area):
            ;PostMessage    http://msdn.microsoft.com/en-us/library/windows/desktop/ms644944%28v=vs.85%29.aspx
            DllCall("user32.dll", "int", "PostMessage", "HWND", GUICtrlGetHandle($GUI_Button2), "UINT", $WM_LBUTTONDOWN, "WPARAM", 1, "LPARAM", BitOR( 25 * 0x10000, BitAND(150, 0xFFFF)))
            Sleep(50)
            DllCall("user32.dll", "int", "PostMessage", "HWND", GUICtrlGetHandle($GUI_Button2), "UINT", $WM_LBUTTONUP, "WPARAM", 0, "LPARAM", BitOR( 25 * 0x10000, BitAND(150, 0xFFFF)))
        Case $GUI_Button2
            MsgBox(0,"PostMessage Testscript","Button 2 was clicked")
        Case $GUI_Event_Close
            Exit
    EndSwitch
EndFunc

;just to log incomming window events
Func CatchWindowMessage($a_HWnD, $a_MsgID, $a_wParam, $a_lParam)
    ConsoleWrite("Event occured:" & @CRLF & "MsgID: " & $a_MsgID & @CRLF & "wParam: " & $a_wParam & @CRLF & "lParam:    " & $a_lParam & @CRLF & @CRLF)
EndFunc

thx anyway :)

Edited by sosad
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...