Moin,
weil es hier gerade nachgefragt worden ist und ich hier nichts wirklich passendes gefunden habe:
AHK kennt für diesen Zweck die Anweisung WinGet, OutputVar, ControlList. Ich finde, das ist ein "nice to have", deshalb habe ich die Funktion _WinGetControls() erstellt:
WinGetControls.au3
#include-once
[/autoit] [autoit][/autoit] [autoit]; #DEMOFUNCTION# ================================================================================================================
; Name...........: _WinGetControls
; Description ...: Liefert ein 2D-Array für die Controls eines Fensters.
; Das Array enhält für jedes Control die folgenden Informationen:
; |[0] HWND - HWND des Controls
; |[1] Class - Klasse des Controls
; |[2] NN - ClassNN des Controls
; |[3] ID - ID des Controls
; |[4] Visible - Sichtbar? 1 = ja, 0 = nein
; Das Feld Array[0][0] enthält die Anzahl der Controls.
; Syntax.........: _WinGetControls($hWnd)
; Parameters ....: $hWnd - HWND des Fensters (z.B. Rückgabewert von GUICreate)
; Return values .: Erfolg: Controlarray
; Fehler: False, @error = 1
; Author ........: Großvater (http://www.autoit.de)
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _WinGetControls($hWnd)
Local $hCB
If Not IsHWnd($hWnd) Then Return SetError(1, 0, False)
__WinGetControlsAddControl("Init", 0)
$hCB = DLLCallbackRegister("__WinGetControlsAddControl", "Int", "HWND;LPARAM")
DllCall("User32.dll", "Int", "EnumChildWindows", "HWND", $hWnd, "Ptr", DllCallbackGetPtr($hCB), "LPARAM", $hWnd)
If @error Then Return SetError(DllCallbackFree($hCB), 0, False)
DllCallbackFree($hCB)
Return __WinGetControlsAddControl("Result", 0)
EndFunc
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __WinGetControlsAddControl
; Description ...: Callback-Funktion für DLLCall "EnumChildWindows" in _WinGetControls
; Remarks .......: Weil ich globale Variable für die Rückgabe von Funktionswerten nicht mag und die Implementierung
; der statischen Arrays recht rudimentär ist, sind die maximale Anzahl von Controls auf 1024
; und die maximale Anzahl von Klassen auf 256 begrenzt.
; ===============================================================================================================================
Func __WinGetControlsAddControl($hWnd, $lParam)
Local Static $UControls = 1024
Local Static $UClasses = 256
Local Static $aControls[$UControls + 1][5]
Local Static $aClasses[$UClasses + 1][2]
Local $aResult, $C, $Class, $ClassExist, $ID, $NN
Switch $hWnd
Case "Init"
$aControls[0][0] = 0
$aClasses[0][0] = 0
Return
Case "Result"
$C = $aControls[0][0] + 1
$aResult = $aControls
Redim $aResult[$C][5]
Return $aResult
EndSwitch
$aResult = DllCall("User32.dll", "Int", "GetClassNameW", "HWND", $hWnd, "WStr", "", "Int", 260)
If @error Or $aResult[0] = 0 Then Return True
$Class = $aResult[2]
$aResult = DllCall("User32.dll", "Int", "GetDlgCtrlID", "HWND", $hWnd)
If @error Or $aResult[0] = 0 Then Return True
$ID = $aResult[0]
$ClassExist = False
$C = $aClasses[0][0]
For $I = 1 To $C
If $aClasses[$I][0] = $Class Then
$NN = $aClasses[$I][1] + 1
$aClasses[$I][1] = $NN
$ClassExist = True
ExitLoop
EndIf
Next
If Not $ClassExist Then
$NN = 1
$C += 1
If $C > $UClasses Then Return False
$aClasses[0][0] = $C
$aClasses[$C][0] = $Class
$aClasses[$C][1] = $NN
EndIf
$C = $aControls[0][0] + 1
If $C > $UControls Then Return False
$aControls[0][0] = $C
$aControls[$C][0] = $hWnd
$aControls[$C][1] = $Class
$aControls[$C][2] = $NN
$aControls[$C][3] = $ID
$aControls[$C][4] = ControlCommand(HWnd($lParam), "", $ID, "IsVisible", "")
Return True
EndFunc
; ===============================================================================================================================
Nach einem Vorschlag von progandy (s.u.) folgt hier noch eine alternative Version, die ohne Callback-Funktion und ohne Beschränkungen hinsichtlich der Anzahl der Controls auskommt und deshalb auch etwas ressourcenschonender ist. Außerdem habe ich den Vorschlag von UEZ (s.u.) zur Ermittlung der AU3-Controlnamen in diese Version eingebaut:
WinGetControls.au3 - alternative Version nach Vorschlägen von progandy und UEZ
#include-once
[/autoit] [autoit][/autoit] [autoit]; #DEMOFUNCTION# ================================================================================================================
; Name...........: _WinGetControls
; Description ...: Liefert ein 2D-Array für die Controls eines Fensters.
; Das Array enhält für jedes Control die folgenden Informationen:
; |[0] HWND - HWND des Controls
; |[1] Class - Klasse des Controls
; |[2] NN - ClassNN des Controls
; |[3] ID - ID des Controls
; |[4] AU3 - AU3-Bezeichnung des Controls
; |[5] Visible - Sichtbar? 1 = ja, 0 = nein
; Das Feld Array[0][0] enthält die Anzahl der Controls.
; Syntax.........: _WinGetControls($hWnd)
; Parameters ....: $hWnd - HWND des Fensters (z.B. Rückgabewert von GUICreate)
; Return values .: Erfolg: Controlarray
; Fehler: False, @error = 1
; Author ........: Großvater & progandy & UEZ (http://www.autoit.de)
; Modified.......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......:
; ===============================================================================================================================
Func _WinGetControls($hWnd)
Local Const $GWL_STYLE = 0xFFFFFFF0
Local Const $BS_AUTOCHECKBOX = 0x0003
Local Const $BS_CHECKBOX = 0x0002
Local Const $BS_GROUPBOX = 0x0007
Local Const $BS_RADIOBUTTON = 0x0004
Local Const $BS_AUTORADIOBUTTON = 0x0009
Local Const $ES_MULTILINE = 4
Local Const $ES_WANTRETURN = 4096
Local Const $SS_ICON = 0x3
Local Const $SS_BITMAP = 0xE
Local Const $WS_VSCROLL = 0x00200000
Local Const $ES_EDIT = BitOR($ES_WANTRETURN, $WS_VSCROLL)
Local $UControls = 100
Local $UClasses = 50
Local $aControls[$UControls + 1][6]
Local $aClasses[$UClasses + 1][2]
Local $aResult, $AU3, $C, $Class, $ClassExist, $Handle, $ID, $NN, $Styles
If Not IsHWnd($hWnd) Then Return SetError(1, 0, False)
Local $sClasses = WinGetClassList($hWnd)
Local $aSplit = StringSplit(StringStripWS($sClasses, 2), @LF)
$aControls[0][0] = 0
$aClasses[0][0] = 0
For $I = 1 To $aSplit[0]
$Class = $aSplit[$I]
$ClassExist = False
$C = $aClasses[0][0]
For $J = 1 To $C
If $aClasses[$J][0] = $Class Then
$NN = $aClasses[$J][1] + 1
$aClasses[$J][1] = $NN
$ClassExist = True
ExitLoop
EndIf
Next
If Not $ClassExist Then
$NN = 1
$C += 1
If $C > $UClasses Then
$UClasses += 50
ReDim $aClasses[$UClasses + 1][2]
EndIf
$aClasses[0][0] = $C
$aClasses[$C][0] = $Class
$aClasses[$C][1] = $NN
EndIf
$Handle = ControlGetHandle($hWnd, "", $Class & $NN)
$aResult = DllCall("User32.dll", "Int", "GetDlgCtrlID", "HWND", $Handle)
If @error Or $aResult[0] = 0 Then
$ID = ""
Else
$ID = $aResult[0]
EndIf
$C = $aControls[0][0] + 1
If $C > $UControls Then
$UControls += 100
ReDim $aControls[$UControls + 1][6]
EndIf
; Ausgeliehen aus der WinAPI.au3
Local $sFuncName = "GetWindowLongW"
If @AutoItX64 Then $sFuncName = "GetWindowLongPtrW"
$aResult = DllCall("User32.dll", "LONG_PTR", $sFuncName, "HWND", $Handle, "INT", $GWL_STYLE)
$Styles = $aResult[0]
; Erweiterung nach Vorschlag von UEZ
Switch $Class
Case "Button"
If BitAND($Styles, $BS_GROUPBOX) = $BS_GROUPBOX Then
$AU3 = "Group"
ElseIf BitAND($Styles, $BS_CHECKBOX) = $BS_CHECKBOX Then
$AU3 = "Checkbox"
ElseIf BitAND($Styles, $BS_AUTOCHECKBOX) = $BS_AUTOCHECKBOX Then
$AU3 = "Checkbox"
ElseIf BitAND($Styles, $BS_RADIOBUTTON) = $BS_RADIOBUTTON Then
$AU3 = "Radio"
ElseIf BitAND($Styles, $BS_AUTORADIOBUTTON) = $BS_AUTORADIOBUTTON Then
$AU3 = "Radio"
Else
$AU3 = "Button"
EndIf
Case "Static"
If BitAND($Styles, $SS_ICON) = $SS_ICON Then
$AU3 = "Icon"
ElseIf BitAND($Styles, $SS_BITMAP) = $SS_BITMAP Then
$AU3 = "Pic"
Else
$AU3 = "Label"
EndIf
Case "Edit"
If BitAND($Styles, $ES_EDIT) = $ES_EDIT Then
$AU3 = "Edit"
Else
$AU3 = "Input"
EndIf
Case "SysAnimate32"
$AU3 = "AVI"
Case "ComboBox"
$AU3 = "Combo"
Case "SysDateTimePick32"
$AU3 = "Date"
Case "ListBox"
$AU3 = "List"
Case "SysListView32"
$AU3 = "ListView"
Case "SysMonthCal32"
$AU3 = "MonthCal"
Case "msctls_progress32"
$AU3 = "Progress"
Case "msctls_trackbar32"
$AU3 = "Slider"
Case "SysTabControl32"
$AU3 = "Tab"
Case "SysTreeView32"
$AU3 = "TreeView"
Case "msctls_updown32"
$AU3 = "UpDown"
Case Else
$AU3 = ""
EndSwitch
$aControls[0][0] = $C
$aControls[$C][0] = $Handle
$aControls[$C][1] = $Class
$aControls[$C][2] = $NN
$aControls[$C][3] = $ID
$aControls[$C][4] = $AU3
$aControls[$C][5] = ControlCommand($hWnd, "", $ID, "IsVisible", "")
Next
$C = $aControls[0][0] + 1
ReDim $aControls[$C][6]
Return $aControls
EndFunc ;==>_WinGetControls
; ===============================================================================================================================
Eine Minidemo gibt es auch:
Demo
#include "WinGetControls.au3"
#include <Array.au3>
Dim $aControls, $hWnd, $Title
[/autoit] [autoit][/autoit] [autoit]Run("Notepad")
$hNotepad = WinWaitActive("[CLASS:Notepad]", "", 2)
If Not IsHWnd($hNotepad) Then
MsgBox(0, "WinGetControls", "Notepad konnte nicht gestartet werden!")
Exit
EndIf
$Title = WinGetTitle($hNotepad )
$aControls = _WinGetControls($hNotepad)
If Not IsArray($aControls) Then
MsgBox(0, "ERROR", "Der Aufruf von _WinGetControls() ist fehlgeschlagen!")
Else
_ArrayDisplay($aControls, $Title, -1, 0, "", "|", "Zeile|HWND|Class|NN|ID|Visible")
EndIf
Exit
[/autoit]
Alternative Version von UEZ:
Das Thema scheint ja wirklich Interesse zu wecken. UEZ hat hier eine erweiterte Version der ersten Funktion eingestellt, die für die Klasse der Buttons zusätzlich die in AU3 verwendeten Bezeichner (Button, Checkbox, Groupbox, Radio) ermittelt. Eine passende Demo hat er dazugetan. Ich habe seine Anregungen in die alternative Version übernommen.
Vielleicht kann es ja jemand brauchen.
Happy scripting!