jaberwacky Posted September 13, 2014 Share Posted September 13, 2014 (edited) Is there a way to register my script to receive messages for when a window is moving or has been moved? I've used _WinAPI_SetWindowsHookEx and all of the various options in many different combos. Been at this for a couple of days now. I've searched this forum and the net too. Seems like I can only do this for specific programs that I specify? If that is the case, then I guess I can register and unregister dynamically. Any ideas? Edit: guess I should state my intent. I want to make a Snap feature that works in the middle of where monitors meet if there are more than one. I know I can use the KB shortcuts and will if that's my only choice. Here my code so far: expandcollapse popup#AutoIt3Wrapper_Run_AU3Check=n #AutoIt3Wrapper_AU3Check_Parameters=-w 1 -w 2 -w 3 -w 4 -w 6 -w 7 -d -q #include <WinAPI.au3> #include <Array.au3> #include <WindowsConstants.au3> Const $mouse_proc_callback = DllCallbackRegister(model_ll_mouse_proc, "long", "int;wparam;lparam") Const $hook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($mouse_proc_callback), _WinAPI_GetModuleHandle(0)) ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hook = ' & $hook & @CRLF) ;### Debug Console Const $half_desktop_width = @DesktopWidth / 2 Const $range = 20 Global $window_focus Global $left_snap = False Global $right_snap = False Global $active = False Do Sleep(100) Until False Volatile Func model_ll_mouse_proc($code, $w_param, $l_param) Switch $code >= 0 Case True Switch $w_param Case $wm_mousemove Switch $active Case True With DllStructCreate($tagPOINT, $l_param) Select Case (.X >= @DesktopWidth - $range) And (.X <= @DesktopWidth) ;ConsoleWrite("Left: " & .X & @CRLF) $left_snap = True $right_snap = False Case (.X >= @DesktopWidth) And (.X <= @DesktopWidth + $range) ;ConsoleWrite("Right: " & .X & @CRLF) $right_snap = True $left_snap = False Case Else $left_snap = False $right_snap = False EndSelect EndWith EndSwitch Case $wm_lbuttondown $window_focus = _WinAPI_GetForegroundWindow() If GetRealParent($window_focus) Then EndIf $active = True Case $wm_lbuttonup Select Case $left_snap WinMove($window_focus, "", $half_desktop_width, 0, $half_desktop_width, 1080) $left_snap = False $right_snap = False Case $right_snap WinMove($window_focus, "", @DesktopWidth, $half_desktop_width, $half_desktop_width, 1024) $left_snap = False $right_snap = False EndSelect $active = False $window_focus = Null EndSwitch EndSwitch Return _WinAPI_CallNextHookEx($hook, $code, $w_param, $l_param) EndFunc Func GetRealParent(Const $hwnd) ; http://stackoverflow.com/questions/16872126/the-correct-way-of-getting-the-parent-window Local Const $hParent = _WinAPI_GetAncestor($hwnd, $GA_PARENT) If (Not $hParent) Or ($hParent = _WinAPI_GetDesktopWindow()) Then Return True EndIf Return False EndFunc Here is the script I used to test setwindowshookex function: #include <WinAPI.au3> Const $wnd_proc_callback = DllCallbackRegister(_call_wnd_proc, "long", "int;wparam;lparam") Const $hook = _WinAPI_SetWindowsHookEx($WH_CALLWNDPROC, DllCallbackGetPtr($wnd_proc_callback), _WinAPI_GetModuleHandle(0)) Do Sleep(100) Until False Func _call_wnd_proc($code, $w_param, $l_param) ConsoleWrite("Heeeeeyyyyy" & @CRLF) Return _WinAPI_CallNextHookEx($hook, $code, $w_param, $l_param) EndFunc Edited September 13, 2014 by jaberwacky Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
jaberwacky Posted September 13, 2014 Author Share Posted September 13, 2014 (edited) I found this thread which does what I want but only for specific windows! If anyone still knows how to make this happen for all present windows I would be much obliged. '?do=embed' frameborder='0' data-embedContent>> Here is the stripped down code from that thread that does what I want: expandcollapse popup#include <WinAPI.au3> Global Const $WM_USER = 0x400 Global Const $WM_MOVE = 0x0003 Global Const $UM_ADDMESSAGE = $WM_USER + 0x100 Global Const $hDll_hook = DllOpen("hook.dll") ; helper dll Global Const $user32 = DllOpen("User32.dll") Global Const $hWndLocal = GUICreate("") ; Needed to receive messages Run("Calc") WinWaitActive("Calculator") Global Const $hWndTarget = WinGetHandle("Calculator") Global Const $iThreadIdTarget = _GetWindowThreadProcessId($hWndTarget) DllCall($hDll_hook, "int", "InstallFilterDLL", "long", $WH_CALLWNDPROC, "long", $iThreadIdTarget, "hwnd", $hWndTarget) ; 0 = Ok DllCall($user32, "int", "SendMessage", "hwnd", $hWndTarget, "int", $UM_ADDMESSAGE, "int", $WM_MOVE, "hwnd", $hWndLocal) GUIRegisterMsg($WM_MOVE, "_Filter") ; Keep running while target exists While WinExists($hWndTarget) Sleep(250) WEnd DllCall($hDll_hook, "int", "UnInstallFilterDLL", "long", $iThreadIdTarget, "hwnd", $hWndTarget, "hwnd", $hWndLocal) ; 0 = ok DllClose($hDll_hook) DllClose($user32) Func _Filter(Const $hWndGUI, Const $MsgID, Const $WParam, Const $LParam) Switch $MsgID Case $WM_MOVE ConsoleWrite("MOVED" & @CRLF) EndSwitch EndFunc Func _GetWindowThreadProcessId(Const $hWnd) Local Const $aRval = DllCall($user32, "dword", "GetWindowThreadProcessId", "hwnd", $hWnd, "dword*", 0)[0] If @error Then Return SetError(@error, @extended, False) EndIf Return $aRval EndFunc Edited September 13, 2014 by jaberwacky Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
jaberwacky Posted September 13, 2014 Author Share Posted September 13, 2014 (edited) I found a solution which works well enough for me! expandcollapse popup#AutoIt3Wrapper_Run_AU3Check=n #AutoIt3Wrapper_AU3Check_Parameters=-w 1 -w 2 -w 3 -w 4 -w 6 -w 7 -d -q #include <WinAPI.au3> #include <Array.au3> #include <WindowsConstants.au3> Global Const $UM_ADDMESSAGE = $WM_USER + 0x100 Global Const $h_dll_hook = DllOpen("hook.dll") ; helper dll Global Const $user32 = DllOpen("User32.dll") Global Const $h_wnd_local = GUICreate("") ; Needed to receive messages Const $mouse_proc_callback = DllCallbackRegister(model_ll_mouse_proc, "long", "int;wparam;lparam") Const $hook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($mouse_proc_callback), _WinAPI_GetModuleHandle(0)) Const $half_desktop_width = @DesktopWidth / 2 Const $range = 20 Global $id_target Global $mouse_pos Global $window_focus Global $left_snap = False Global $right_snap = False OnAutoItExitRegister(_cleanup) Do Sleep(100) Until False Volatile Func model_ll_mouse_proc($code, $w_param, $l_param) Switch $code >= 0 Case True Switch $w_param Case $wm_mousemove $mouse_pos = DllStructCreate($tagPOINT, $l_param) $mouse_pos.X = Abs($mouse_pos.X) $mouse_pos.Y = Abs($mouse_pos.Y) Case $wm_lbuttondown $window_focus = _WinAPI_GetForegroundWindow() If GetRealParent($window_focus) Then $id_target = _register_message($window_focus) EndIf Case $wm_lbuttonup Select Case $left_snap WinMove($window_focus, "", $half_desktop_width, 0, $half_desktop_width, 1080) $left_snap = False $right_snap = False Case $right_snap WinMove($window_focus, "", @DesktopWidth, $half_desktop_width, $half_desktop_width, 1024) $left_snap = False $right_snap = False EndSelect $window_focus = Null EndSwitch EndSwitch Return _WinAPI_CallNextHookEx($hook, $code, $w_param, $l_param) EndFunc Func _filter(Const $h_wnd_gui, Const $msg_id, Const $w_param, Const $l_param) Switch $msg_id Case $WM_MOVE ConsoleWrite("MOVED" & @CRLF) _uninstall_filter($id_target, $window_focus) Case $WM_MOVING ConsoleWrite("MOVING" & @CRLF) If ($mouse_pos.X >= @DesktopWidth - $range) And ($mouse_pos.X <= @DesktopWidth) Then $left_snap = True $right_snap = False ElseIf($mouse_pos.X >= @DesktopWidth) And ($mouse_pos.X <= @DesktopWidth + $range) Then $right_snap = True $left_snap = False Else $left_snap = False $right_snap = False EndIf EndSwitch EndFunc Func GetRealParent(Const $hwnd) ; http://stackoverflow.com/questions/16872126/the-correct-way-of-getting-the-parent-window Local Const $hParent = _WinAPI_GetAncestor($hwnd, $GA_PARENT) If (Not $hParent) Or ($hParent = _WinAPI_GetDesktopWindow()) Then Return True EndIf Return False EndFunc Func _register_message(Const $h_target) Local Const $thread_id_target = _GetWindowThreadProcessId($h_target) DllCall($h_dll_hook, "int", "InstallFilterDLL", "long", $WH_CALLWNDPROC, "long", $thread_id_target, "hwnd", $h_target) _SendMessage($h_target, $UM_ADDMESSAGE, $WM_MOVE, $h_wnd_local) _SendMessage($h_target, $UM_ADDMESSAGE, $WM_MOVING, $h_wnd_local) GUIRegisterMsg($WM_MOVE, "_filter") GUIRegisterMsg($WM_MOVING, "_filter") Return $thread_id_target EndFunc Func _GetWindowThreadProcessId(Const $h_wnd) Local Const $ret = DllCall($user32, "dword", "GetWindowThreadProcessId", "hwnd", $h_wnd, "dword*", 0)[0] If @error Then Return SetError(@error, @extended, False) EndIf Return $ret EndFunc Func _uninstall_filter(Const $thread_id_target, Const $h_wnd_target) DllCall($h_dll_hook, "int", "UnInstallFilterDLL", "long", $thread_id_target, "hwnd", $h_wnd_target, "hwnd", $h_wnd_local) EndFunc Func _cleanup() _uninstall_filter($id_target, $window_focus) DllClose($h_dll_hook) DllClose($user32) EndFunc Edited September 13, 2014 by jaberwacky Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
jaberwacky Posted September 13, 2014 Author Share Posted September 13, 2014 (edited) Sad to say that this remains unsolved. This code will get the move and moving info for some windows but not all. If anybody knows a better solution, I'd love to hear it. expandcollapse popup#AutoIt3Wrapper_Run_AU3Check=n #AutoIt3Wrapper_AU3Check_Parameters=-w 1 -w 2 -w 3 -w 4 -w 6 -w 7 -d -q #include <WinAPI.au3> #include <Array.au3> #include <WindowsConstants.au3> #include <BorderConstants.au3> Const $UM_ADDMESSAGE = $WM_USER + 0x100 Const $h_dll_hook = DllOpen("hook.dll") ; helper dll Const $user32 = DllOpen("User32.dll") Const $h_wnd_local = GUICreate("") ; Needed to receive messages Const $mouse_proc_callback = DllCallbackRegister(_ll_mouse_proc, "long", "int;wparam;lparam") Const $hook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, DllCallbackGetPtr($mouse_proc_callback), _WinAPI_GetModuleHandle(0)) Const $half_desktop_width = @DesktopWidth / 2 Const $h_dc = _WinAPI_GetWindowDC(0) Const $h_pen = _WinAPI_CreatePen($PS_SOLID, $half_desktop_width, 0x0000FF) Const $o_orig = _WinAPI_SelectObject($h_dc, $h_pen) Local $s_rect = DllStructCreate($tagRECT) Const $range = 20 Global $id_target Global $mouse_pos Global $window_focus Global $left_snap = False Global $right_snap = False OnAutoItExitRegister(_cleanup) Do Sleep(100) Until False Volatile Func _ll_mouse_proc($code, $w_param, $l_param) Switch $code >= 0 Case True Switch $w_param Case $wm_lbuttondown $window_focus = _WinAPI_GetForegroundWindow() ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $window_focus = ' & $window_focus & @CRLF) ;### Debug Console If _get_real_parent($window_focus) Then $id_target = _register_message($window_focus) EndIf EndSwitch EndSwitch Return _WinAPI_CallNextHookEx($hook, $code, $w_param, $l_param) EndFunc Func _filter(Const $h_wnd_gui, Const $msg_id, Const $w_param, Const $l_param) Switch $msg_id Case $WM_MOVE ConsoleWrite("Move" & @CRLF) Select Case $left_snap WinMove($window_focus, "", $half_desktop_width, 0, $half_desktop_width, 1080) Case $right_snap WinMove($window_focus, "", @DesktopWidth, $half_desktop_width, $half_desktop_width, 1024) EndSelect $left_snap = False $right_snap = False $window_focus = Null _uninstall_filter($id_target, $window_focus) Case $WM_MOVING ConsoleWrite("Moving" & @CRLF) Local Const $mouse_pos = MouseGetPos(0) Select Case ($mouse_pos >= (@DesktopWidth - $range)) And ($mouse_pos <= @DesktopWidth) ConsoleWrite("Left" & @CRLF) With $s_rect .Left = $half_desktop_width .Right = 0 .Top = $half_desktop_width .Bottom = 1080 EndWith _WinAPI_DrawEdge($h_dc, DllStructGetPtr($s_rect), $BDR_RAISEDINNER, $BF_RECT) $left_snap = True $right_snap = False Case ($mouse_pos >= @DesktopWidth) And ($mouse_pos <= (@DesktopWidth + $range)) ConsoleWrite("Right" & @CRLF) $right_snap = True $left_snap = False Case Else $left_snap = False $right_snap = False EndSelect EndSwitch EndFunc Func _get_real_parent(Const $hwnd) ; http://stackoverflow.com/questions/16872126/the-correct-way-of-getting-the-parent-window Local Const $hParent = _WinAPI_GetAncestor($hwnd, $GA_PARENT) If (Not $hParent) Or ($hParent = _WinAPI_GetDesktopWindow()) Then Return True EndIf Return False EndFunc Func _register_message(Const $h_target) Local Const $thread_id_target = DllCall($user32, "dword", "GetWindowThreadProcessId", "hwnd", $h_target, "dword*", 0)[0] DllCall($h_dll_hook, "int", "InstallFilterDLL", "long", $WH_CALLWNDPROC, "long", $thread_id_target, "hwnd", $h_target) _SendMessage($h_target, $UM_ADDMESSAGE, $WM_MOVE, $h_wnd_local) _SendMessage($h_target, $UM_ADDMESSAGE, $WM_MOVING, $h_wnd_local) GUIRegisterMsg($WM_MOVE, "_filter") GUIRegisterMsg($WM_MOVING, "_filter") Return $thread_id_target EndFunc Func _uninstall_filter(Const $thread_id_target, Const $h_wnd_target) DllCall($h_dll_hook, "int", "UnInstallFilterDLL", "long", $thread_id_target, "hwnd", $h_wnd_target, "hwnd", $h_wnd_local) EndFunc Func _cleanup() _uninstall_filter($id_target, $window_focus) _WinAPI_SelectObject($h_dc, $o_orig) _WinAPI_DeleteObject($h_pen) _WinAPI_ReleaseDC(0, $h_dc) DllClose($h_dll_hook) DllClose($user32) EndFunc Edited September 13, 2014 by jaberwacky Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
Solution jaberwacky Posted September 13, 2014 Author Solution Share Posted September 13, 2014 Ok! Yes. I think this will work. Thank you everybody. #include <APISysConstants.au3> #include <GUIMenu.au3> #include <WinAPIProc.au3> #include <WinAPISys.au3> #include <WindowsConstants.au3> Global $hEventProc = DllCallbackRegister(_EventProc, "none", "ptr;dword;hwnd;long;long;dword;dword") Global $hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($hEventProc)) OnAutoItExitRegister(OnAutoItExit) Global $iPid = Run(@SystemDir & "\notepad.exe") While ProcessExists($iPid) Sleep(1000) WEnd Func OnAutoItExit() _WinAPI_UnhookWinEvent($hEventHook) DllCallbackFree($hEventProc) EndFunc Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime) #forceref $hEventHook, $iObjectID, $iChildID, $iThreadId, $iEventTime Switch $iEvent Case $EVENT_SYSTEM_MOVESIZEEND ConsoleWrite("End" & @CRLF) Case $EVENT_SYSTEM_MOVESIZESTART ConsoleWrite("Start" & @CRLF) EndSwitch EndFunc Gianni and pixelsearch 2 Helpful Posts and Websites: AutoIt3 Variables and Function Parameters MHz | AutoIt Wiki | Using the GUIToolTip UDF BrewManNH | Can't find what you're looking for on the Forum? Link to comment Share on other sites More sharing options...
Gianni Posted September 14, 2014 Share Posted September 14, 2014 <snip> Thank you everybody. <snip> You are welcome jaberwacky 1 Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now