3

I would like to obtain the current Position (progress) property value from TProgressBar1, which is a child of TProgressFrame1 and grandchild of TPanel1 within a particular TProgressDlg Window. TProgressBar is a class defined in Delphi, and TProgressBar1 is a specific instance that AutoHotkey "sees" with its own HWnd.

Is it possible to grab the TProgressBar1.Position value from an external application with AutoHotkey?

I've tried

; AutoHotkey Version: 1.1.22.07 
DetectHiddenWindows, On
SetTitleMatchMode, RegEx
GroupAdd, MyGroup, ahk_exe [partial path of executable], , , ahk_exe explorer.exe ; exclude any explorer windows open to that path.
WinGet, x, List, ahk_group MyGroup
Loop, %x% ; This application has 68-73 windows, most hidden, when it runs
{
    this_id := x%A_Index%
    WinGetTitle wtit, ahk_id %this_id%
    WinGet, clh, ControlListHwnd, ahk_id %this_id% ;%wtit%, %wtxt%
    StringSplit, clh_, clh, `n
    Loop, %clh_0% ; the 0th entry contains the size of the array this loop iteration. Don't want to loop through all in %clh_ as previous iterations may have stored more values at haven't been cleared.
    {
        clh_cur := clh_%A_Index%
        IfEqual, cl_%A_Index%, TProgressBar1
        {
            B := cl_%A_Index% ; TProgressBar1
            C := %B%.Position ; Expecting something like 60 (percent). I could also divide by %B%.Max to make sure what the range is, assuming I could get values  like this.
            MsgBox "%B% is %C% percent complete"
        }
    }
}
return

%C% comes out blank, whereas %B% is indeed TProgressBar1

It looks like in native Delphi, this would look something like (from here)

 aPB := TProgressBar(FindComponent('Progress')) ;
 curValue := aPB.Position

Delphi codeusage doc for the property link indicates that something like
curValue := TProgressBar1.Position would work

Do I use something like

  1. ComObjGet? or
  2. TProgressBar1.__Get(Position)? or
  3. SendMesssage, 0x03E6, clh_%A_Index%, 0x03330600 ;*? (and/or any of the above with...)
  4. cpy := TProgressBar1.Clone() first?

WM_DDE_REQUEST = 0x03E6
TProgressBar has a Properties value of Delphi00001514 0x03330600 (53675520)

I have since tried some iterations of 3 and 4, but I may be doing it wrong, as there's no evidence that the MyMessageMonitor (below) is ever called. Here's what I've tried:

WM_DDE_INITIATE   := 0x3E0
WM_DDE_TERMINATE:= 0x3E1
WM_DDE_ADVISE   := 0x3E2
WM_DDE_UNADVISE   := 0x3E3
WM_DDE_ACK   := 0x3E4
WM_DDE_DATA   := 0x3E5
WM_DDE_REQUEST   := 0x3E6
WM_DDE_POKE   := 0x3E7
WM_DDE_EXECUTE   := 0x3E8

OnMessage(0x03E05, "MyMessageMonitor") ; WM_DDE_DATA by MSDN's definition
OnMessage(WM_DDE_DATA, "MyMessageMonitor") ; WM_DDE_DATA there's a post "correcting" MSDN's value at bottom, so may as well look for both
OnMessage(0x03E4, "MyMessageMonitor") ; WM_DDE_ACK

...

; IfEqual block innards
        nAppli := DllCall("GlobalAddAtom", "str", [application exe name, minus .exe], "Ushort")
        nDDE_Topic := DllCall("GlobalAddAtom", "str", [application exe name, minus .exe], "Ushort")
        SendMessage, WM_DDE_INITIATE, A_ScriptHwnd, nAppli | nDDE_Topic << 16,,ahk_id %clh_cur%
        B := cl_%A_Index%
        Bh := clh_%A_Index%
        C := %Bh%.Clone()
        D := %C%.__Get("Position")
        E := IsObject(%C%)
        F := %Bh%["Position"]
        SendMessage, 0x03E6, A_ScriptHwnd,  0x03330600, cl_%A_Index%, ahk_id %this_id% ; send WM_DDE_REQUEST from current window to TProgressBar1
        MsgBox "%B% has position value %D% or %F%. %B% an object? %E%" ; brings up box with "TProgressBar1 has position value  or . TProgressBar1 an object? 0"
        DllCall("DeleteAtom", "Ushort", nAppli)
        DllCall("DeleteAtom", "Ushort", nDDE_Topic)
...
OnMessage(0x03E05, "")
OnMessage(0x03E5, "") ; WM_DDE_DATA
OnMessage(WM_DDE_ACK, "") ; 0x03E4
return

MyMessageMonitor(wParam, lParam, msg, hwnd)
{
    MsgBox "w: " . wParam . " l: " . lParam . " msg: " . msg . " hwnd: " . hwnd
    return
}
mpag
  • 315
  • 3
  • 16

0 Answers0