ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 07 Jan 2021, 08:41

Hallo,

ich habe wieder mal eine Frage, wo ich eure Hilfe brauche.

Ich habe ein Java Windows Programm, wo es eine Klasse ToolbarWindow321 gibt. In dieser sind mehrere Buttons integriert. (Siehe Farben)
Image

Nun möchte ich diese einzelnen Reiter auslesen ( haben alle eine Bezeichnung ) und, je was für eine Bezeichnung diese einzelnen TAB/Buttons haben, diesen dann schliessen.
Dazu gibt es schon eine Möglichkeit bei WinSpyM, wo ich den Namen des TAB/Button auslesen kann.

https://www.autohotkey.com/boards/search.php?author_id=82923&sr=posts
Übrigens eine richtig gute Ergänzung zu Windowws Spy!
Dazu nur das betreffende Codeschnipsel.

Code: Select all

Test := WinExist(" jp2launcher.exe")
WinActivate, ahk_id %Test%
ControlGet, g_hWnd, hWnd,,ToolbarWindow321, ahk_id %Test%


        ToolbarItems := GetToolbarItems(g_hWnd)
        For Each, Item in ToolbarItems {
            MsgBox % "Zeilennummer " A_LineNumber  " und Ergebnis :  A_Index: " A_Index " Item.ID: " Item.ID " Item.String: " Item.String
			
        }
return

GetToolbarItems(hToolbar) {
	WinGet PID, PID, ahk_id %hToolbar%

    If !(hProc := DllCall("OpenProcess", "UInt", 0x438, "Int", False, "UInt", PID, "Ptr")) {
        Return
    }

    If (A_Is64bitOS) {
        Try DllCall("IsWow64Process", "Ptr", hProc, "Int*", Is32bit := true)
    } Else {
        Is32bit := True
    }

    RPtrSize := Is32bit ? 4 : 8
    TBBUTTON_SIZE := 8 + (RPtrSize * 3)

    SendMessage 0x418, 0, 0,, ahk_id %hToolbar% ; TB_BUTTONCOUNT
    ButtonCount := ErrorLevel

    IDs := [] ; Command IDs
    Loop %ButtonCount% {
        Address := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "UPtr", TBBUTTON_SIZE, "UInt", 0x1000, "UInt", 4, "Ptr")

        SendMessage 0x417, % A_Index - 1, Address,, ahk_id %hToolbar% ; TB_GETBUTTON   ; Wird die Reihenfolge der Id's ermiitelt zum A_index
        If (ErrorLevel == 1) {
            VarSetCapacity(TBBUTTON, TBBUTTON_SIZE, 0)
            DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", Address, "Ptr", &TBBUTTON, "UPtr", TBBUTTON_SIZE, "Ptr", 0)
            IDs.Push(NumGet(&TBBUTTON, 4, "Int"))
        }

        DllCall("VirtualFreeEx", "Ptr", hProc, "Ptr", Address, "UPtr", 0, "UInt", 0x8000) ; MEM_RELEASE
    }

    ToolbarItems := []
    Loop % IDs.Length() {
        ButtonID := IDs[A_Index]
        ;~ SendMessage 0x44B, %ButtonID% , 0,, ahk_id %hToolbar% ; TB_GETBUTTONTEXTW
        ;BufferSize := ErrorLevel * 2

        BufferSize := 128

        Address := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "UPtr", BufferSize, "UInt", 0x1000, "UInt", 4, "Ptr")

        SendMessage 0x44B, %ButtonID%, Address,, ahk_id %hToolbar% ; TB_GETBUTTONTEXTW

        VarSetCapacity(Buffer, BufferSize, 0)
        Test := DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", Address, "Ptr", &Buffer, "UPtr", BufferSize, "Ptr", 0)
		MsgBox % "Zeilennummer " A_LineNumber  " und Ergebnis : " Buffer
        ToolbarItems.Push({"ID": IDs[A_Index], "String": Buffer})

        DllCall("VirtualFreeEx", "Ptr", hProc, "Ptr", Address, "UPtr", 0, "UInt", 0x8000) ; MEM_RELEASE
    }

    DllCall("CloseHandle", "Ptr", hProc)
	
	
	  For Each, Item in ToolbarItems {
            MsgBox % "Zeilennummer " A_LineNumber  " und Ergebnis :  A_Index: " A_Index " Item.ID: " Item.ID " Item.String: " Item.String
	}
    Return ToolbarItems
}
Dazu nun meine Frage.

Ich verstehe einfach nicht, wieso ich den Namen des jeweiligen Buttons in diesem Schnipsel nicht über die Msgbox abfragen kann, sonder dafür extra eine FOR Schleife laufen lassen muss. Was ist mein Denkfehler?

und 2. Frage.: Wie kann ich dann den betroffnenen Button schliessen?

Danke Bert
Attachments
ToolbarWindow321.jpg
ToolbarWindow321.jpg (2.6 KiB) Viewed 2152 times
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 08 Jan 2021, 04:11

Moin,

ich weiß nicht, ob ich Deine Fragen richtig verstehe.

Zur For-Schleife:

Die Funktion GetToolbarItems() liefert ein 'einfaches' Array' von 'assoziativen' Arrays:

Code: Select all

        +-> ID     -> Wert
Index ->+
        +-> String -> Wert
Für das 'einfache' Array brauchst Du keine For-Schleife. Die Anzahl der Elemente und damit der Bereich der gültigen Indices lassen sich über Array.Length() bestimmen. Für Indices im Bereich von 1 bis Array.Length() kannst Du dann auch direkt auf das Array zugreifen:

Code: Select all

ID := ToolbarItems[Index, "ID"]

Zur zweiten Frage:
Was heißt hier: "Wie kann ich dann den betroffnenen Button schliessen?". "Schliessen"ist im Zusammenhang mit Buttons ein recht unüblicher Begriff.
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 08 Jan 2021, 07:56

Hallo Just me,

danke fürs darüber lesen.
zu 1. Das weiss ich. Ich habe aber das Problem, dass mit

Code: Select all

DllCall("ReadProcessMemory", "Ptr", hProc, "Ptr", Address, "Ptr", &Buffer, "UPtr", BufferSize, "Ptr", 0)
der Name des Buttons abgefragt wird.
Wenn ich aber mit :

Code: Select all

 MsgBox % "Zeilennummer " A_LineNumber  " und Ergebnis : " Buffer
diesen abfrage erhalte ich nicht den Namen, sondern nur den 1. Buchstaben des Namens des Controlls ( Beispiel : B ) .
Mit dem Array in der Funktion bekomme ich den vollen Namen ( Beispiel : Beschreibung ) . Wie kann ich erreichen , dass ich auch mit der MSGbox den vollen Namen abfragen kann?

2.
Ich kann mit

Code: Select all

SendMessage, 0x416, 3, 0,, ahk_id %g_hWnd%

problemlos in der Klasse ToolbarWindow321 die einzelnen Buttons löschen. Ich erwische aber da die falschen, weil ich die richtige id des einzelnen Buttons nicht greifen kann bzw. nicht zuordnen kann.

Danke

Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 08 Jan 2021, 09:41

Code: Select all

  SendMessage 0x44B, %ButtonID%, Address,, ahk_id %hToolbar% ; TB_GETBUTTONTEXTW
TB_GETBUTTONTEXTW ist die Unicodeversion der Nachricht. Setzt Du ein Unicode-Ahk ein?

Code: Select all

SendMessage, 0x416, 3, 0,, ahk_id %g_hWnd%
TB_DELETEBUTTON erwartet im ersten Parameter den Index des Buttons, nicht seine ID. Wenn Du nur die ID hast, kannst Du Dir mit TB_COMMANDTOINDEX (0x0419) den zugehörigen Index holen.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 08 Jan 2021, 09:53

Noch etwas: Wenn Du den Inhalt einer AHK-Variablen (hier: Buffer) über ihre Adresse (&Buffer) veränderst, werden die Kapazität und die intern verwaltete Stringlänge nicht angepasst. Wenn bei Dir alles Unicode ist, könnte ein VarSetCapacity(Buffer, -1) helfen.
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 11 Jan 2021, 07:44

Danke Dir, ich bin einen Schritt weiter gekommen. :)
die Lösung war

Code: Select all

VarSetCapacity(Buffer, -1)
:bravo:
Jetzt noch eine Frage: Wie kann ich anstatt zu löschen, diesen Button aktivieren und in den Vordergrund bringen ( also genau so, als wenn ich den Button mit der Maus anklicken würde)?
Das brauche ich, um in den Tabellen des aktiven Buttons weiter zu arbeiten.
Ich habe es mit

Code: Select all

SendMessage, 0x0403 , %ButtonID%, 1,, ahk_id %hToolbar% ; TB_PRESSBUTTON
probiert, da wird der Button nur markiert.
Hast du da auch noch eine Idee?

Danke


Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 12 Jan 2021, 06:36

Moin,

das Zauberwort heißt wohl tatsächlich "Klicken", ich habe jedenfalls auf die Schnelle keine Alternative gefunden.

Ich habe mal das gebastelt, das auch die Position innerhalb der Toolbar und die Größe der Buttons einliest (und es mit dem "Snipping Tool getestet):

Code: Select all

#NoEnv
Msgbox, 0, Hallo!, Bitte jetzt das beliebte Windows Snipping Tool starten!
If !(HWND := WinExist("Snipping Tool")) {
   MsgBox, 0, Hallo!, Harrh, harrh!
   ExitApp
}
WinActivate, ahk_id %HWND%
ControlGet, HTBW, Hwnd, ,ToolbarWindow321, ahk_id %HWND%
TB_Buttons := GetToolbarBtns(HTBW)
ButtonCount := TB_Buttons.Count()
For Each, Btn in TB_Buttons
   MsgBox, 0, Button %A_Index% of %ButtonCount%, % "A_Index: " A_Index "`nBtn.ID: " Btn.ID "`nBtn.TX: " Btn.TX
                                                 . "`nBtn.X: " BTN.X "`nBtn.Y: " BTN.Y
                                                 . "`nBtn.W: " BTN.W "`nBtn.H. " BTN.H
ExitApp

GetToolbarBtns(HTB) {
   Static TCL := (A_IsUnicode ? 2 : 1), TB_GETBUTTONTEXT := (A_IsUnicode ? 0x044B : 0x042D)
   Static MemSize := 4098 ; should be enough in this case
   WinGet PID, PID, ahk_id %HTB%
   If !(HPROC := DllCall("OpenProcess", "UInt", 0x0438, "Int", 0, "UInt", PID, "UPtr"))
      Return 0
   Is32bit := True
   If (A_Is64bitOS)
      Try DllCall("IsWow64Process", "Ptr", HPROC, "IntP", Is32bit)
   R_PtrSize := Is32bit ? 4 : 8
   R_PtrType := Is32bit ? "UInt" : "UPtr"
   SendMessage, 0x0418, 0, 0, , ahk_id %HTB% ; TB_BUTTONCOUNT
   If !(ButtonCount := (ErrorLevel = "FAIL" ? 0 : ErrorLevel))
      Return (DllCall("CloseHandle", "Ptr", HPROC) & 0)
   RMEM :=
   ToolbarBtns := []
   If !(RMEM := DllCall("VirtualAllocEx", "Ptr", HPROC, "Ptr", 0, "Ptr", MemSize, "UInt", 0x1000, "UInt", 4, "UPtr"))
      Return (DllCall("CloseHandle", "Ptr", HPROC) & 0)
   TBBTN_Size := 8 + (R_PtrSize * 3)
   VarSetCapacity(TBBTN, TBBTN_Size, 0) ; TBBUTTON structure
   VarSetCapacity(RECT, 16, 0)
   Loop %ButtonCount% {
      ID := 0, X := 0, Y := 0, W := 0, H := 0
      TX := ""
      SendMessage, 0x0417, A_Index - 1, RMEM, , ahk_id %HTB% ; TB_GETBUTTON  - 0-based index
      If (ErrorLevel = 1) {
         DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTN, "UPtr", TBBTN_Size, "Ptr", 0)
         ID := NumGet(TBBTN, 4, "Int")
         SendMessage, TB_GETBUTTONTEXT, ID, RMEM, , ahk_id %HTB% ; TB_GETBUTTONTEXT
         TXL := (ErrorLevel = "FAIL" ? -1 : ErrorLevel)
         If (TXL > 0) {
            TBBTX_Size := ++TXL * TCL
            VarSetCapacity(TBBTX, TBBTX_Size, 0)
            DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTX, "UPtr", TBBTX_Size, "Ptr", 0)
            TX := StrGet(&TBBTX, TXL)
         }
         SendMessage, 0x0433, ID, RMEM, , ahk_id %HTB% ; TB_GETRECT
         If (ErrorLevel) {
            DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &RECT, "UPtr", 16, "Ptr", 0)
            X := NumGet(RECT,  0, "Int")
            Y := NumGet(RECT,  4, "Int")
            W := NumGet(RECT,  8, "Int") - X
            H := NumGet(RECT, 12, "Int") - Y
         }
      }
      ToolbarBtns[A_Index] := {ID: ID, TX: TX, X: X, Y: Y, W: W, H: H} ; 1-based index
   }
   DllCall("VirtualFreeEx", "Ptr", HPROC, "Ptr", RMEM, "UPtr", 0, "UInt", 0x8000) ; MEM_RELEASE
   DllCall("CloseHandle", "Ptr", HPROC)
   Return ToolbarBtns
}

Wenn man diese Daten hat, kann man z.B. wie folgt gezielt klicken:

1. Mit Veränderung der Cursorposition:

Code: Select all

BT5 := TB_Buttons[5]
; MsgBox, 0, Button 5, % BT5.X . " - " . BT5.Y . " - " . BT5.W . " - " . BT5.H
WinGetPos, TBX, TBY, , , ahk_id %HTBW% ; HBTW -> Toolbar
CX := BT5.X + (BT5.W // 2)
CY := BT5.Y + (BT5.H // 2)
DllCall("SetCursorPos", "Int", TBX + CX, "Int", TBY + CY)
Click
MsgBox, Klick auf Button 5

2. Ohne Veränderung der Cursorposition:

Code: Select all

BT5 := TB_Buttons[5]
; MsgBox, 0, Button 5, % BT5.X . " - " . BT5.Y . " - " . BT5.W . " - " . BT5.H
BX := BT5.X + (BT5.W // 2)
BY := BT5.Y + (BT5.H // 2)
ControlClick, , ahk_id %HTBW%, , , , X%BX% Y%BY% ; HBTW -> Toolbar
MsgBox, ControlClick on Button 5
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 14 Jan 2021, 01:44

Danke dir, mit dem Snippingtool funktioniert es super.
Jetzt habe ich danke dir eine komplette Funktion zum auslesen und bearbeiten der Windowstoolbox. :bravo:

Jetzt teste ich das Java Programm.

Das funktioniert auch super , hat aber ein Problem mit

Code: Select all

VarSetCapacity(TBBTX, TBBTX_Size, 0)
dort braucht er bei jeder Abfrage ca. 10 Sekunden, siehe Log unten. Kann man das noch ändern?

Code: Select all

SendMessage,0x0417,A_Index - 1,RMEM,,ahk_id %HTB%
143: if (ErrorLevel = 1)  
144: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTN, "UPtr", TBBTN_Size, "Ptr", 0)  
145: ID := NumGet(TBBTN, 4, "Int")
146: SendMessage,TB_GETBUTTONTEXT,ID,RMEM,,ahk_id %HTB%
147: TXL := (ErrorLevel = "FAIL" ? -1 : ErrorLevel)
148: if (TXL > 0)  
149: TBBTX_Size := ++TXL * TCL
150: VarSetCapacity(TBBTX, TBBTX_Size, 0)   (10.06)
151: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTX, "UPtr", TBBTX_Size, "Ptr", 0)  
152: TX := StrGet(&TBBTX, TXL)
153: }
154: SendMessage,0x0433,ID,RMEM,,ahk_id %HTB%
155: if (ErrorLevel)  
156: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &RECT, "UPtr", 16, "Ptr", 0)  
157: X := NumGet(RECT,  0, "Int")
158: Y := NumGet(RECT,  4, "Int")
159: W := NumGet(RECT,  8, "Int") - X
160: H := NumGet(RECT, 12, "Int") - Y
161: }
162: }
164: ToolbarBtns[A_Index] := {ID: ID, TX: TX, X: X, Y: Y, W: W, H: H}  
165: }
140: ID := 0, X := 0, Y := 0, W := 0, H := 0  
141: TX := ""
142: SendMessage,0x0417,A_Index - 1,RMEM,,ahk_id %HTB%
143: if (ErrorLevel = 1)  
144: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTN, "UPtr", TBBTN_Size, "Ptr", 0)  
145: ID := NumGet(TBBTN, 4, "Int")
146: SendMessage,TB_GETBUTTONTEXT,ID,RMEM,,ahk_id %HTB%
147: TXL := (ErrorLevel = "FAIL" ? -1 : ErrorLevel)
148: if (TXL > 0)  
149: TBBTX_Size := ++TXL * TCL
150: VarSetCapacity(TBBTX, TBBTX_Size, 0)   (10.59)
151: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTX, "UPtr", TBBTX_Size, "Ptr", 0)  
152: TX := StrGet(&TBBTX, TXL)
153: }
154: SendMessage,0x0433,ID,RMEM,,ahk_id %HTB%
155: if (ErrorLevel)  
156: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &RECT, "UPtr", 16, "Ptr", 0)  
157: X := NumGet(RECT,  0, "Int")
158: Y := NumGet(RECT,  4, "Int")
159: W := NumGet(RECT,  8, "Int") - X
160: H := NumGet(RECT, 12, "Int") - Y
161: }
162: }
164: ToolbarBtns[A_Index] := {ID: ID, TX: TX, X: X, Y: Y, W: W, H: H}  
165: }
140: ID := 0, X := 0, Y := 0, W := 0, H := 0  
141: TX := ""
142: SendMessage,0x0417,A_Index - 1,RMEM,,ahk_id %HTB%
143: if (ErrorLevel = 1)  
144: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTN, "UPtr", TBBTN_Size, "Ptr", 0)  
145: ID := NumGet(TBBTN, 4, "Int")
146: SendMessage,TB_GETBUTTONTEXT,ID,RMEM,,ahk_id %HTB%
147: TXL := (ErrorLevel = "FAIL" ? -1 : ErrorLevel)
148: if (TXL > 0)  
149: TBBTX_Size := ++TXL * TCL
150: VarSetCapacity(TBBTX, TBBTX_Size, 0)   (9.61)
151: DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTX, "UPtr", TBBTX_Size, "Ptr", 0)  
152: TX := StrGet(&TBBTX, TXL)
153: }

Ich gebe dir noch eine Rückmeldung.

Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 14 Jan 2021, 05:41

Moin,

das hört sich merkwürdig an, weil die Texte ja nicht so lang sein sollten, dass VarSetCapacity Zeit braucht. Werden für die Buttons 'vernünftige' Texte eingelesen?

Hier könnte die 32-Bit Falle von SendMessage beteiligt sein. TB_GETBUTTONTEXT gibt als Indikator für einen Misserfolg -1 zurück. Daraus wird, wenn entweder AHK oder die Zielanwendung 32-bittig sind, der positive Wert 0xFFFFFFFF bzw. 4294967295. Das ist recht groß und wird zudem von der Prüfung (TXL > 0) nicht abgefangen.

Ich schlage folgende Änderung vor:

Code: Select all

         ...
         SendMessage, TB_GETBUTTONTEXT, ID, RMEM, , ahk_id %HTB% ; TB_GETBUTTONTEXT
         TXL := (ErrorLevel = "FAIL" ? -1 : (ErrorLevel << 32 >> 32)) ; <<<<<
         MsgBox, 0, TXL, %TXL% ; <<<< Nur zum Testen! Wenn es korrekt läuft, sofort wieder raus!
         ...
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 15 Jan 2021, 06:03

Das wars und jetzt läuft es.


Danke dafür.

Schönes Wochenende


Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 15 Jan 2021, 06:09

Hast Du vor der Korrektur Texte erhalten?
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 15 Jan 2021, 06:11

... oder mit der ursprünglich eingestellten Version?
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 18 Jan 2021, 08:11

Ja, habe ich, dauerte aber sehr lange. Ging auch mit deiner ersten Version schon.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 18 Jan 2021, 09:26

Moin,

das verunsichert mich etwas. Gemäß Microsoft Dokumentation gibt TB_GETBUTTONTEXT dann -1 zurück, wenn etwas nicht geklappt hat. In diesem Fall sollte auch kein plausibler Text ausgelesen werden können. Seit der letzten Änderung wird wegen If (TXL > 0) { gar nicht mehr versucht, Text auszulesen. Für die Buttons, die vorher Probleme gemacht haben, sollte deshalb im Array im Schlüssel TX kein Text zu finden sein.

Ich habe hier keine für einen Test geeignetenToolbars. Kannst Du das mal prüfen und feststellen, ob es eine 'Systematik' gibt?
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 19 Jan 2021, 02:29

Hallo Just me,

ist so wie du es geschrieben hast. Wird -1 ausgegeben , ist kein Text vorhanden.
Ist im übrigen eine tolle Funktion. Die muss ich mir mal näher ansehen.

Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 19 Jan 2021, 04:54

Moin Bert, danke!
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 15 Feb 2021, 13:08

Hallo @Just me,

kann ich dich noch mal um Hilfe bitten.
Ich brauche noch für die oben von dir erstellte Funktion den Punkt, dass ich erkenne, welcher der Buttons aktuell aktiv ist. Also im Vordergrund ist.
Ich komme mit den normalen Befehlen von Ahk hier nicht weiter. Es scheint auch so, das über java gestartet Programme deutlich schwerer auszulesen sind.

Gibt es dazu irgendwelche Turorials, die ich mir mal reinziehen kann?

Danke
Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 16 Feb 2021, 05:26

Moin,

das Ganze ist ziemlich widerspentig. Ich habe noch nicht viel mit Toolbars gemacht. Sie verhindert jedenfalls schon mal, dass man sich direkt mit den enthaltenen "Buttons" verständigen kann. Wenn sie sich dann noch in einer fremden Anwendung befindet, ist man vom normalen Benachrichtigungsverfahren, das das Eltenfenster über Aktionen innerhalb der Toolbar informiert, ausgesperrt. Und wenn die Anwendung in Java geschrieben ist, kann es noch mehr Probleme geben (muss es aber nicht).

Ich habe hier schon mit dem Snipping-Tool ein paar Sachen ausprobiert, bislang aber ohne überzeugenden Erfolg. Ich bin mir aber auch nicht 100-%-tig sicher, was genau Du mit "... aktuell aktiv ist. Also im Vordergrund ist." meinst. Kannst Du mir das noch etwas genauer erklären?
Milchmann
Posts: 112
Joined: 05 Nov 2016, 08:50

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by Milchmann » 16 Feb 2021, 07:42

Hallo,

danke fürs Antworten.

Bei dem Bild im ersten Beispiel ist der hellblaue Button farblich unterlegt und ich sehe die Daten des hellblauen Buttons. Klicke ich den anderen Button an, ist der farblich unterlegt und ich sehe die Daten dieses Buttons dann auf dem Bildschirm. Ich habe es schon mit "TB_ISBUTTONCHECKED " probiert, funktioniert aber nicht.


Danke Bert
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: ToolbarWindow32 Namen des TAB/Button auslesen und dann schliessen/ verstecken

Post by just me » 16 Feb 2021, 09:15

Es gibt eine TB_GETHOTITEM Nachricht, die vielleicht den korrekten Index liefert. Wenn sie nichts findet, liefert sie -1.

Code: Select all

TB_GetHotItem(HTB) ; HTB : HWND (handle) of the toolbar control
   ; TB_GETHOTITEM = 0x0447
   Return DllCall("SendMessage", "Ptr", HTB, "UInt", 0x0447, "Ptr", 0, "Ptr", 0, "Int")
}
Ansonsten kannst Du die folgende Version von GetToolbarBtns(HTB) ausprobieren. Sie liefert zusätzlich Status (state) und Stil (style) der Buttons. Vielleicht ändert sich da nach dem Klicken etwas:

Code: Select all

; ======================================================================================================================
GetToolbarBtns(HTB) {
   Static TCL := (A_IsUnicode ? 2 : 1), TB_GETBUTTONTEXT := (A_IsUnicode ? 0x044B : 0x042D)
   Static MemSize := 4098 ; should be enough in this case
   If !(RMEM := RMO_Create(HTB, 4096))
      Return !(Erroreve := 1) ; False
   WinGet PID, PID, ahk_id %HTB%
   If !(HPROC := DllCall("OpenProcess", "UInt", 0x0438, "Int", 0, "UInt", PID, "UPtr"))
      Return 0
   Is32bit := True
   If (A_Is64bitOS)
      Try DllCall("IsWow64Process", "Ptr", HPROC, "IntP", Is32bit)
   R_PtrSize := Is32bit ? 4 : 8
   R_PtrType := Is32bit ? "UInt" : "UPtr"
   SendMessage, 0x0418, 0, 0, , ahk_id %HTB% ; TB_BUTTONCOUNT
   If !(ButtonCount := (ErrorLevel = "FAIL" ? 0 : ErrorLevel))
      Return (DllCall("CloseHandle", "Ptr", HPROC) & 0)
   RMEM :=
   ToolbarBtns := []
   If !(RMEM := DllCall("VirtualAllocEx", "Ptr", HPROC, "Ptr", 0, "Ptr", MemSize, "UInt", 0x1000, "UInt", 4, "UPtr"))
      Return (DllCall("CloseHandle", "Ptr", HPROC) & 0)
   TBBTN_Size := 8 + (R_PtrSize * 3)
   VarSetCapacity(TBBTN, TBBTN_Size, 0) ; TBBUTTON structure
   VarSetCapacity(RECT, 16, 0)
   Loop %ButtonCount% {
      IBM := -2, ID := 0, State := 0x00, Style := 0x00, X := 0, Y := 0, W := 0, H := 0
      Text := ""
      SendMessage, 0x0417, A_Index - 1, RMEM, , ahk_id %HTB% ; TB_GETBUTTON  - 0-based index
      If (ErrorLevel = 1) {
         DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTN, "UPtr", TBBTN_Size, "Ptr", 0)
         IBM := NumGet(TBBTN, 0, "Int")
         ID := NumGet(TBBTN, 4, "Int")
         State := Format("0x{:02X}", NumGet(TBBTN, 8, "UChar"))
         Style := Format("0x{:02X}", NumGet(TBBTN, 9, "UChar"))
         SendMessage, TB_GETBUTTONTEXT, ID, RMEM, , ahk_id %HTB% ; TB_GETBUTTONTEXT
         ; TXL := (ErrorLevel = "FAIL" ? -1 : ErrorLevel)
         TXL := (ErrorLevel = "FAIL" ? -1 : (ErrorLevel << 32 >> 32))
         If (TXL > 0) {
            TBBTX_Size := ++TXL * TCL
            VarSetCapacity(TBBTX, TBBTX_Size, 0)
            DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &TBBTX, "UPtr", TBBTX_Size, "Ptr", 0)
            Text := StrGet(&TBBTX, TXL)
         }
         SendMessage, 0x0433, ID, RMEM, , ahk_id %HTB% ; TB_GETRECT
         If (ErrorLevel) {
            DllCall("ReadProcessMemory", "Ptr", HPROC, "Ptr", RMEM, "Ptr", &RECT, "UPtr", 16, "Ptr", 0)
            X := NumGet(RECT,  0, "Int")
            Y := NumGet(RECT,  4, "Int")
            W := NumGet(RECT,  8, "Int") - X
            H := NumGet(RECT, 12, "Int") - Y
         }
      }
      ; 1-based index
      ToolbarBtns[A_Index] := {IBM: IBM, ID: ID, State: State, Style: Style, Text: Text, X: X, Y: Y, W: W, H: H}
   }
   DllCall("VirtualFreeEx", "Ptr", HPROC, "Ptr", RMEM, "UPtr", 0, "UInt", 0x8000) ; MEM_RELEASE
   DllCall("CloseHandle", "Ptr", HPROC)
   Return ToolbarBtns
}

Code: Select all

...
   MsgBox, 0, Button %A_Index% of %ButtonCount%, % "A_Index: " A_Index
                                                 . "`nBtn.IBM: " Btn.IBM "`nBtn.ID: " Btn.ID
                                                 . "`nBtn.State: " Btn.State "`nBtn.Style: " Btn.Style
                                                 . "`nBtn.Text: " Btn.Text
                                                 . "`nBtn.X: " BTN.X "`nBtn.Y: " BTN.Y
                                                 . "`nBtn.W: " BTN.W "`nBtn.H. " BTN.H
...
Post Reply

Return to “Ich brauche Hilfe”