Jump to content
Sign in to follow this  
alext

Newbie question (ControlGetHandle not working like supposed to)

Recommended Posts

alext

Maybe this question has already been answered somewhere, (i haven't found it though) ... in case it did, please just point me to the right direction and I will figure it out.

Here is my problem... I have a listbox with the following properties

>>>> Control <<<<

Class: ListBox

Instance: 4

ClassnameNN: ListBox4

Advanced (Class): [CLASS:ListBox; INSTANCE:4]

ID: 302

Text:

Position: 713, 83

Size: 300, 406

ControlClick Coords: 98, 173

Style: 0x50310121

ExStyle: 0x00000204

Handle: 0x00270130

As you can see the instance nr is 4 and the id is 302... so the following lines of code should return the same handle, but they don't.

When I use the instance, I do get the correct handle...

Local $hSectionGrid = ControlGetHandle("Client","","[iD:302]")

ConsoleWrite("SectionGrid: " & $hSectionGrid &@CR)

Local $hSectionGrid_1 = ControlGetHandle("Client","","[CLASS:ListBox;INSTANCE:4]")

ConsoleWrite("SectionGrid: " & $hSectionGrid_1 &@CR)

The reason I need this to work is because I have a "hidden" control...and I can't get the instance nr of that control, just the ID... but when I try getting it's handle by means of the ID...it just doesn't return me the correct handle.

Can anybody tell me what I'm doing wrong here?

Thanks for the help!

Share this post


Link to post
Share on other sites
PsaltyDS

This works:

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>

GUICreate("Client", 300, 380)
For $n = 1 To 10
    GUICtrlCreateList("List: " & $n, 20, 20 + (($n - 1) * 30), 200, 20)
Next
$idButton_1 = GUICtrlCreateButton("Get Handles", 100, 330, 100, 30)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $idButton_1
            For $n = 1 To 10
                $sMsg = "Instance = " & $n & ":" & @CRLF
                $hList = ControlGetHandle("Client", "", "[CLASS:ListBox; Instance:" & $n & "]")
                $sMsg &= @TAB & "HWND (by Class/Instance) = " & $hList & @CRLF
                $idList = _WinAPI_GetDlgCtrlID($hList)
                $sMsg &= @TAB & "ControlID = " & $idList & "; Type = " & VarGetType($idList) & @CRLF
                $idListInt = Int(String($idList))
                $sMsg &= @TAB & "ControlID (Int) = " & $idListInt & "; Type = " & VarGetType($idListInt) & @CRLF
                $hList = ControlGetHandle("Client", "", "[ID:" & $idListInt & "]")
                $sMsg &= @TAB & "HWND (by ControlID) = " & $hList & @CRLF
                ConsoleWrite($sMsg)
            Next
    EndSwitch
WEnd

I noticed while trying it that in some cases passing an invalid control ID (0) caused the handle to the last control created (the button in GUI above) to be returned. If you are passing the control ID in a variable, make sure it is an integer and the correct ID. Note in my demo where the ControlID returned from _WinAPI_GetDlgCtrlId() has to be converted before it's used.

:)

Edit: Changed handling of $idList to avoid dereferencing a pointer. The pointer only comes up due to a bug in the Production version. It is returned as a correct INT32 type in the current Beta.

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
alext

This works:

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>

GUICreate("Client", 300, 380)
For $n = 1 To 10
    GUICtrlCreateList("List: " & $n, 20, 20 + (($n - 1) * 30), 200, 20)
Next
$idButton_1 = GUICtrlCreateButton("Get Handles", 100, 330, 100, 30)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $idButton_1
            For $n = 1 To 10
                $sMsg = "Instance = " & $n & ":" & @CRLF
                $hList = ControlGetHandle("Client", "", "[CLASS:ListBox; Instance:" & $n & "]")
                $sMsg &= @TAB & "HWND (by Class/Instance) = " & $hList & @CRLF
                $idList = _WinAPI_GetDlgCtrlID($hList)
                $sMsg &= @TAB & "ControlID = " & $idList & "; Type = " & VarGetType($idList) & @CRLF
                $idListInt = Int(String($idList))
                $sMsg &= @TAB & "ControlID (Int) = " & $idListInt & "; Type = " & VarGetType($idListInt) & @CRLF
                $hList = ControlGetHandle("Client", "", "[ID:" & $idListInt & "]")
                $sMsg &= @TAB & "HWND (by ControlID) = " & $hList & @CRLF
                ConsoleWrite($sMsg)
            Next
    EndSwitch
WEnd

I noticed while trying it that in some cases passing an invalid control ID (0) caused the handle to the last control created (the button in GUI above) to be returned. If you are passing the control ID in a variable, make sure it is an integer and the correct ID. Note in my demo where the ControlID returned from _WinAPI_GetDlgCtrlId() has to be converted before it's used.

:)

Edit: Changed handling of $idList to avoid dereferencing a pointer. The pointer only comes up due to a bug in the Production version. It is returned as a correct INT32 type in the current Beta.

;) mmmkay.... the thing is... I don't have an INSTANCE for my object...I only have the ID. So I was trying to get a handle to a control by it's ID. But to make sure I'm not wasting my time I tried getting a handle to a control for which I did know it's INSTANCE and it's ID. (just as a test)

ControlGetHandle("Client","","[iD:302]") and ControlGetHandle("Client","","[CLASS:ListBox;INSTANCE:4]") should return me the same handle...as you can see from the control info ... ID 302 and LISTBOX of Instance 4 are one and the same...

And somehow the handle that I get by an ID is not the same as the one I get by the INSTANCE.

I'm not creating objects (controls) ... I need to be able to control an existing object in an application written in ... I dunno...I don't care.

So basically with an Info tool I get the ID and Instance of a control... and with ControlGetHandle I want a handle (preferably the same handle B) ) once with it's ID and once with it's Instance. Unfortunatly this does not happen...

and I don't know why... It's driving me crazy since I need to get a handle to a control from wich I don't have the INSTANCE...I think it's hidden or something...

Anyway...I appreciate your help!!

Share this post


Link to post
Share on other sites
PsaltyDS

I was only trying to demonstrate that everything worked as advertised in a demo GUI that we could all work with. There was a minor detour into a bug that is irrelevant to this topic. The real point was that we can't reproduce your symptoms. What is the app producing that GUI? If it's something common, we might be able to see it.

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
alext

I was only trying to demonstrate that everything worked as advertised in a demo GUI that we could all work with. There was a minor detour into a bug that is irrelevant to this topic. The real point was that we can't reproduce your symptoms. What is the app producing that GUI? If it's something common, we might be able to see it.

:)

The problem is that this utility I'm trying to control was written sometimes around 200BC or something... it's so ancient I think I can get it sold to an antique store...

Unfortunatly we don't have the code for this tool (as the programmer most likely sat next to Jezus in highschool).

And I can't give this program out ... kinda contains sensitive info about our company... so I guess we're just SOL.

So... I'm not giving you anything to help me am I? Sorry man!

All I know is that I have a ListBox with another ListBox inside of it ... don't know how this works but I have a Info utility that has recognized them (the AI Window Info utility didn't recognize the inner ListBox). The Instance ID for the outer ListBox are in both Info utilities the same... so I guess it's working allright.

So now I have an ID for the inner (hidden?) ListBox... and I would like to get a handle to it.

Maybe this will be fixed (somehow) in a future release of AutoIt.

Thanks anyway!!

Share this post


Link to post
Share on other sites
bo8ster

You will always be able to get the instance using WinGetClassList(). This is how the instance count is generated within AutoIt. You can display the output in an array to see what is going on.


Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic]

Share this post


Link to post
Share on other sites
alext

You will always be able to get the instance using WinGetClassList(). This is how the instance count is generated within AutoIt. You can display the output in an array to see what is going on.

WinGetClassList() only gives me the names of the classes... I don't see the Instance...or is the Instance ID the (0 based) index from the control (from the bottom)?

Share this post


Link to post
Share on other sites
alext

This works:

#include <GuiConstantsEx.au3>
#include <WinAPI.au3>

GUICreate("Client", 300, 380)
For $n = 1 To 10
    GUICtrlCreateList("List: " & $n, 20, 20 + (($n - 1) * 30), 200, 20)
Next
$idButton_1 = GUICtrlCreateButton("Get Handles", 100, 330, 100, 30)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $idButton_1
            For $n = 1 To 10
                $sMsg = "Instance = " & $n & ":" & @CRLF
                $hList = ControlGetHandle("Client", "", "[CLASS:ListBox; Instance:" & $n & "]")
                $sMsg &= @TAB & "HWND (by Class/Instance) = " & $hList & @CRLF
                $idList = _WinAPI_GetDlgCtrlID($hList)
                $sMsg &= @TAB & "ControlID = " & $idList & "; Type = " & VarGetType($idList) & @CRLF
                $idListInt = Int(String($idList))
                $sMsg &= @TAB & "ControlID (Int) = " & $idListInt & "; Type = " & VarGetType($idListInt) & @CRLF
                $hList = ControlGetHandle("Client", "", "[ID:" & $idListInt & "]")
                $sMsg &= @TAB & "HWND (by ControlID) = " & $hList & @CRLF
                ConsoleWrite($sMsg)
            Next
    EndSwitch
WEnd

I noticed while trying it that in some cases passing an invalid control ID (0) caused the handle to the last control created (the button in GUI above) to be returned. If you are passing the control ID in a variable, make sure it is an integer and the correct ID. Note in my demo where the ControlID returned from _WinAPI_GetDlgCtrlId() has to be converted before it's used.

:)

Edit: Changed handling of $idList to avoid dereferencing a pointer. The pointer only comes up due to a bug in the Production version. It is returned as a correct INT32 type in the current Beta.

What if I know the handle of the object from my Info utility? How can i use it to control the object?

Something like

$Handle = 0x00350146

_GuiCtrlListBox.gettext($Handle)

But this doesn't work....

Share this post


Link to post
Share on other sites
PsaltyDS

All I know is that I have a ListBox with another ListBox inside of it ... don't know how this works but I have a Info utility that has recognized them (the AI Window Info utility didn't recognize the inner ListBox). The Instance ID for the outer ListBox are in both Info utilities the same... so I guess it's working allright.

So now I have an ID for the inner (hidden?) ListBox... and I would like to get a handle to it.

Maybe this will be fixed (somehow) in a future release of AutoIt.

Thanks anyway!!

Well now, that's interesting. Rather than one inside the other, it may just be one stacked on top of the other by it's X/Y coordinates. Controls can be "stacked" on GUI just like windows on you desktop, and AU3Info.exe only returns the info for the one at the top of stack (z-order is the term of art).

WinGetClassList() only gives me the names of the classes... I don't see the Instance...or is the Instance ID the (0 based) index from the control (from the bottom)?

Instance numbers are 1-based. If you have the class, you can generate ClassNameNN by trying numbers from 1 to 99 as "ListBox1" thru "ListBox99", or use advanced control IDs as "[CLASS:ListBox; INSTANCE:1]" thru "[CLASS:ListBox; INSTANCE:99]".

What if I know the handle of the object from my Info utility? How can i use it to control the object?

Something like

$Handle = 0x00350146

_GuiCtrlListBox.gettext($Handle)

But this doesn't work....

You can force an HWND type by:
$Handle = Hwnd(0x00350146)
The problem is, you would have to rediscover and reenter the literal handle value every time you ran the program. Handles to windows and controls (controls are just little child windows to the OS) remain fixed for the life of the current instance, but will be different each time they are recreated (running the app again).

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites
bo8ster

WinGetClassList() only gives me the names of the classes... I don't see the Instance...or is the Instance ID the (0 based) index from the control (from the bottom)?

let me demonstrate. The array returned by WinGetClassList() may look something like this

..

ListBox

Button

ListView

ListBox

Button

...

Count how many times the same class appears so you get something like ...

ListBox1

Button1

ListView1

ListBox2

Button2

You can sort the array for ease.

See here for more info _ControlGetClassnameNN()

Edited by bo8ster

Post your code because code says more then your words can. SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y. Use Opt("MustDeclareVars", 1)[topic="84960"]Brett F's Learning To Script with AutoIt V3[/topic][topic="21048"]Valuater's AutoIt 1-2-3, Class... is now in Session[/topic]Contribution: [topic="87994"]Get SVN Rev Number[/topic], [topic="93527"]Control Handle under mouse[/topic], [topic="91966"]A Presentation using AutoIt[/topic], [topic="112756"]Log ConsoleWrite output in Scite[/topic]

Share this post


Link to post
Share on other sites
alext

I appreciate all of you help guys... but it doesn't seem to work like I would like it to.

My info tool shows me 2 ListBoxes (on top of each other or inside of each other) but I starting to think it also might have multiple columns...and from what I've read on this forum, AutoIt does not support ListBoxes with multiple columns.

I think we're just SOL :)

Anyway! Thanks again!

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  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.