Jump to content

Enumerate controls for any window


sohfeyr
 Share

Recommended Posts

A few things always bugged me about WinGetClassList:

1) Unlike WinList, it doesn't give you the handles.

2) It tells you the classnames of the controls, but not the instance numbers, making it inconvenient for using with Control functions.

3) It reports all descendant controls with no regard for hierarchy or ownership.

I don't know about the rest of you, but I was excited to see Piccaso's callback post, not least because he included an EnumWindows / EnumChildWindows sample. This is based on that. Supporting functions and download links follow.

Suggestions welcome!

Usage:

WinControlList("AutoIt Help") ; outputs to console, easily modified
WinControlListGUI("AutoIt Help") ; outputs to treeview in a GUI
oÝ÷ ØÆ¢º.)Þ±«­¢+Ø(¥¹±Õ±ÐíÉÉä¹ÔÌÐì(¥¹±Õ±ÐíU%
½¹ÍѹÑ̹ÔÌÐì(¥¹±Õ±ÐíÕ¥QÉY¥Ü¹ÔÌÐì()±½°ÀÌØí]¥¹½ÝÍlÅt°ÀÌØí
¡¥±]¥¹½ÝÍlÅt()Õ¹]¥¹
½¹Ñɽ±1¥ÍÐ ÀÌØí¡]¹AɹФ($ÀÌØíIIdõ]¥¹
½¹Ñɽ±1¥ÍÑU$ ÀÌØí¡]¹AɹаÀ°À¤($ÀÌØíÌôÅÕ½ÐìÅÕ½Ðì(%½ÈÀÌØí¥¸ÀÌØíIId($%½ÈÀÌØí¥¸ÀÌØí($$$ÀÌØí̵ÀìôÀÌØíµÀìQ($%9áÐ($$ÀÌØí̵Àìô
I1(%9áÐ(%
½¹Í½±]É¥Ñ ÀÌØí̤)¹Õ¹()Õ¹]¥¹
½¹Ñɽ±1¥ÍÑU$ ÀÌØí¡]¹AɹаÀÌØíÍÑ­´ôÄ°ÀÌØíM¡½ÝU$ôĤ($ÀÌØí¡±°ô±±=Á¸ ÅÕ½ÐíÔÍ
±±    ¬¹±°ÅÕ½Ðì¤($ìÐչѥ½¸A½¥¹ÑÈ($ÀÌØí¡Aɽô±±
±° ÀÌØí¡±°°ÅÕ½Ðí¥¹ÐÅÕ½Ðì°ÅÕ½Ðí5å
±±    ­AÑÈÅÕ½Ðì¤($ì
ÉÑI¥ÙÈ]¥¹½Ü($ÀÌØí¡]¹5¥¸ôU%
ÉÑ ÅÕ½Ðí]¥¹½Ý̹յÉѽÈÅÕ½Ðì°ØÈÈ°ÐÐà°ÄäÈ°ÄÈÔ°ÀÌØí]M}M%i  =`¬ÀÌØí]M}MeM59T¤($ÀÌØíQÉY¥ÜôU%
Ñɱ
ÉÑQÉY¥Ü À°À°ØÈÀ°ÐÈà¤(%U%
ÑɱMÑIͥ饹 ´Ä°ÀÌØíU%}=
-UQ

EnumWindowsTest.au3

Edited by sohfeyr
Link to comment
Share on other sites

would this work for me i would love you so hard!!!

but :

D:\Dokumente und Einstellungen\AndiT\Desktop\enumerate.au3 (58) : ==> Subscript used with non-Array variable.: 
DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc[0],"int",1) 
DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc^ ERROR
My UDF's : Startet on : 06.06.2006_CaseSearchOrReplaceStr();~> Searches OR Replaces a String,;~> With or Without Casesensivity
Link to comment
Share on other sites

D:\Dokumente und Einstellungen\AndiT\Desktop\enumerate.au3 (58) : ==> Subscript used with non-Array variable.: 
DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc[0],"int",1) 
DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc^ ERROR
$hProc is not an array if the earlier DLLCall failed. Make sure you have downloaded Piccaso's au3callback.dll, and that it is in the same folder as the script you are running. You don't need to register it or anything, but it does have to be present.
Link to comment
Share on other sites

this is pain :<

Yeah... good luck with that. I only needed to be able to handle ordinary Windows controls for my purposes, and I won't even pretend to know how to approach controls for game windows. If there was a gun to my head I'd try using PixelSearch and doing some color manipulation, but looking at your post count I'm guessing you already know all your built-in options.

Link to comment
Share on other sites

Link to comment
Share on other sites

would this work for me i would love you so hard!!!

but :

D:\Dokumente und Einstellungen\AndiT\Desktop\enumerate.au3 (58) : ==> Subscript used with non-Array variable.: 
DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc[0],"int",1) 
DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc^ ERROR
Au3CallBackDLL probably is not working on WIN98. I had the same error.
Link to comment
Share on other sites

  • 1 year later...

http://www.autoitscript.com/forum/index.ph...st&p=216066

I linked to it in the first post. I would post it here for download, but since it isn't mine it just didn't feel like I had the right...

Hello;

It may be some time that this thread is close; but I saw it couple days ago.

I couldn't find "au3callback.dll" - I sent an email to picasso; but couldn't get any response.

Can someone give me a copy of that - I need it badly. I googled it, this is the only place where the file has been mentioned <with filename>. Please help me;

regards

Link to comment
Share on other sites

Hello;

It may be some time that this thread is close; but I saw it couple days ago.

I couldn't find "au3callback.dll" - I sent an email to picasso; but couldn't get any response.

Can someone give me a copy of that - I need it badly. I googled it, this is the only place where the file has been mentioned <with filename>. Please help me;

regards

This is outdated now since DllCallbackRegister() was added to AutoIt.

Edited by Siao

"be smart, drink your wine"

Link to comment
Share on other sites

  • 3 months later...

Great App!, and no, the code does not work anymore :P I changed the callback-routines to work with DLLCallbackRegister :P

#include <array.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <GuiTreeView.au3>


Global $aWindows[1], $aChildWindows[1]

;WinControlList("callback")
;~ WinControlListGUI("AutoIt Help",1,1)
AllList()

Func WinControlList($hWndParent)
    $RARY=WinControlListGUI($hWndParent, 0,0)
    $s=""
    For $a in $RARY
        For $b in $a
            $s &= $b & @TAB
        Next
        $s &= @CRLF
    Next
    ConsoleWrite($s)
EndFunc

Func WinControlListGUI($hWndParent, $stackem=1, $ShowGUI=1)
;~  $hDll = DllOpen("au3CallBack.dll")
    ; Get Function Pointer
;~  $hProc = DllCall($hDll,"int","MyCallBackPtr")
    ; Create Reciever Window
;~  $wind =DllCallbackRegister("EnumWindowsProc","int","hwnd;lparam")
    Local $child = DllCallbackRegister("EnumChildProc","int","hwnd;lparam")
    $hWndMain = GUICreate("Windows Enumerator",622, 448, 192, 125,$WS_SIZEBOX+$WS_SYSMENU)
    $TreeView = GUICtrlCreateTreeView(0, 0, 620, 428)
    GUICtrlSetResizing (-1,$GUI_DOCKAUTO)
    GUICtrlSetFont(-1,9,Default,Default,"Courier New")
    ; Register 'Callback' Functions
;~  GUIRegisterMsg(0x400+1,"EnumWindowsProc") ; WM_USER+1
;~  GUIRegisterMsg(0x400+2,"EnumChildProc") ; WM_USER+2
    ; Tell Dll where to send messages
;~  DllCall($hDll,"hwnd","SetHwnd","hwnd",$hWndMain)
    
    $TreeViewParent = GUICtrlCreateTreeViewItem($hWndParent & ' -> "' & WinGetTitle($hWndParent) & '" ' & GetClassName($hWndParent) & ".", $TreeView)
    
    $RARY=0 ; turns into an array
    WinControlListRecursiveTL(DllCallbackGetPtr($child), $TreeView, WinGetHandle($hWndParent), $TreeViewParent, $RARY, $stackem) ; Enumerate Child Windows  
    DllCallbackFree($child)
    ; Display
    If $ShowGUI=1 then
        GUISetState()
        While GuiGetMsg() <> $GUI_EVENT_CLOSE
            Sleep(10)
        WEnd
    EndIf   
    Return $RARY
EndFunc


Func WinControlListRecursiveTL($hProc, $TreeView, $hWndParent, $TreeViewParent, ByRef $RARY, $stackem=1)
;~  DllCall($hDll,"int","SetWindowsMessage","int",0x400+2) ; WM_USER + 2
    ReDim $aChildWindows[1]
    DllCall("user32.dll","int","EnumChildWindows","hwnd",WinGetHandle($hWndParent),"int",$hProc,"int",1)
    For $hWndChild In $aChildWindows
        If Not IsHWnd($hWndChild) Then ContinueLoop
        If $stackem=1 then 
            If ControlGetParent($hWndChild) <> $hWndParent Then ContinueLoop
        EndIf
            
        $ID=ControlGetID($hWndChild)
        $POS=ControlGetPos($hWndParent,"",$hWndChild)
        If IsArray($POS)=0 then $POS = _ArrayCreate(0,0,0,0)
        $ClassNameNN=ControlGetClassNameNN($hWndChild, $hWndParent)
        $NP=_GUICtrlTreeView_InsertItem($TreeView,$hWndChild & ' -> "' & WinGetTitle($hWndChild) & '" ' & _
            $ClassNameNN & " ID:" & $ID & " @:" & _ArrayToString($POS,","), $TreeViewParent)
            
        $ACtl=_ArrayCreate($hWndChild, $hWndParent, ControlGetParent($hWndChild), $ID, _ArrayToString($POS,","), $ClassNameNN, GetClassName($hWndChild)) 
        If $RARY=0 Then
            $RARY=_ArrayCreate($ACtl)
        Else
            _ArrayAdd($RARY,$ACtl)
        EndIf
        
        If $stackem=1 then WinControlListRecursiveTL($hProc, $TreeView, $hWndChild, $RARY, $NP)
    Next
    Return $RARY
EndFunc

#region "Callback Functions"
;~ BOOL CALLBACK EnumWindowsProc(
;~  HWND hwnd,  // handle to parent window
;~  LPARAM lParam   // application-defined value
;~ );
Func EnumWindowsProc($hWnd, $LParam)
    Local $MyMessage, $hWndFound
;~  $MyMessage = DllStructCreate ("int;" _ ; HWND hwnd, // handle to parent window
;~                              & "int" _ ; LPARAM lParam   // application-defined value
;~                              , $LParam)
    $hWndFound = $hWnd
    _ArrayAdd($aWindows, $hWndFound)
    Return True ; To get next window
EndFunc

;~ BOOL CALLBACK EnumChildProc(
;~  HWND hwnd,  // handle to child window
;~  LPARAM lParam   // application-defined value
;~ );
Func EnumChildProc($hWnd, $LParam)
    Local $MyMessage, $hWndChildFound;Found
;~  $MyMessage = DllStructCreate ("int;" _ ; HWND hwnd, // handle to child window
;~                              & "int" _ ; LPARAM lParam   // application-defined value
;~                              , $LParam)
    $hWndChildFound = $hWnd
    _ArrayAdd($aChildWindows, $hWndChildFound)
    Return True ; To get next window
EndFunc
#endregion
#region "Control Info"
Func ControlGetParent($hWndChild)
    $GP=DllCall('user32.dll', 'int', 'GetParent', 'int', $hWndChild)
    Return $GP[0]
EndFunc

Func ControlGetID($hCtrlWnd)
    $hCtrlWnd=ControlGetHandle("","",$hCtrlWnd)
    $x = DllCall('User32.dll', 'int', 'GetDlgCtrlID', 'hwnd', $hCtrlWnd)
    If @error or $x[0]=0 then Return SetError(-1,0,"-1")
    Return $x[0]
EndFunc

; Get the classname of the stated control or window
Func GetClassName($hWndControl)
    $name=DllCall('user32.dll', 'int', 'GetClassName', 'hwnd', $hWndControl, 'str', "", 'int', 256)
    Return $name[2]
EndFunc

Func ControlGetClassNameNN($hCtrlWnd, $hWinWnd="")
    $hCtrlWnd=ControlGetHandle($hWinWnd,"",$hCtrlWnd)
    $name = GetClassName($hCtrlWnd)
    $lst=StringSplit(WinGetClassList($hWinWnd,""), @crlf)
    For $C in StringSplit(WinGetClassList($hWinWnd,""), @crlf)
        If $C = $name then
            For $x = 1 to UBound($lst)
                $ctl = $C & $x
                If ControlGetHandle($hWinWnd,"",$ctl) = $hCtrlWnd then Return $ctl
            Next
        EndIf
    Next
    Return "?"
EndFunc
#endregion

Func AllList()
    ;Dim $aWindows[1],$aChildWindows[1]

    ; Load Dll
;~  $hDll = DllOpen("au3CallBack.dll")
    ; Get Function Pointer
;~  $hProc = DllCall($hDll,"int","MyCallBackPtr")
    ; Create Reciver Window
    $hWndMain = GUICreate("Windows Enumerator",622, 448, 192, 125,$WS_SIZEBOX+$WS_SYSMENU)
    $TreeView = GUICtrlCreateTreeView(0, 0, 620, 428)
    GUICtrlSetResizing (-1,$GUI_DOCKAUTO)
    GUICtrlSetFont(-1,9,Default,Default,"Courier New")
    GUISetState()
    ; Register 'Callback' Functions
    Local $wind =DllCallbackRegister("EnumWindowsProc","int","hwnd;lparam")
    Local $child = DllCallbackRegister("EnumChildProc","int","hwnd;lparam")
    ; Tell Dll where to send messages
    ; Enumerate Windows
;~  DllCall($hDll,"int","SetWindowsMessage","int",0x400 + 1) ; WM_USER + 1
    DllCall("user32.dll","int","EnumWindows","int",DllCallbackGetPtr($wind),"int",1)

    $iWindows = UBound($aWindows)
    $iWinCount = 0
    $aProc = ProcessList()
    for $i = 1 to $aProc[0][0]
        $iPid = $aProc[$i][1]
        $sModule = $aProc[$i][0]
        $TreeViewPid = GUICtrlCreateTreeViewItem($iPid & ' -> "' & $sModule & '"',$TreeView)
        For $hWndParent In $aWindows
            If Not IsHWnd($hWndParent) Or WinGetProcess($hWndParent) <> $iPid Then ContinueLoop
            $iWinCount += 1
            $TreeViewParent = GUICtrlCreateTreeViewItem($hWndParent & ' -> "' & WinGetTitle($hWndParent) & '" ' & GetClassName($hWndParent), $TreeViewPid)
            WinSetTitle($hWndMain,"","Windows Enumerator - " & Round($iWinCount/$iWindows*100) & "%")
            ; Enumerate ChildWindows
            ReDim $aChildWindows[1]
            DllCall("user32.dll","int","EnumChildWindows","hwnd",$hWndParent,"int",DllCallbackGetPtr($child),"int",1)
            For $hWndChild In $aChildWindows
                If Not IsHWnd($hWndChild) Then ContinueLoop
                $name=DllCall('user32.dll', 'int', 'GetClassName', 'hwnd', $hWndChild, 'str', "", 'int', 256)
                $name = $name[2]
                _GUICtrlTreeView_InsertItem($TreeView,$hWndChild & ' -> "' & WinGetTitle($hWndChild) & '" ' & $name, $TreeViewParent)
            Next
            If GUIGetMsg() = $GUI_EVENT_CLOSE Then Exit
        Next
    Next
    WinSetTitle($hWndMain,"","Windows Enumerator - Done")
    DllCallbackFree($child)
    DllCallbackFree($wind)
    While GuiGetMsg() <> $GUI_EVENT_CLOSE
        Sleep(10)
    WEnd
    Exit
EndFunc

Func GetDesktopWindow()
    $x=DllCall('user32.dll','int','GetDesktopWindow')
    Return $x[0]
EndFunc

Func NULL()
    Return ControlGetParent(GetDesktopWindow())
EndFunc

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

  • 9 months later...

Hi all,

Do someone still have au3CallBack.dll ? I can't find it in the forum.

I need to call EnumChildWindows, and unless changes have been made to autoit since then, I don't know any other way to do so.

Thanks a lot.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...