Что нового

Как вернуть 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 472
Репутация
2 401
Зачем это нужно?
 
Автор
S

Sergey2210

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

Sergey2210

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

Yashied

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 472
Репутация
2 401
Код:
; ===============================================================================
;~ 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 711
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 472
Репутация
2 401
Sergey2210 [?]
Вы вырезали что-то лишнее
Я ничего не вырезал, это пример с оф. форума, видимо его обновили (кстати там нехватало только функций _WinAPI_GetAncestor($h_control, 2) после «WindowFromPoint»).
 
Автор
S

Sergey2210

Осваивающий
Сообщения
263
Репутация
31
Всё ясно,спасибо :smile:
 
Верх