Что нового

Как вернуть Class элемента

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Версия AutoIt:3.

Поскажите пожалуйста,как вернуть Class элемента например Input при помощи наведения мыши на него в таком формате [CLASS:здесь ;Instance:id]

только мне эта функция нужна для встройки в скрипт,я знаю что можно воспользоваться Control Viewer или AutoIt Window Info,но это мне нужно в самом скрипте, вот пример чужого окна:

Код:
#include <GUIConstants.au3>
#include <WindowsConstants.au3>

$hForm = GUICreate('Autorize',200,40)
$input = GUICtrlCreateInput('',10,10,100,20)
$Button = GUICtrlCreateButton('OK',120,10,70,20)
GUISetState()

While 1
	$msg = GUIGetMsg()
	Switch $msg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Button
            $name = GUICtrlRead($input)	
            If $name = 'Login' Then
                MsgBox(0,'','OK')
			EndIf	
	EndSwitch
WEnd
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Зачем это нужно?
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
что бы по локале управлять другим приложением
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
У Вас Yashied хороший пример Control Viewer,ток я разобраться не могу,мне единственное нужно чтоб при наведении на элемент мышкой возвращался Class элемента,просто я координаты буду указывать мышке по которым она будет двигаться на элемент,а дальше отсылать этому элементу команду
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Это непростая задача, то, что в AutoIt называется ID, это не системный идентификатор элемента, а порядковый номер элемента на форме. Чтобы его получить, нужно пронумеровать все видимые элементы (здесь есть куча нюансов), таким образом ты получишь искомый ID. Я предоставил исходный код CV, изучай.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Код:
; ===============================================================================
;~ 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
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Спасибо,я так понимаю с помощью этих функций можно получить Class?
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Ещё,хочу спросить,если этот пример показывает ID элемента например 9523819 это нормально? Всё,понял,функция работает только когда приложение развёрнуто.
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
Yashied
Очень удивила эта строчка в плане скобок: :scratch:
Код:
;2091-я строчка CV.au3
If ($Index) And (StringCompare(_GUICtrlListView_GetItemText($hListView, $Index, 1), $Data, 1)) Then

они лишние или несут какой-то смысл?
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Наверное есть какойто смысл раз она там стоит,проблема в этом скрипте,он действует только на развёрнутые окна,а как быть с темы которые не могут развернуться во весь экран.... :scratch:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
zlo-kazan сказал(а):
...они лишние или несут какой-то смысл?

Нужна для обновления информации в ListView, если данные элемента изменились. А сравнение нужно для того, чтобы лишний раз не обновлять элемент в списке. А на счет скобок, я всегда заключаю условия в скобки, если их (условий) больше одного. Это позволяет избежать множество ошибок, связанных с приоритетами операторов.

Код:
If ((...) And (...)) Or ((...) And (...)) Then
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
Не догадывался о подобных конструкциях. :laugh: Выкручивался до этого If внутри If.... ;D
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Вот эта функция блокирует работу если окно не развёрнуто:

Код:
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
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Всё,разобрался,нашёл на оф.форуме ну и без мелких добавлений не обошлоь ;D

Код:
#include <WinAPI.au3>
#include <Array.au3>
#include <Process.au3>

AdlibRegister("_Mouse_Control_GetInfoAdlib", 1)
HotKeySet("{ESC}", "sExit")

Global $pos1 = MouseGetPos()
Global $pos2 = MouseGetPos()
Global $appHandle = 0
Global $dll = DllOpen("user32.dll")

While 1
    Sleep(0xFFFFFFF)
WEnd

Func _Mouse_Control_GetInfoAdlib()
    Local $Last_hControl = 0
    Local $aCtrlPos[4], $aNewCtrlPos[4]
    $pos1 = MouseGetPos()
    If $pos1[0] <> $pos2[0] Or $pos1[1] <> $pos2[1] Then
        Local $a_info = _Mouse_Control_GetInfo()
        Local $aDLL = DllCall('User32.dll', 'int', 'GetDlgCtrlID', 'hwnd', $a_info[0]) 
        If @error Then Return
		$PID = WinGetProcess ($appHandle)
		$Process = _ProcessGetName($PID)
        ToolTip("Parent Hwd = " & _WinAPI_GetAncestor($appHandle, 2) & @CRLF & _
		        "Handle = " & $a_info[0] & @CRLF & _
				"Title = " & WinGetTitle($appHandle) & @CRLF & _
				"Condition = " & WinGetState($appHandle) & @CRLF & _
				"Process = " & $Process & @CRLF & _
		        "ClassNN = " & $a_info[4] & @CRLF & _
                "Class = " & $a_info[1] & @CRLF & _
                "ID = " & $aDLL[0] & @CRLF & _
                "Mouse X = " & $a_info[2] & @CRLF & _
                "Mouse Y = " & $a_info[3])
        $pos2 = MouseGetPos()
    EndIf
EndFunc

Func _Mouse_Control_GetInfo()
    Local $client_mpos = $pos1
    Local $a_mpos
    Local $point, $cHwnd, $pos, $size
    $a_mpos = $client_mpos
    Local $h_control = WindowFromPoint($a_mpos)
    $appHandle = _WinAPI_GetAncestor($h_control, 2)
    If @error Then Return SetError(2, 0, 0)
    Local $t_class = DllStructCreate("char[260]")
    DllCall("User32.dll", "int", "GetClassName", "hwnd", $h_control, "ptr", DllStructGetPtr($t_class), "int", 260)
    Local $a_ret[5] = [$h_control, DllStructGetData($t_class, 1), $a_mpos[0], $a_mpos[1], "none"]
    Local $sClassNN = _ControlGetClassnameNN($a_ret[0])
    $a_ret[4] = $sClassNN
    Return $a_ret
EndFunc

Func WindowFromPoint($point)
    Local $cHwnd, $hwnd, $pos, $size
    $point = MouseGetPos()
    $hwnd = DllCall($dll, "hwnd", "WindowFromPoint", "int", $point[0], "int", $point[1])
    If $hwnd[0] <> 0 Then
        $pos = WinGetPos($hwnd[0])
        If @error Then Return 0
        $size = WinGetClientSize($hwnd[0])
        If @error Then Return 0
        $pos[0] += (($pos[2] - $size[0]) / 2)
        $pos[1] += (($pos[3] - $size[1]) - (($pos[2] - $size[0]) / 2))
        $cHwnd = DllCall($dll, "hwnd", "RealChildWindowFromPoint", "hwnd", $hwnd[0], _
                "int", $point[0] - $pos[0], "int", $point[1] - $pos[1])
        If $cHwnd[0] <> 0 Then $hwnd[0] = $cHwnd[0]
    EndIf
    Return $hwnd[0]
EndFunc 

Func GetHoveredHwnd($i_xpos, $i_ypos)
    Local $iRet = DllCall("user32.dll", "int", "WindowFromPoint", "long", $i_xpos, "long", $i_ypos)
    If IsArray($iRet) Then
        $appHandle = $iRet[0]
        Return HWnd($iRet[0])
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc

Func _ControlGetClassnameNN($hControl)
    If Not IsHWnd($hControl) Then Return SetError(1, 0, "")
    Local Const $hParent = _WinAPI_GetAncestor($appHandle, 2)
    If Not $hParent Then Return SetError(2, 0, "")
    Local Const $sList = WinGetClassList($hParent) 
    Local $aList = StringSplit(StringTrimRight($sList, 1), @LF, 2)
    _ArraySort($aList)
    Local $nInstance, $sLastClass, $sComposite
    For $i = 0 To UBound($aList) - 1
        If $sLastClass <> $aList[$i] Then 
            $sLastClass = $aList[$i]
            $nInstance = 1
        EndIf
        $sComposite = $sLastClass & $nInstance
        If ControlGetHandle($hParent, "", $sComposite) = $hControl Then
            Return $sComposite
        EndIf
        $nInstance += 1 
    Next
    Return SetError(3, 0, "")
EndFunc 

Func sExit()
    DllClose($dll)
    Exit
EndFunc
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Ничем,это он и есть,только Вы вырезали что-то лишнее и Ваш пример работает только на развёрнутые окна
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Sergey2210 [?]
Вы вырезали что-то лишнее
Я ничего не вырезал, это пример с оф. форума, видимо его обновили (кстати там нехватало только функций _WinAPI_GetAncestor($h_control, 2) после «WindowFromPoint»).
 
Верх