; ===============================================================================
;~ This script gets the control under the mouse pointer (active or inactive)
;~ The information then can be used with in conjunction with a control function.
;~ Requires AutoIt v3.3.0.0 or later to run and to view apps maximized.
;~ Big thanks to SmOke_N for his help in creating it - he did just about all of it!
; ===============================================================================
#include <WinAPI.au3>
#include <Array.au3>
Opt("MustDeclareVars", 1)
Opt("MouseCoordMode", 2)
AdlibRegister("_Mouse_Control_GetInfoAdlib", 10)
HotKeySet("^!x", "MyExit") ; Press Ctrl+Alt+x to stop the script
Global $pos1 = MouseGetPos()
Global $pos2 = MouseGetPos() ; must be initialized
Global $appHandle = 0
While 1
Sleep(0xFFFFFFF)
WEnd
; ===============================================================================
;~ Retrieves the information of a Control located under the mouse and displayes it in a tool tip next to the mouse.
;~ Function uesd
;~ _Mouse_Control_GetInfo()
;~ GetDlgCtrlID
; ===============================================================================
Func _Mouse_Control_GetInfoAdlib()
$pos1 = MouseGetPos()
If $pos1[0] <> $pos2[0] Or $pos1[1] <> $pos2[1] Then ; has the mouse moved?
Local $a_info = _Mouse_Control_GetInfo()
Local $aDLL = DllCall('User32.dll', 'int', 'GetDlgCtrlID', 'hwnd', $a_info[0]) ; get the ID of the control
Local $sClassNN = _ControlGetClassnameNN($a_info[0]) ; optional, will run faster without it
If @error Then Return
ToolTip("Handle = " & $a_info[0] & @CRLF & _
"Class = " & $a_info[1] & @CRLF & _
"ClassNN = " & $sClassNN & @CRLF & _ ; optional
"ID = " & $aDLL[0] & @CRLF & _
"Mouse X Pos = " & $a_info[2] & @CRLF & _
"Mouse Y Pos = " & $a_info[3] & @CRLF & _
"Parent Hwd = " & $appHandle)
;~ "Other ClassNN = " & ControlGetFocus($appHandle) & @CRLF & _
$pos2 = MouseGetPos()
EndIf
EndFunc ;==>_Mouse_Control_GetInfoAdlib
; ===============================================================================
;~ Retrieves the information of a Control located under the mouse.
;~ Uses Windows functions WindowFromPoint and GetClassName to retrieve the information.
;~ Functions used
;~ _GetHoveredHwnd()
;~ _ClientToScreen()
;~ Returns
;~ [0] = Control Handle of the control
;~ [1] = The Class Name of the control
;~ [2] = Mouse X Pos (converted to Screen Coord)
;~ [3] = Mouse Y Pos (converted to Screen Coord)
; ===============================================================================
Func _Mouse_Control_GetInfo()
$appHandle = GetHoveredHwnd() ; Uses the mouse to do the equivalent of WinGetHandle()
Local $client_mpos = MouseGetPos() ; gets client coords because of "MouseCoordMode" = 2
ConsoleWrite("AppHandle is : " & $appHandle & @LF)
Local $a_mpos = _ClientToScreen($appHandle, $client_mpos[0], $client_mpos[1]) ; $a_mpos now screen coords
If @error Then Return SetError(1, 0, 0)
Local $a_wfp = DllCall("user32.dll", "hwnd", "WindowFromPoint", "long", $a_mpos[0], "long", $a_mpos[1])
If @error Then Return SetError(2, 0, 0)
Local $t_class = DllStructCreate("char[260]")
DllCall("User32.dll", "int", "GetClassName", "hwnd", $a_wfp[0], "ptr", DllStructGetPtr($t_class), "int", 260)
Local $a_ret[4] = [$a_wfp[0], DllStructGetData($t_class, 1), $a_mpos[0], $a_mpos[1]]
Return $a_ret
EndFunc ;==>_Mouse_Control_GetInfo
; ===============================================================================
;~ Translates client coordinates into screen coordinates, [0] = x and [1] = y from the return array.
;~ Requires - AutoItSetOption("MouseCoordMode", 2)
;~ Params
;~ $h_wnd - Identifies the window whose client area is used for the conversion.
;~ $i_x - x pos of the client coord
;~ $i_y - Y pos of the client coord
;~ Returns
;~ Screen coordinates
; ===============================================================================
Func _ClientToScreen($h_wnd, $i_x, $i_y)
;~ ConsoleWrite("Client here, " & $i_x & "," & $i_y & @CRLF)
Local $t_point = DllStructCreate("int;int")
DllStructSetData($t_point, 1, $i_x)
DllStructSetData($t_point, 2, $i_y)
DllCall("user32.dll", "int", "ClientToScreen", "hwnd", $h_wnd, "ptr", DllStructGetPtr($t_point))
Local $a_ret[2] = [DllStructGetData($t_point, 1), DllStructGetData($t_point, 2)]
;~ ConsoleWrite("Screen here, " & $a_ret[0] & "," & $a_ret[1] & @CRLF)
Return $a_ret
EndFunc ;==>_ClientToScreen
; ===============================================================================
; Retrieves the Handle of GUI/Application the mouse is over.
; Similar to WinGetHandle except it used the current mouse position (Client Coords)
; Taken from http://www.autoitscript.com/forum/index.php?showtopic=444962
; ===============================================================================
Func GetHoveredHwnd()
Local $iRet = DllCall("user32.dll", "int", "WindowFromPoint", "long", MouseGetPos(), "long", MouseGetPos())
If IsArray($iRet) Then
$appHandle = $iRet[0]
Return HWnd($iRet[0])
Else
Return SetError(1, 0, 0)
EndIf
EndFunc ;==>GetHoveredHwnd
; ===============================================================================
;~ Gets the ClassNN of a control (Classname and Instance Count)
;~ The instance is really a way to uniquely identify classes with the same name
;~ Big thanks to Valik for writing the function, taken from - http://www.autoitscript.com/forum/index.php?showtopic=97662
;~ Param $hControl - the control handle from which you want the ClassNN
;~ Returns the ClassNN of the given control
;~ Function Used
;~ GetHoveredHwnd() - For some programs using _WinAPI_GetParent or _WinAPI_GetAncestor does not work as the top level window is got returned.
; ===============================================================================
Func _ControlGetClassnameNN($hControl)
If Not IsHWnd($hControl) Then Return SetError(1, 0, "")
Local Const $hParent = $appHandle ; get the Window handle, this is set in GetHoveredHwnd()
If Not $hParent Then Return SetError(2, 0, "")
Local Const $sList = WinGetClassList($hParent) ; list of every class in the Window
Local $aList = StringSplit(StringTrimRight($sList, 1), @LF, 2)
_ArraySort($aList) ; improves speed
Local $nInstance, $sLastClass, $sComposite
For $i = 0 To UBound($aList) - 1
If $sLastClass <> $aList[$i] Then ; set up the first occurrence of a unique classname
$sLastClass = $aList[$i]
$nInstance = 1
EndIf
$sComposite = $sLastClass & $nInstance ;build the ClassNN for testing with ControlGetHandle
;if ControlGetHandle(ClassNN) matches the given control return else look at the next instance of the classname
If ControlGetHandle($hParent, "", $sComposite) = $hControl Then
ConsoleWrite($sComposite & " is " & $hControl & " which == " & ControlGetHandle($hParent, "", $sComposite) & @LF)
Return $sComposite
EndIf
$nInstance += 1 ; count the number of times the class name appears in the list
Next
Return SetError(3, 0, "")
EndFunc ;==>_ControlGetClassnameNN
Func MyExit() ; stops the script
ConsoleWrite("Script Stoppted By User" & @CR)
Exit
EndFunc ;==>MyExit