Sign in to follow this  
Followers 0
sohfeyr

Enumerate controls for any window

18 posts in this topic

#1 ·  Posted (edited)

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

Share this post


Link to post
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

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

really nice, nowit works, but too crappy that it doesnt work for the game warcraft 3 :<

this is pain :<

Edited by Busti

My UDF's : Startet on : 06.06.2006_CaseSearchOrReplaceStr();~> Searches OR Replaces a String,;~> With or Without Casesensivity

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

pixelsearch is crap at games :/ fuck i have to go gto learn c++ :/


My UDF's : Startet on : 06.06.2006_CaseSearchOrReplaceStr();~> Searches OR Replaces a String,;~> With or Without Casesensivity

Share this post


Link to post
Share on other sites

@Busti: Did you ever think that there were no controls and the whole thing is rendered to the Window directly?

@sohfeyr: Nice job, but where is the dll?

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

@Busti: Did you ever think that there were no controls and the whole thing is rendered to the Window directly?

@sohfeyr: Nice job, but where is the dll?

there are, like in diablo II ...


My UDF's : Startet on : 06.06.2006_CaseSearchOrReplaceStr();~> Searches OR Replaces a String,;~> With or Without Casesensivity

Share this post


Link to post
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.

Share this post


Link to post
Share on other sites

Oh, sorry. I didn't see that, thanks.

This looks like something very useful. Good job!

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

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"

Share this post


Link to post
Share on other sites

With the added autoit features, should the code that you posted in your first post still work ?

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

humm... forget it. I just need to upgrade, there are build-in functions called DllCallback*** now...

Share this post


Link to post
Share on other sites

#18 ·  Posted (edited)

EDIT: I replied to a post 3 years old, didnt noticed srry

Edited by oMBRa

Share this post


Link to post
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
Sign in to follow this  
Followers 0