Jump to content
Sign in to follow this  
Mechaflash

Function to enumerate controls?

Recommended Posts

Anyway to easily enumerate all controls (i.e. control classes, instances, etc.) in a 3rd party app?

A business app I'm working on has all of the controls with their own classes and correct instances, but I don't know of an easy way to target each control in a loop without manually inputting the control info.

Edited by mechaflash213

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Share this post


Link to post
Share on other sites

Something like this loop for each class? Else, would you re-explain?

#include <Array.au3>
$iArrayCounter = 1
Dim $aControls[$iArrayCounter][3]
Dim $aControlTypes[3]=["Edit","Button","etc"]
For $i = 0 To Ubound ($aControlTypes)-1
 $iInstance = 1
 While 1
  $hControl = ControlGetHandle("DevTrack", "", "[CLASSNN:" & $aControlTypes[$i] & $iInstance & "]")
  If IsHWnd ( $hControl ) Then
   ReDim $aControls[$iArrayCounter][3]
   $aControls[$iArrayCounter-1][0]=$aControlTypes[$i]
   $aControls[$iArrayCounter-1][1]=$iInstance
   $aControls[$iArrayCounter-1][2]=$hControl
   $iArrayCounter += 1
  Else
   ExitLoop
  EndIf
  $iInstance += 1
 WEnd
Next
_ArrayDisplay ($aControls)

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

Something like this loop for each class? Else, would you re-explain?

#include <Array.au3>
$iArrayCounter = 1
Dim $aControls[$iArrayCounter][3]
Dim $aControlTypes[3]=["Edit","Button","etc"]
For $i = 0 To Ubound ($aControlTypes)-1
$iInstance = 1
While 1
$hControl = ControlGetHandle("DevTrack", "", "[CLASSNN:" & $aControlTypes[$i] & $iInstance & "]")
If IsHWnd ( $hControl ) Then
ReDim $aControls[$iArrayCounter][3]
$aControls[$iArrayCounter-1][0]=$aControlTypes[$i]
$aControls[$iArrayCounter-1][1]=$iInstance
$aControls[$iArrayCounter-1][2]=$hControl
$iArrayCounter += 1
Else
ExitLoop
EndIf
$iInstance += 1
WEnd
Next
_ArrayDisplay ($aControls)

Now if that could be modified to automatically find out what the classes are without specifying them, that would be what I was looking for.

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Share this post


Link to post
Share on other sites

Find me a way to get HWND -> Class, and I can do just that, using something like:

ControlGetHandle("Yourwindow", "", "[REGEXPCLASS:" & $aControlTypes[$i] & "; INSTANCE:" & $iInstance & "]")

aaaaand, possibly found it:

Func GetClassName($hWnd)

$Rt = DllCall("User32.dll","int","GetClassNameW","HWND",$hWnd,"wstr","","int",5000)

if @error Or $Rt[0] = 0 Then Return SetError(1,0,0)

Return SetError(0,0,$Rt[2])

EndFunc

Edited by jdelaney

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

Your welcome :)

$iArrayCounter = 1
Dim $aControls[$iArrayCounter][3]
Dim $aControlTypes[3]=["Edit","Button","etc"]
Dim $aControlTypes[1]=["[Ww]+"]
For $i = 0 To Ubound ($aControlTypes)-1
$iInstance = 1
While 1 ; loop through all instances
$sRegExp = $aControlTypes[0]
$hControl = ControlGetHandle("DevTrack", "", "[REGEXPCLASS:" & $sRegExp & "; INSTANCE:" & $iInstance & "]")
If Not IsHWnd ( $hControl ) Then ExitLoop
While 1; loop through all class types within each instance
$hControl = ControlGetHandle("DevTrack", "", "[REGEXPCLASS:" & $sRegExp & "; INSTANCE:" & $iInstance & "]")
If IsHWnd ( $hControl ) Then
    $sControlType = GetClassName($hControl)
    $sRegExp = $sRegExp & "[^" & $sControlType & "]"
    ReDim $aControls[$iArrayCounter][3]
    $aControls[$iArrayCounter-1][0]=$sControlType
    $aControls[$iArrayCounter-1][1]=$iInstance
    $aControls[$iArrayCounter-1][2]=$hControl
    $iArrayCounter += 1
Else
    ExitLoop
EndIf
WEnd
$iInstance += 1
WEnd
Next
_ArrayDisplay ($aControls)
Func GetClassName($hWnd)
$Rt = DllCall("User32.dll","int","GetClassNameW","HWND",$hWnd,"wstr","","int",5000)
if @error Or $Rt[0] = 0 Then Return SetError(1,0,0)
Return SetError(0,0,$Rt[2])
EndFunc

edit: almost, some itteration issues

Edited by jdelaney

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

Simplified...got all the control types, then used my original loop:

#include <Array.au3>
$iArrayCounter = 1
Dim $aControls[$iArrayCounter][3]
Dim $aControlTypes[1]
$sRegExp = ""
; get all classes
While 1; loop through all class types within each instance
 $hControl = ControlGetHandle("DevTrack", "", "[REGEXPCLASS:" & $sRegExp & "]")
 If IsHWnd($hControl) Then
  $sControlType = GetClassName($hControl)
  If $iArrayCounter > 1 Then
   $sRegExp = StringLeft($sRegExp, StringLen($sRegExp) - 1)
   $sRegExp = $sRegExp & "|^" & $sControlType & "]"
  Else
   $sRegExp = "[^" & $sControlType & "]"
  EndIf
  ConsoleWrite ( $sRegExp & @CRLF )
  ReDim $aControlTypes[$iArrayCounter]
  $aControlTypes[$iArrayCounter - 1] = $sControlType
  $iArrayCounter += 1
  ConsoleWrite ( $sControlType & @CRLF )
 Else
  ExitLoop
 EndIf
WEnd
$iArrayCounter = 1
Dim $aControls[$iArrayCounter][3]
For $i = 0 To Ubound ($aControlTypes)-1
 $iInstance = 1
 While 1
  $hControl = ControlGetHandle("DevTrack", "", "[CLASSNN:" & $aControlTypes[$i] & $iInstance & "]")
  If IsHWnd ( $hControl ) Then
   ReDim $aControls[$iArrayCounter][3]
   $aControls[$iArrayCounter-1][0]=$aControlTypes[$i]
   $aControls[$iArrayCounter-1][1]=$iInstance
   $aControls[$iArrayCounter-1][2]=$hControl
   $iArrayCounter += 1
  Else
   ExitLoop
  EndIf
  $iInstance += 1
 WEnd
Next
_ArrayDisplay ( $aControls )
Func GetClassName($hWnd)
 $Rt = DllCall("User32.dll", "int", "GetClassNameW", "HWND", $hWnd, "wstr", "", "int", 5000)
 If @error Or $Rt[0] = 0 Then Return SetError(1, 0, 0)
 Return SetError(0, 0, $Rt[2])
EndFunc   ;==>GetClassName

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

sweeeeeeeet. Works uber great. Now go make this a UDF and share your brilliance :thumbsup:

Thanx JD


Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

Share this post


Link to post
Share on other sites

Adjusted to be called as a function with example usage.

#include <Array.au3>
Local $hWnd
$hWnd = WinGetHandle("All My Papers Demonstration Software")
$aControlClasses = _WinControls_Enumerate($hWnd)
_ArrayDisplay($aControlClasses)

Func _WinControls_Enumerate(Const $hWinHandle) ; Pass a window handle to this function. Outputs a 2D-3Index array of control Classes, Instances, and Handles of a window
    Local $iArrayCounter = 1, $sRegExp = "", $sWinHandle
    Dim $aControls[$iArrayCounter][3]
    Dim $aControlTypes[1]

    ; get all classes
    While 1; loop through all class types within each instance
        $hControl = ControlGetHandle($hWinHandle, "", "[REGEXPCLASS:" & $sRegExp & "]")
        If IsHWnd($hControl) Then
            $sControlType = GetClassName($hControl)
            If $iArrayCounter > 1 Then
                $sRegExp = StringLeft($sRegExp, StringLen($sRegExp) - 1)
                $sRegExp = $sRegExp & "|^" & $sControlType & "]"
            Else
                $sRegExp = "[^" & $sControlType & "]"
            EndIf
            ConsoleWrite ( $sRegExp & @CRLF )
            ReDim $aControlTypes[$iArrayCounter]
            $aControlTypes[$iArrayCounter - 1] = $sControlType
            $iArrayCounter += 1
            ConsoleWrite ( $sControlType & @CRLF )
            Else
            ExitLoop
        EndIf
    WEnd
    $iArrayCounter = 1
    Dim $aControls[$iArrayCounter][3]
    For $i = 0 To Ubound ($aControlTypes)-1
        $iInstance = 1
        While 1
            $hControl = ControlGetHandle($hWinHandle, "", "[CLASSNN:" & $aControlTypes[$i] & $iInstance & "]")
            If IsHWnd ( $hControl ) Then
                ReDim $aControls[$iArrayCounter][3]
                $aControls[$iArrayCounter-1][0]=$aControlTypes[$i]
                $aControls[$iArrayCounter-1][1]=$iInstance
                $aControls[$iArrayCounter-1][2]=$hControl
                $iArrayCounter += 1
            Else
                ExitLoop
            EndIf
            $iInstance += 1
        WEnd
    Next
    Return $aControls
EndFunc

    Func GetClassName($hWnd)
        $Rt = DllCall("User32.dll", "int", "GetClassNameW", "HWND", $hWnd, "wstr", "", "int", 5000)
        If @error Or $Rt[0] = 0 Then Return SetError(1, 0, 0)
        Return SetError(0, 0, $Rt[2])
    EndFunc   ;==>GetClassName

Spoiler

“Hello, ladies, look at your man, now back to me, now back at your man, now back to me. Sadly, he isn’t me, but if he stopped using ladies scented body wash and switched to Old Spice, he could smell like he’s me. Look down, back up, where are you? You’re on a boat with the man your man could smell like. What’s in your hand, back at me. I have it, it’s an oyster with two tickets to that thing you love. Look again, the tickets are now diamonds. Anything is possible when your man smells like Old Spice and not a lady. I’m on a horse.”

 

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  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By sudeepjd
      I am building an application which needs a child panel in the GUI Control that needs to be scrolled as it contains controls that extend beyond the panel height. But I also need to have the users to be able to Tab through those controls. I don't seem to be able to to both working together. 
      The Tabstops can be allowed on children by using $WS_EX_CONTROLPARENT and the Scrollbar creation using the GUIScrollBar.au3.
      If I set the $WS_EX_CONTROLPARENT it drags the entire child and does not allow the scroll, but if I remove it, the Scroll works but the tabstops don't. Please see the below sample application that can help reproduce this problem.
       
      #include <GUIConstants.au3> #include <GUIScrollbars.au3> #include <WindowsConstants.au3> Opt("GUIOnEventMode", 1) ; Change to OnEvent mode Global $width=500, $height=500, $titel="Tabtest in Childwindow" ; create the parentwindow $mainwindow = GUICreate($titel, $width, $height, -1, -1) GUISetBkColor(0x00ffff) ; show the parentwindow GUISetState(@SW_SHOW,$mainwindow) ; check on screen sleep(1000) ; create the childwindow with the scrollbars active ->TABSTOPS Dont work $childwindo1 = GUICreate("child", 220,$height, 10 ,0,$WS_CHILD, -1 ,$mainwindow) _GUIScrollBars_Init($childwindo1, 100, 100) GUISetBkColor(0xff0000, $childwindo1) GUISetState(@SW_SHOW, $childwindo1) $input_1 = GUICtrlCreateInput("Scroll Works",10,10) $input_2 = GUICtrlCreateInput("Tab Does Not",10,40) ; create the childwindow with the scrollbars active ->TABSTOPS Work, Scroll does not because window moves $childwindo2 = GUICreate("child", 220, $height, 240 ,0,$WS_CHILD, $WS_EX_CONTROLPARENT ,$mainwindow) _GUIScrollBars_Init($childwindo2, 100, 100) GUISetBkColor(0xff0000, $childwindo2) GUISetState(@SW_SHOW, $childwindo2) $input_3 = GUICtrlCreateInput("Tab Works",10,10) $input_4 = GUICtrlCreateInput("Scroll Does Not",10,40) GUIRegisterMsg($WM_VSCROLL, "WM_VSCROLL") ; register close GUISetOnEvent($GUI_EVENT_CLOSE, "close_it",$mainwindow) ;loop While 1 Sleep(100) ; Idle around WEnd Func close_it() ; exit application GUIDelete($mainwindow) exit EndFunc $childwindo = GUICreate("child",$width,$height,0,0,$WS_CHILD,-1,$mainwindow) GUISetBkColor(0xff0000) GUISetState(@SW_SHOW,$childwindo) Func WM_VSCROLL($hWnd, $iMsg, $wParam, $lParam) #forceref $iMsg, $wParam, $lParam Local $iScrollCode = BitAND($wParam, 0x0000FFFF) Local $iIndex = -1, $iCharY, $iPosY Local $iMin, $iMax, $iPage, $iPos, $iTrackPos For $x = 0 To UBound($__g_aSB_WindowInfo) - 1 If $__g_aSB_WindowInfo[$x][0] = $hWnd Then $iIndex = $x $iCharY = $__g_aSB_WindowInfo[$iIndex][3] ExitLoop EndIf Next If $iIndex = -1 Then Return 0 ; Get all the vertial scroll bar information Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT) $iMin = DllStructGetData($tSCROLLINFO, "nMin") $iMax = DllStructGetData($tSCROLLINFO, "nMax") $iPage = DllStructGetData($tSCROLLINFO, "nPage") ; Save the position for comparison later on $iPosY = DllStructGetData($tSCROLLINFO, "nPos") $iPos = $iPosY $iTrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos") Switch $iScrollCode Case $SB_TOP ; user clicked the HOME keyboard key DllStructSetData($tSCROLLINFO, "nPos", $iMin) Case $SB_BOTTOM ; user clicked the END keyboard key DllStructSetData($tSCROLLINFO, "nPos", $iMax) Case $SB_LINEUP ; user clicked the top arrow DllStructSetData($tSCROLLINFO, "nPos", $iPos - 1) Case $SB_LINEDOWN ; user clicked the bottom arrow DllStructSetData($tSCROLLINFO, "nPos", $iPos + 1) Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box DllStructSetData($tSCROLLINFO, "nPos", $iPos - $iPage) Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box DllStructSetData($tSCROLLINFO, "nPos", $iPos + $iPage) Case $SB_THUMBTRACK ; user dragged the scroll box DllStructSetData($tSCROLLINFO, "nPos", $iTrackPos) EndSwitch ; // Set the position and then retrieve it. Due to adjustments ; // by Windows it may not be the same as the value set. DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS) _GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) _GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO) ;// If the position has changed, scroll the window and update it $iPos = DllStructGetData($tSCROLLINFO, "nPos") If ($iPos <> $iPosY) Then _GUIScrollBars_ScrollWindow($hWnd, 0, $iCharY * ($iPosY - $iPos)) $iPosY = $iPos EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_VSCROLL  
      Any help to get both working together is appreciated.
      Thanks,
      Sudeep.
    • By Atrax27
      I have a webpage that I would like to Focus the Input on a particular field, which is not automatically set as the initial input.
       
      Website:
      https://fiscaloffice.summitoh.net/PropertyTaxValues/PayTaxCC.htm
       
      I want to just simply use the Send(“154xxx”) into the “Parcel” field, then Send(“{ENTER}”) without cycling through tab presses each time before getting to the correct inputbox, where number of tab press numbers might change depending on a few things (using either IE, chrome, etc). On most websites I try this with, the “Login ID” field is the first one that the cursor jumps to so all I do is just start a Send command, but here I can’t do that since it’s not the initial cursor location.
       
      I’ve read a few things on the forums about “_WinAPI_SetFocus” but that appears to work on AutoIT generated form fields only (see below code), I don’t know how to translate it for website use, thanks for any help!
       
      #include <GUIConstantsEx.au3> #Include <WinAPI.au3>   $hGUI = GUICreate("Test", 500, 500) $hInput = GUICtrlCreateInput("", 10, 10, 400, 20) GUICtrlCreateButton("Test", 10, 100, 80, 30) GUICtrlSetState(-1, $GUI_FOCUS)   GUISetState() Sleep(5000) _WinAPI_SetFocus(ControlGetHandle("Test", "", $hInput)) While 1     Switch GUIGetMsg()         Case $GUI_EVENT_CLOSE             Exit     EndSwitch WEnd  
         
    • By paradox109
      Hello, 
      I have A simple question about http request. What would be the fastest way to send mupltiple http request at the same time with autoit? The only way i figured  out was to to start multiple processes. This way works fine but its not really a good way. What user would like to see 15 processes running in the background at the same time. I know multithread is also not available in autoit.
    • By undcover
      Hello, I'm automating part of the note taking ability of my old bad POS, I managed to do much of the heavy lifting in the past weeks, I can finally do everything i want and more.
      Now I have a form with two buttons that expand the form to show a note taking beast that can lets us escape the hell of the one way editing the POS actually support (no cursor just delete. want to change the time on that order better delete everything and start the note from scratch, well not anymore)
      Now i'm stuck, my form shows up as two buttons over the POS window, however I need it to go away when I minimized the POS or switch to a different page or application, I was able to do so by doing a while loop, it worked badly as it will repeat the show command infinitely and if i break the loop then there's no way to restart the loop if the user didn't interact with the buttons directly.
      I have many ways I could know when controls are visible and it worked, I just don't have a way of constantly checking for this without straining the CPU, I know if I work it somehow I could do a while loop that can work, but it'll be CPU intensive. (Bad POS entails BAD PC)
      Should I make another form that does the loop? can I make the loop slower ?
      I'm using  VB.net VS 2017 with AutoitX dll.
      EDIT: Hello anyone who searched for this, if you're and idiot like me and forgot that Timers exist then this will jog your memory
       
      Add a timer to your form, set the timer for 1 sec intervals (dealers choice)
      start your timer (within form load or manually)
      Timer1.start()
      then double click the timer to create a Timer tick (for my case the control visibility test i want to make each second)
      it should look something like this :
          Private Sub timer1_Tick(sender As Object, e As EventArgs) Handles timer1.Tick         dim visibleform = ait.ControlCommand("my app", "", "[NAME:wacontact]", "IsVisible", "")         If visibleform = 0 Then             Me.Hide() ElseIf visibleform = 1 And Me.Visible = False Then ' to prevent the timer ticks from interupting any sendkeys or something we put two conditions. Me.Show() End If     End Sub remarks: ait. is the call I set for Autoit DLL.
       
       
       
    • By BlueSkyMemory
      Hello guys! I'm a rookie in AutoIt lol.
      I've tried to looking up in MSDN and the UDFs, but it can only get the GUID of a usual partition and with the GUID to control it. Now I have no ways😥.
      Thanks a lot for your help!
×
×
  • Create New...