Jump to content

Getting currently selected control


Recommended Posts

Hello,

I have been playing around with this a couple ways but wanted to see what you guys recommend.

I want to be able to the menu or control or whatever piece of a window a user has selected.

I can get the current window but I guess the real trick is know what type of control they have open.

What is the right approach for this? Do I try to read what type of controls the window has available and enumerate that?

Thanks

Link to comment
Share on other sites

ControlGetFocus()

:)

Thanks for the help. What I want to do here is determine if the user has selected a different control on the screen.

I had looked at that but wasn't sure what to do with the control ref. When I look at a window this doesn't appear to change when I select different parts of the windoe (IE, I am in notepad and select file and then select view, problem is the same control ref is returned). What can I do with the control ref, getting text appears to use the control ID. Are the two things related?

Also, it looks like ControlGetFocus only does keyboard focus (I might be wrong) is their a way to get whatever the focus is?

thanks again

Playing around with

CODE
$temp=0

$text=ControlGetFocus(WinGetTitle(""), "")

While($temp<10)

MsgBox(0, "", WinGetTitle("") & " has " & $text)

if $text==ControlGetFocus(WinGetTitle(""), "") then

Else

MsgBox(0, "", WinGetTitle("") & " has " & $text)

$text=ControlGetFocus(WinGetTitle(""), "")

EndIf

$temp=$temp+1

Sleep(3000)

WEnd

Link to comment
Share on other sites

Try this:

Opt("WinTitleMatchMode", 4)

Dim $exitTimer = TimerInit()
;$oldWindowInfo[0] = Active Window Handle
;$oldWindowInfo[1] = Active Window Control Focus
Dim $oldWindowInfo[2] = [WinGetHandle("[ACTIVE]"), ControlGetFocus("[ACTIVE]")]

Do
    If $oldWindowInfo[0] = WinGetHandle("[ACTIVE]") And $oldWindowInfo[1] <> ControlGetFocus("[ACTIVE]") Then
        ConsoleWrite("Control focus has changed in window " & @LF & WinGetTitle($oldWindowInfo[0]) & @LF & " from " & @LF & $oldWindowInfo[1] & @LF & _
        " to " & @LF & ControlGetFocus("[ACTIVE]") & @LF & @LF)
        $oldWindowInfo[1] = ControlGetFocus("[ACTIVE]")
    ElseIf $oldWindowInfo[0] <> WinGetHandle("[ACTIVE]") Then
        ConsoleWrite("Window focus has changed from " & @LF & WinGetTitle($oldWindowInfo[0]) & @LF & " to " & @LF & WinGetTitle("[ACTIVE]") & @LF & _
        " new control focused is " & @LF & ControlGetFocus("[ACTIVE]") & @LF & @LF)
        $oldWindowInfo[0] = WinGetHandle("[ACTIVE]")
        $oldWindowInfo[1] = ControlGetFocus("[ACTIVE]")
    Else
        ToolTip("Active window has control " & $oldWindowInfo[1] & " focused")
    EndIf
    Sleep(25)
Until TimerDiff($exitTimer) > 30000 ; 30 Seconds

Edit:

Edited so the code would fit into the forum view..

Edited by FreeFry
Link to comment
Share on other sites

Thanks again for all the help and code.

I think I may have asked my question wrong and/or misunderstand windows GUIs.

In the help for controls I see it says for instance that notepad is one big control. I had some checks for comparing controls but that doesn't appear to much different from just checking to see if the active window is different.

So then how would a person go about finding out what part of the screen or what menu is selected.

I would like to be able to use the same piece of code to know if the current menu is different in IE or notepad or any windows app with standard GUIs and controls.

I also tried getting the current text for a window which is helpful but really doesn't tell me if a certain menu is selected.

Is this possible with autoit? What type of functions should I be looking at?

And again thanks.

Link to comment
Share on other sites

I believe that a control and a menu is two different things...

I guess you'd have to check what window is open, and do assumptions based on what window and/or control is active..

You can retrieve the classname of a control with the UDF _WinAPI_GetClassName, if that's what you want..

For an example(unrelated) of how to retrieve all windows owned by a process with a special classname, one can use this function:

#include <WinAPI.au3>

; All shell windows will be found:
$a = _ProcessGetWinEx(WinGetProcess("Program Manager"))
For $i = 1 To $a[0]
    ConsoleWrite('Window: "' & WinGetTitle($a[$i]) & '" has class: ' & _WinAPI_GetClassName($a[$i]) & @LF)  
Next

; Only the start button will be found:
$a = _ProcessGetWinEx(WinGetProcess("Program Manager"), "Button")
For $i = 1 To $a[0]
    ConsoleWrite('Window: "' & WinGetTitle($a[$i]) & '" has class: ' & _WinAPI_GetClassName($a[$i]) & @LF)  
Next

Func _ProcessGetWinEx($ivPid, $svClass = "")
    
    $ivPid = ProcessExists($ivPid)
    If Not $ivPid Then Return(SetError(1, 0, 0))
    
    Local $avwArray = WinList()
    Local $avRet[1] = [0]
    
    For $i = 1 To $avwArray[0][0]
        If WinGetProcess($avwArray[$i][1]) = $ivPid Then
            If $svClass = "" Or _WinAPI_GetClassName($avwArray[$i][1]) = $svClass Then
                $avRet[0] += 1
                ReDim $avRet[$avRet[0]+1]
                $avRet[$avRet[0]] = $avwArray[$i][1]
            EndIf
        EndIf
    Next
    
    Return $avRet
    
EndFunc
Link to comment
Share on other sites

I posted this yesterday and I am not sure if I asked the question correctly.

http://www.autoitscript.com/forum/index.php?showtopic=67100

what I want to get is if a new button or menu or any sort of item is opened by the user.

I know how to see if the active window has changed but how would I for instance in notepad if a user selects File or selects View (is same control). Can Autoit get this information and what approach could I use to get it?

Thanks

Check out the _GuiCtrlMenu_* functions, probably leading to _GuiCtrlMenu_GetItemState().

:)

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

FreeFry thanks again.

A couple questions.

I have played with get class name but wasn't sure exactly what that was (you are getting the class names but what does that mean?). If I get all the class names for an active window does that mean I can somehow plug those classes back in somewhere?

You were talking about assumptions for window types does that mean for example if the window name starts with Internet Explorer I can look for Web controls and menus or was that about something else?

Edited by maestro1024
Link to comment
Share on other sites

FreeFry thanks again.

A couple questions.

I have played with get class name but wasn't sure exactly what that was (you are getting the class names but what does that mean?). If I get all the class names for an active window does that mean I can somehow plug those classes back in somewhere?

Sorry, I might have misunderstood what you wanted there. Sorry, my example code was more related to the assumptions you could make based on what classname the window has...

You were talking about assumptions for window types does that mean for example if the window name starts with Internet Explorer I can look for Web controls and menus or was that about something else?

Well, you could get the classname of the window with the previously mentioned _WinAPI_GetClassName, and then you can make assumptions based on what "type" of classname it has(note that _WinAPI_GetClassName also works on controls, etc.), but a internet explorer window has only a few controls, the main one(ie. the part where you do the actual surfing in) is called "Internet Explorer_Server", but you can't use most of the WinX and ControlX functions on it..

If what you really want is to automate the web browser, you should look into the IE UDFs..

Sorry for any confusion I might have caused you. :/

Edited by FreeFry
Link to comment
Share on other sites

Thanks again. You guys have been very helpful. I am thinking maybe I can create a test app (some menus in C#) and see if I can get the menus,etc from it.

Maybe this isn't possible in AutoIt (which is fine, I wouldn't want to bang my head too hard if it is not even possible).

I don't actually have to have the names of menus but just need to know if they change.

I was playing with this hoping to see different info when I play this and select drop downs on notepad or IE. Problem is I didn't see a difference when selecting different drop downs.

CODE
#include "GuiMenu.au3"

$temp=0

While($temp<7)

; $title = WinGetClassList(WinGetTitle(""), "")

; FileWriteLine("test.txt","Text read was:"& $text)

$hWnd = WinGetHandle(WinGetTitle(""))

FileWrite("test.txt", "Title: " & WinGetTitle(""))

$hMain = _GUICtrlMenu_GetMenu ($hWnd)

$hFile = _GUICtrlMenu_GetItemSubMenu ($hMain, 2)

$state= _GuiCtrlMenu_GetItemState($hFile,$hFile)

FileWriteLine("test.txt","Window: " & $hWnd & " Menu : " & $hMain & " Sub Menu: " & $hFile & " State " & $state)

$temp=$temp+1

Sleep(2000)

WEnd

Link to comment
Share on other sites

Try this:

#include <GuiMenu.au3>

Sleep(2500) ; To allow time to activate a window..
$hMain = _GUICtrlMenu_GetMenu (WinGetHandle(""))

$Timer = TimerInit()

For $i = 0 To _GUICtrlMenu_GetItemCount($hMain)
    ConsoleWrite("Detected a menu item: " & _GUICtrlMenu_GetItemText($hMain, $i) & @LF)
    $subMenu = _GUICtrlMenu_GetItemSubMenu($hMain, $i)
    For $x = 0 To _GUICtrlMenu_GetItemCount($subMenu)
        ConsoleWrite(@TAB & "Detected a sub-menu item: " & _GUICtrlMenu_GetItemText($subMenu, $x) & @LF)
    Next
Next

Do
    For $i = 0 To _GUICtrlMenu_GetItemCount($hMain)
        $subMenu = _GUICtrlMenu_GetItemSubMenu($hMain, $i)
        For $x = 0 To _GUICtrlMenu_GetItemCount($subMenu)
            If BitAND(_GUICtrlMenu_GetItemState($subMenu, $x), 16) Then
                ConsoleWrite(_GUICtrlMenu_GetItemText($subMenu, $x) & @TAB & "is Highlighted" & @LF)
            EndIf
        Next
    Next
Until TimerDiff($Timer) > 12500 ; 12.5 Seconds

I tested it on SciTE, and it works fine there..

Edit: I noticed a small error I made in the code, it was supposed to use BitAND against the item state, not comparing it to 16 directly..

Edited by FreeFry
Link to comment
Share on other sites

CODE
BitAND(_GUICtrlMenu_GetItemState($subMenu, $x),16 )

Not sure I follow on the bitAnd

you have the itemstate which makes sense

Help says "16 - Item is highlighted"

Doesn't that mean if it is highlighted the function will return that and the code would be correct?

Link to comment
Share on other sites

Also, wanted to make sure I understand what you did here.

Tell me if I am wrong. I played with this some and looked up the function calls but I still might be mising something.

You get all of the current menus and sub-menus for the current window.

And then you look at every one of those menus to see if they are currently highlighted.

Please correct me if I am wrong.

This is where the assumption about window type comes in. This code should work on a standard windows app with menus but will definately not work on an IE page.

Link to comment
Share on other sites

Also, wanted to make sure I understand what you did here.

Tell me if I am wrong. I played with this some and looked up the function calls but I still might be mising something.

You get all of the current menus and sub-menus for the current window.

And then you look at every one of those menus to see if they are currently highlighted.

That's correct.

Please correct me if I am wrong.

This is where the assumption about window type comes in. This code should work on a standard windows app with menus but will definately not work on an IE page.

Well, as far as I know, all windows that has a menu should be able to be 'automated' this way, but then again, if what you're trying to do is to see/handle the content on a webpage these functions will not work..

CODE
BitAND(_GUICtrlMenu_GetItemState($subMenu, $x),16 )
Not sure I follow on the bitAnd

you have the itemstate which makes sense

Help says "16 - Item is highlighted"

Doesn't that mean if it is highlighted the function will return that and the code would be correct?

The helpfile also says "Can be one or more of the following:"

Which means that it can be a combination(added together I believe) of those values. What BitAND does is check if has the value 16 in it. If you want to see an example in the helpfile of another similar scenario have a look at WinGetState.

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...