Jump to content

Advice Please: How to detect when the user moves any visible window?


Recommended Posts

I'm only a moderately experienced AutoIt coder, so I'd appreciate some guidance on the best techniques to code up the following: I want to receive notice of every time the user manually moves any visible / non-minimized window (not just mine). When I get that event notification, I also want to know if a particular key is pressed at the time (such as Control or Windows key).

I don't need a lot of hand-holding, but there appears to be different approaches and I'd like your advise in choosing among them. For example, there's _WinAPI_SetWinEventHook()/HookEx(), or GUIRegisterMsg(). Or maybe there are other, better alternatives?

Thanks for your time and knowledge!

Link to post
Share on other sites

Hi Mbee,
Concerning the moving/resizing part of any visible window, @jaberwacky did a great job using _WinAPI_SetWinEventHook() in his last post of this thread. It allows to be noticed "live" while any window is being moved or resized.

It's fun to run his script from Scite, then resizing/moving the Scite Window while looking at AutoIt Console. You can also add other events in his function _EventProc() , for example if you want to be noticed if any window is minimized or restored etc...

Func _EventProc($hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)
    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART
            ConsoleWrite("Start : a window is being moved or resized" & @CRLF)

        Case $EVENT_SYSTEM_MOVESIZEEND
            ConsoleWrite("End : the movement or resizing of a window has finished" & @CRLF)

        Case $EVENT_SYSTEM_MINIMIZESTART
            ConsoleWrite("Start : A window object is about to be minimized" & @CRLF)

        Case $EVENT_SYSTEM_MINIMIZEEND
            ConsoleWrite("End : A window object is about to be restored" & @CRLF)
  EndSwitch
EndFunc

List of possible events in this msdn link

Link to post
Share on other sites

If you combine in the same script :
1) _WinAPI_SetWinEventHook()  to take care of any window being moved or resized.
2) _WinAPI_SetWindowsHookEx() to take care of the keyboard input (as found in AutoIt help file examples)

Then you should be able to reach your goal as described in your initial post (at least for the Control keys or the Windows keys), something like the following script, where both Controls keys are checked :

#include <WinAPIConstants.au3>
#include <WinAPISys.au3>
#include <WindowsConstants.au3>

Opt( "MustDeclareVars", 1)

Global $g_hEventProc = DllCallbackRegister("_EventProc", "none", "ptr;dword;hwnd;long;long;dword;dword")
Global $g_hEventHook = _WinAPI_SetWinEventHook($EVENT_MIN, $EVENT_MAX, DllCallbackGetPtr($g_hEventProc))

Global $g_hStub_KeyProc = DllCallbackRegister("_KeyProc", "long", "int;wparam;lparam")
Global $g_hHook = _WinAPI_SetWindowsHookEx($WH_KEYBOARD_LL, DllCallbackGetPtr($g_hStub_KeyProc), _WinAPI_GetModuleHandle(0))

OnAutoItExitRegister(OnAutoItExit)

Local $iPid = Run(@SystemDir & "\notepad.exe")

While ProcessExists($iPid)
  Sleep(1000)
WEnd

;======================================
Func _EventProc($g_hEventHook, $iEvent, $hWnd, $iObjectID, $iChildID, $iThreadId, $iEventTime)

    Switch $iEvent
        Case $EVENT_SYSTEM_MOVESIZESTART
            ConsoleWrite("Start : a window is being moved or resized . " & _
                "Window title : " & WinGetTitle($hWnd) & @crlf)

        Case $EVENT_SYSTEM_MOVESIZEEND
            ConsoleWrite("End : the movement or resizing of a window has finished . " & _
                "Window title : " & WinGetTitle($hWnd) & @crlf & @crlf)
  EndSwitch
EndFunc   ;==>_EventProc

;======================================
Func _KeyProc($nCode, $wParam, $lParam)

    If $nCode < 0 Then
        Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
    EndIf

    Local $tKEYHOOKS = DllStructCreate($tagKBDLLHOOKSTRUCT, $lParam), $sKeyCode = ""

    If $wParam = $WM_KEYDOWN Then ; a nonsystem key is pressed. A nonsystem key is a key that is pressed when the ALT key is not pressed.
        Local $iKeycode = DllStructGetData($tKEYHOOKS, "vkCode")
        Switch $iKeycode
            Case 0xA2
                $sKeyCode = "Left Control"
            Case 0xA3
                $sKeyCode = "Right Control"
            ; Case ...
            ;      ...
        EndSwitch
    Else ; this part takes care of the Alt key
        Local $iFlags = DllStructGetData($tKEYHOOKS, "flags")
        Switch $iFlags
            Case $LLKHF_ALTDOWN ; context code flag
                $sKeyCode = "Alt"
        EndSwitch
    EndIf

    If $sKeyCode Then
        ConsoleWrite($sKeyCode & " key was pressed" & @crlf)
    EndIf

    Return _WinAPI_CallNextHookEx($g_hHook, $nCode, $wParam, $lParam)
EndFunc   ;==>_KeyProc

;======================================
Func OnAutoItExit()

    _WinAPI_UnhookWinEvent($g_hEventHook)
    DllCallbackFree($g_hEventProc)

    _WinAPI_UnhookWindowsHookEx($g_hHook)
    DllCallbackFree($g_hStub_KeyProc)
EndFunc   ;==>_OnAutoItExit

The best way to test the program is to run it from Scite, then resize Scite window while a Control key is pressed. It allows to read the results in Scite Console while resizing and/or pressing the Control keys.

Then closing the useless NotePad window will end the script (or you can end it directly by clicking on exit in AutoIt icon from the systray). No matter the way you'll choose to end the script, the important function OnAutoItExit() will be triggered.

Good luck :)

Updates :

* Sunday Oct 9, 2022 : display also the window title of the moved/resided window

* Monday Oct 10, 2022 : added code for detecting a pressed Alt key

Edited by pixelsearch
Updates listed above
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...