Jump to content

On _Singleton and Control IDs


Recommended Posts

Hello. I have a few claryfing questions regarding some stuff in AutoIt.

About _Singleton, how is it supposed to be used? Is the first "text" parameter supposed to be some text in particular or can it be any string I want, so long as it is unique?

Is the following line of code enough to prevent running of multiple instances of my script?

_Singleton("some text i made up")

As for control IDs, are they constant for a particular instance of a control in a program? Does the ID change across different runs of the program? Does it change between different simultaneously running instances of the program?

Also, what's the process involved in getting the ID of the control under my mouse pointer, like the one in Window Info Tool? I've read on how to get the control ID of a control that has keyboard focus, but I need to learn how to do it for mouseovers.

Help please. Thank you.

Link to comment
Share on other sites

About _Singleton: You can use any "string" to identify the occurrence of the script.

See example in the AutoIt Help File.

About "getting the ID of the control under my mouse pointer": You an use GUIGetCursorInfo( [winhandle] ), but

the mouse cursor position is successful only on an window created by a GUICreate.

This function returns a five-element array that containing the mouse cursor information:

$array[4] = ID of the control that the mouse cursor is hovering over (or 0 if none).

http://forum.autoitbrasil.com/ (AutoIt v3 Brazil!!!)

Somewhere Out ThereJames Ingram

somewh10.png

dropbo10.pngDownload Dropbox - Simplify your life!
Your virtual HD wherever you go, anywhere!

Link to comment
Share on other sites

Hello. I have a few claryfing questions regarding some stuff in AutoIt.

About _Singleton, how is it supposed to be used? Is the first "text" parameter supposed to be some text in particular or can it be any string I want, so long as it is unique?

Is the following line of code enough to prevent running of multiple instances of my script?

_Singleton("some text i made up")

As for control IDs, are they constant for a particular instance of a control in a program? Does the ID change across different runs of the program? Does it change between different simultaneously running instances of the program?

Also, what's the process involved in getting the ID of the control under my mouse pointer, like the one in Window Info Tool? I've read on how to get the control ID of a control that has keyboard focus, but I need to learn how to do it for mouseovers.

Help please. Thank you.

A lot of questions there esp for someone starting new so I hope you understand it all.

1.) Singleton, what jscript said - the help file should explain everything else. Run the example script.

2.) 99% of the time, Control IDs do not change. To get the control you must know the control handle which is a child to a window instance, thus you cannot get them mixed up.

3.) GetDlgCtrlID or _WinAPI_GetDlgCtrlID will give you the Control ID based on a control handle. I have a script in my sig "Control Handle under mouse" that gets this type of info. The process simply is, get the Window Handle, get the Control handle then get the ControlID.

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]

Link to comment
Share on other sites

Thank you for the help.

I'm not exactly new to AutoIt. I've done a few minor scripts in the past, but this will be the first time I'm doing so with serious effort.

I'm trying to make a script that will help me make automation scripts for my program installations. I've already got working parts, the only things missing are interpreting key presses from keycodes from lParams for WM_KEYDOWN and WM_SYSKEYDOWN, and getting IDs of controls on mouse click.

Edited by omikron48
Link to comment
Share on other sites

nps, if you have any issues, post your code >_

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]

Link to comment
Share on other sites

I looked at your 'control handle under mouse' script and tried incorporating it. AmI supposed to feed the [0] element of _Mouse_Control_GetInfo() into _WinAPI_GetDlgCtrlID to get the control ID?

That's what I did and I don't seem to be getting the correct result when I tried it on windows calculator.

Am I doing something wrong? I copied the code as is, omitting this section:

AdlibEnable("_Mouse_Control_GetInfoAdlib", 10)
HotKeySet("^!x", "MyExit") ; Press Ctrl+Alt+x to stop the script

Global $pos1 = MouseGetPos()
Global $pos2 = MouseGetPos() ; must be initialized
Global $appHandle = 0

While 1
    Sleep(0xFFFFFFF)
WEnd

; ===============================================================================
;~ Retrieves the information of a Control located under the mouse and displayes it in a tool tip next to the mouse.
;~ Function uesd
;~  _Mouse_Control_GetInfo()
;~  GetDlgCtrlID
; ===============================================================================
Func _Mouse_Control_GetInfoAdlib()

and placing this at the top of my script:

#include <WinAPI.au3>
#include <Array.au3>
AutoItSetOption("MustDeclareVars", 1)
AutoItSetOption("MouseCoordMode", 2)
Global $appHandle = 0

I'm using this to get the control ID:

Func MouseGetControlID()
    Local $cInfo = _Mouse_Control_GetInfo()
    Return _WinAPI_GetDlgCtrlID($cInfo[0])
EndFunc

Can I even post my script here in the forums? Technically, my script does some input logging but the purpose of it is not for malicious keylogging, rather installation procedure tracking.

EDIT: I forgot to mention. I notice that there are LuCallbackProxy.exe(s) remaining everytime my script closes. What did I forget to do?

EDIT2: I isolated the event of LuCallbackproxy.exe being left running being caused by my addition of the 'control handle under mouse' code.

I tried to code the same process using _WinAPI_<method>. Did I understand it correctly? It seems to not want to work.

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>
Opt('MouseCoordMode', 2)

...<other code>...

Func GetMouseOverCID()
    Local $mpos = MouseGetPos()
    Local $tPointC = DllStructCreate($tagPOINT)
    DllStructSetData($tPointC, 1, $mpos[0])
    DllStructSetData($tPointC, 2, $mpos[1])
    Local $ptrTPC = DllStructGetPtr($tPointC)
    Local $mwHandle = _WinAPI_WindowFromPoint($ptrTPC)
    If($mwHandle == 0) Then
        SetError(1)
        Return 0
    EndIf
    Local $tPointS = DllStructCreate($tagPOINT)
    DllStructSetData($tPointS, 1, $mpos[0])
    DllStructSetData($tPointS, 2, $mpos[1])
    Local $ptrTPS = DllStructGetPtr($tPointS)
    Local $check = _WinAPI_ClientToScreen($mwHandle, $ptrTPS)
    If $check == 0 Then
        SetError(1)
        Return 0
    EndIf
    Local $mcHandle = _WinAPI_WindowFromPoint($ptrTPS)
    If($mcHandle == 0) Then
        SetError(1)
        Return 0
    EndIf
    Return $mcHandle
EndFunc

The aim is for $mcHandle to contain the handle for the control under the mouse. I think I followed the same procedure as the sample script of bo8ster. I may be wrong though.

Edited by omikron48
Link to comment
Share on other sites

  • Moderators

omikron48,

Please do not bump your posts within 24 hrs. Remember this is not a 24/7 support forum - those who answer are only here because they like helping others and have some time to spare. You just have to wait until someone who knows something about your particular problem, and is willing to help, comes online. Be patient and someone will answer eventually. Or if not - tough! >_<

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

The reason why you are having trouble with my script is, its not as simple as you think. I have removed the use of client coords and ClassNN.

WindowFromPoint returns a pointer to the window, not to a control, so $mcHandle will never reference a control.

As you can see, I am using DLLCals, the same thing is done in the WinAPI functions, they are just a wrapper.

Try this

AutoItSetOption("MustDeclareVars", 1)
AdlibEnable("_Mouse_Control_GetInfoAdlib", 10)
HotKeySet("^!x", "MyExit") ; Press Ctrl+Alt+x to stop the script

Global $pos1 = MouseGetPos()
Global $pos2 = MouseGetPos() ; must be initialized
Global $appHandle = 0

While 1
    Sleep(0xFFFFFFF)
WEnd

; ===============================================================================
;~ Retrieves the information of a Control located under the mouse and displayes it in a tool tip next to the mouse.
;~ Function uesd
;~  _Mouse_Control_GetInfo()
;~  GetDlgCtrlID
; ===============================================================================
Func _Mouse_Control_GetInfoAdlib()
    $pos1 = MouseGetPos()
    If $pos1[0] <> $pos2[0] Or $pos1[1] <> $pos2[1] Then ; has the mouse moved?
        Local $a_info = _Mouse_Control_GetInfo()
        Local $aDLL = DllCall('User32.dll', 'int', 'GetDlgCtrlID', 'hwnd', $a_info[0]) ; get the ID of the control
        If @error Then Return
        ToolTip("Handle = " & $a_info[0] & @CRLF & _
                "Class = " & $a_info[1] & @CRLF & _                
                "ID = " & $aDLL[0] & @CRLF & _
                "Mouse X Pos = " & $a_info[2] & @CRLF & _
                "Mouse Y Pos = " & $a_info[3] & @CRLF & _
                "Parent Hwd = " & $appHandle)
        $pos2 = MouseGetPos()
    EndIf
EndFunc   ;==>_Mouse_Control_GetInfoAdlib

; ===============================================================================
;~ Retrieves the information of a Control located under the mouse.
;~ Uses Windows functions WindowFromPoint and GetClassName to retrieve the information.
;~ Functions used
;~  _GetHoveredHwnd()
;~  _ClientToScreen()
;~ Returns
;~   [0] = Control Handle of the control
;~   [1] = The Class Name of the control
;~   [2] = Mouse X Pos (converted to Screen Coord)
;~   [3] = Mouse Y Pos (converted to Screen Coord)
; ===============================================================================
Func _Mouse_Control_GetInfo()
    $appHandle = GetHoveredHwnd() ; Uses the mouse to do the equivalent of WinGetHandle()
    Local $a_mpos = MouseGetPos() ; gets client coords because of "MouseCoordMode" = 2
    ConsoleWrite("AppHandle is : " & $appHandle & @LF)
;~     Local $a_mpos = _ClientToScreen($appHandle, $client_mpos[0], $client_mpos[1]) ; $a_mpos now screen coords
    If @error Then Return SetError(1, 0, 0)
    Local $a_wfp = DllCall("user32.dll", "hwnd", "WindowFromPoint", "long", $a_mpos[0], "long", $a_mpos[1])
    If @error Then Return SetError(2, 0, 0)
    Local $t_class = DllStructCreate("char[260]")
    DllCall("User32.dll", "int", "GetClassName", "hwnd", $a_wfp[0], "ptr", DllStructGetPtr($t_class), "int", 260)
    Local $a_ret[4] = [$a_wfp[0], DllStructGetData($t_class, 1), $a_mpos[0], $a_mpos[1]]
    Return $a_ret
EndFunc   ;==>_Mouse_Control_GetInfo

; ===============================================================================
; Retrieves the Handle of GUI/Application the mouse is over.
; Similar to WinGetHandle except it used the current mouse position (Client Coords)
; Taken from http://www.autoitscript.com/forum/index.php?showtopic=444962
; ===============================================================================
Func GetHoveredHwnd()
    Local $iRet = DllCall("user32.dll", "int", "WindowFromPoint", "long", MouseGetPos(), "long", MouseGetPos())
    If IsArray($iRet) Then
        $appHandle = $iRet[0]
        Return HWnd($iRet[0])
    Else
        Return SetError(1, 0, 0)
    EndIf
EndFunc   ;==>GetHoveredHwnd

Func MyExit() ; stops the script
    ConsoleWrite("Script Stoppted By User" & @CR)
    Exit
EndFunc   ;==>MyExit

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]

Link to comment
Share on other sites

Thank you very much.

I tried it and it works. Don't know how it can be done using _WinAPI_<> though. All I notice is that the return type for WindowFromPoint differs when getting the window handle and the control handle.

I've almost got my script fully working. The only thing missing before it can be fully functional is getting the title and text of the window under the mouse. Is there a way to get the window title and text using a window handle returned by the first WindowFromPoint call?

As it is, I can only get the window title and text of the last active window before the mouse click, so if there was a change in active window, it would only be seen after processing of the mouse click.

Again,thanks a whole lot. >_<

Link to comment
Share on other sites

_WinAPI_GetWindowText?

It sounds more like a logic issue, you are not updating the window handle when the mouse moves at the right time.

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]

Link to comment
Share on other sites

I'm not updating anything when the mouse moves. I made a hook for the mouse and process getting the control ID on mouse click.

This is why I can't use the ative window information since my code runs after the mouse click but before the change in active windows.

All that's left now is polshing the code and finding a better way of making sense of keyboard input lParams

Link to comment
Share on other sites

well, run the WindowFromPoint in the mouse click event, so you have everything you need at that time.

Its hard to really help without seeing the code. You can post your script here, key logging is banded (like logging every key) but logging results is not. If you post something that the mods don't like, they will tell you. If it is really bad they may just remove the offending section of code from ur post.

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]

Link to comment
Share on other sites

Ok then, here goes...

#include <Misc.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <StructureConstants.au3>

Opt('MustDeclareVars', 1)

Global $appHandle = 0

... <other code> ...

;Callback process for mouse
Func _MouseProc($mCode, $mwParam, $mlParam)
    Local $tMSLL, $mX, $mY, $cID
    
    If $mCode < 0 Then
    Return _WinAPI_CallNextHookEx($mHook, $mCode, $mwParam, $mlParam)
    EndIf
    
    $tMSLL = DllStructCreate($tagMSDLLHOOKSTRUCT, $mlParam)
    $mX = DllStructGetData($tMSLL, 1)
    $mY = DllStructGetData($tMSLL, 2)
    
    Switch $mwParam 
        Case $WM_LBUTTONDOWN
            LogWriteLine("Left clicked at: (" & $mX & ", " & $mY & ")")
            LogWriteLine("<Mouse Clicked>" & @CRLF & GetMouseOverDetail())
        Case $WM_RBUTTONDOWN
            LogWriteLine("Right clicked at: (" & $mX & ", " & $mY & ")")
            LogWriteLine("<Mouse Clicked>" & @CRLF & GetMouseOverDetail())
    EndSwitch
    
    Return _WinAPI_CallNextHookEx($mHook, $mCode, $mwParam, $mlParam)
EndFunc

;Returns mouse over details
Func GetMouseOverDetail()
    Local $mInfo = _Mouse_Control_GetInfo()
    Local $cID = DllCall('User32.dll', 'int', 'GetDlgCtrlID', 'hwnd', $mInfo[0])
    If @error == 0 Then
        Local $cText = _WinAPI_GetWindowText($mInfo[0])
        Local $text = @TAB & "Control ID: " & $cID[0] & @CRLF & @TAB & "Control Text: " & """" & $cText & """"
    EndIf
    Return $text
EndFunc

When I tried using $appHandle for _WinAPI_GetWindowText but I keep getting the same handle no matter where I move my mouse and click. I'm getting the correct control ID and handle, but I can get the actual handle of the window I click on.

Edited by omikron48
Link to comment
Share on other sites

If you know you are getting the correct control handle, look at _WinAPI_GetAncestor and _WinAPI_GetParent

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]

Link to comment
Share on other sites

I made some small changes - look at ControlGetText. It is either the text within a control or the title of a window - different functions for each.

;Returns mouse over details
Func GetMouseOverDetail()   
    Local $mInfo = _Mouse_Control_GetInfo()
    Local $cID = DllCall('User32.dll', 'int', 'GetDlgCtrlID', 'hwnd', $mInfo[0])
    
    $appHandle = DllCall("user32.dll", "int", "WindowFromPoint", "long", MouseGetPos(), "long", MouseGetPos())
    
    If @error == 0 Then
        Local $cText = ControlGetText($mInfo[0])
        Local $text = @TAB & "Control ID: " & $cID[0] & @CRLF & @TAB & "Control Text: " & """" & $cText & """" & " App Handle text: " & _WinAPI_GetWindowText($appHandle)
        
    EndIf
    Return $text
EndFunc

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]

Link to comment
Share on other sites

To make it clear control ID does not change it is static even you close the program and run again.

It will assign first come first serve like

$h1 = GUI1...

$h2 = GUI2...

$h2 = GUI2...

$h1 = GUI1...

This is not the same as GUI2 comes before GUI1 so GUI2 got the first ID

Link to comment
Share on other sites

To make it clear control ID does not change it is static even you close the program and run again.

It will assign first come first serve like

$h1 = GUI1...

$h2 = GUI2...

$h2 = GUI2...

$h1 = GUI1...

This is not the same as GUI2 comes before GUI1 so GUI2 got the first ID

Not in every case, but in most. The app I work with changes every time it loads - very annoying.

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]

Link to comment
Share on other sites

Finally worked right. Apparently you had to use the $GA_ROOT flag for GetAncestor

Local $wHandle = _WinAPI_GetAncestor($mInfo[0], $GA_ROOT)
Local $wTitle = _WinAPI_GetWindowText($wHandle)
Local $wText = StringLeft(WinGetText($wTitle), 100)

I constantly check my active window so I have a basis for comparison for what I should be getting from my window handle.

Local $isChanged
    While(1)
        $isChanged = False
        $currTitle = WinGetTitle("[ACTIVE]")
        $currText = StringLeft(WinGetText("[ACTIVE]"), 100)
        $currHandle = WinGetHandle("[ACTIVE]")
        If StringCompare($currTitle,  $prevTitle) <> 0 Then
            LogWriteLine("Active Window Title Changed!")
            $prevTitle = $currTitle
            $isChanged = True
        EndIf
        If StringCompare($currText, $prevText) <> 0 Then
            LogWriteLine("Active Window Text Changed!")
            $prevText = $currText
            $isChanged = True
        EndIf
        If StringCompare($currHandle,  $prevHandle) <> 0 Then
            LogWriteLine("Active Window Handle Changed!")
            $prevHandle = $currHandle
            $isChanged = True
        EndIf
        If $isChanged Then
            LogWriteLine("<Active Window Changed>" & @CRLF & GetCurrentDetail())
        EndIf
        Sleep(100)
    WEnd
Edited by omikron48
Link to comment
Share on other sites

Sounds right, great to hear that you got it working.

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]

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