Auf fremdes Fenster klicken

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Delle
Beiträge: 1118
Registriert: 10.05.2005 22:48

Auf fremdes Fenster klicken

Beitrag von Delle »

Hallo,

ich will in einem "fremden" Programm auf eine gewisse Schaltfläche klicken lassen.

Das Handle vom jeweiligen Fenster habe ich mir hiermit besorgt:

Code: Alles auswählen

  Structure Point64
    StructureUnion
    p.point
    q.q
    EndStructureUnion
  EndStructure
 
  Procedure Thread(z)
    hndl = 0
    cursor.Point64
    Repeat
      GetCursorPos_(cursor.Point64)
      hndl = WindowFromPoint_( cursor\q )
      SetGadgetText(1,"Handle-Nummer unter Maus: "+Str(hndl))
      Delay(100)
    ForEver
   
  EndProcedure
 
  If OpenWindow(0,0,0,250,50,"Window",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
    StickyWindow(0,1)
    TextGadget(1,10,10,220,20,"",0)
    CreateThread(@Thread(),0)
   
    Repeat
      EventID=WaitWindowEvent()
      If EventID = #PB_Event_CloseWindow
        End
      EndIf
    ForEver
  EndIf
Geklickt werden soll hiermit:

Code: Alles auswählen

Enumeration
  
  #Start
  
EndEnumeration

OpenWindow(0,0,0,175,155,"Klicker",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)

StickyWindow(0,1)

ButtonGadget(#Start,10,10,155,30,"Start")

Repeat
      
      EventID=WaitWindowEvent(50)
      
      If EventID=#PB_Event_Gadget And EventGadget()=#Start
        
          x=570
          y=200
          SetCursorPos_(x,y)
          Delay(250)
          SetForegroundWindow_(786536)
          Delay(250)
          mouse_event_(#MOUSEEVENTF_LEFTDOWN,x,y,0,0)
          mouse_event_(#MOUSEEVENTF_LEFTUP,x,y,0,0)
                 
      EndIf
      
    Until EventID=#PB_Event_CloseWindow
    
End
Der Mauscursor wird zwar auf die Position gesetzt, geklickt wird aber nicht.

Eigentlich müsste doch SetForegroundWindow_() VOR dem Klick gesetzt werden oder? Hat aber dann gar keinen Effekt.

Das Zielprogramm hat übrigens nicht wie das Browserfenster nur ein Handle, sondern mehrere für Titel, Statusleiste usw. Einfach mal mit dem Handlefinder oben in der PB-IDE rumfahren...

Hat jemand eine Idee woran das liegen könnte?

Dankeschöööö! :-)
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Auf fremdes Fenster klicken

Beitrag von RSBasic »

Du musst kein eigenes Programm entwickeln, um die Handle-Nummer unter der Maus zu ermitteln.
Dafür gibt es bereits fertige Programme, die noch mehr zeigen, z.B. alle Controls eines Fensters und der GUI-Aufbau.
https://www.rsbasic.de/temp/WinSpy.exe
https://www.rsbasic.de/temp/ShoWin.exe

Ist es immer ein Button, auf den du klicken möchtest? Warum mit mouse_event_()?
mouse_event_() würde ich niemals benutzen. Viel zu unsicher und der Mauscursor des Benutzers (genauso wie die Zwischenablage) sollte nicht verändert werden.
Außerdem muss immer sichergestellt werden, dass das Zielfenster immer gerade im Vordergrund ist. Selbst wenn du SetForegroundWindow_() benutzt, kann es aus irgendeinem Grund doch mal passieren, dass vielleicht ein anderes Sticky-Fenster darüber liegt oder genau in dem Moment ein anderes Fenster geöffnet wird und schon klickst du auf etwas falsches.

Um einen Button-Klick zu simulieren, gibt es eine viel einfache und direkte Lösung: #BM_CLICK
Da muss dein Zielfenster nicht mal im Vordergrund sein.

Code: Alles auswählen

EnableExplicit

Define Handle

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(1, 10, 10, 200, 30, "Button-Klick simulieren", 0)
  ButtonGadget(2, 10, 50, 200, 30, "Button", 0)
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            Handle = GadgetID(2)
            ;Handle = ...
            SendMessage_(GadgetID(2), #BM_CLICK, 0, 0)
          Case 2
            Debug "Auf den Button wurde geklickt"
        EndSelect
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Wenn du die Handle-Nummer eines Buttons eines Fensters ermitteln möchtest, kannst du folgende Funktionen benutzen:
  • EnumWindows_()
  • EnumChildWindows_()
  • FindWindow_()
  • FindWindowEx_()
  • GetWindow_() (z.B. mit #GW_CHILD)
Weitere Funktionen, die auch nützlich sein können, um mehr zu erfahren, was das für ein Control ist:
  • GetClassName_()
  • GetWindowText_()
  • GetWindowLongPtr_()
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Delle
Beiträge: 1118
Registriert: 10.05.2005 22:48

Re: Auf fremdes Fenster klicken

Beitrag von Delle »

Hallo Ray! :D
RSBasic hat geschrieben:Du musst kein eigenes Programm entwickeln, um die Handle-Nummer unter der Maus zu ermitteln.
Dafür gibt es bereits fertige Programme, die noch mehr zeigen, z.B. alle Controls eines Fensters und der GUI-Aufbau.
https://www.rsbasic.de/temp/WinSpy.exe
https://www.rsbasic.de/temp/ShoWin.exe
Das Snippet ist glaub sogar von Dir aus dem Forum. Reicht mir persönlich aus, um schnell das Handle zu finden.
RSBasic hat geschrieben:Ist es immer ein Button, auf den du klicken möchtest? Warum mit mouse_event_()?
mouse_event_() würde ich niemals benutzen. Viel zu unsicher und der Mauscursor des Benutzers (genauso wie die Zwischenablage) sollte nicht verändert werden.
Außerdem muss immer sichergestellt werden, dass das Zielfenster immer gerade im Vordergrund ist. Selbst wenn du SetForegroundWindow_() benutzt, kann es aus irgendeinem Grund doch mal passieren, dass vielleicht ein anderes Sticky-Fenster darüber liegt oder genau in dem Moment ein anderes Fenster geöffnet wird und schon klickst du auf etwas falsches.
Also eigentlich soll es so ablaufen:

1) Das Tool startet und ist unsichtbar/minimiert.
2) Das Zielprogramm ist geöffnet/Focus.
3) Sobald ein Hotkey gedrückt wird, fängt das Tool an zu "arbeiten".
4) Im Zielfenster/Control wird ein Rechtsklick ausgeführt, anschließend ein Linksklick ca. 50 Pixel weiter unten.

Bild

5) Das Tool springt wieder in Wartemodus...

Das hat ähnlich bei Browsersachen funktioniert, nur diesmal mit einem "richtigen" Programm nicht :(
RSBasic hat geschrieben:Um einen Button-Klick zu simulieren, gibt es eine viel einfache und direkte Lösung: #BM_CLICK
Da muss dein Zielfenster nicht mal im Vordergrund sein.
Direkt ist das schon, aber nicht "einfach" ;)

Dazu müsste ich aber die Handles der Buttons im Zielprogramm wissen und die geben mir auch Deine 2 genannten Tools nicht her.

Also mir wäre ein einfaches "fester" Klick an einer bestimmten Position lieber.
PB 6.02 LTS + Win 11
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Auf fremdes Fenster klicken

Beitrag von RSBasic »

Hi Delle,

wenn ich deinen Screenshot anschaue, dann ist es keine typische Win32-Anwendung, sondern eine Anwendung mit selbstgemachter Benutzeroberfläche.
Das ist in der Tat nicht so einfach möglich.
Dann nehme ich meine Aussage wieder zurück. :D
Dann musst du wohl doch mit mouse_event_() arbeiten. :|

Da ich das Programm nicht habe, kann ich dir leider nicht helfen.
Wenn du mit WinSpy oder mit dem "Handle unter Maus"-Code auf das Fenster und auf die Controls zeigst, was kann ermittelt werden?
Wahrscheinlich nur ein einziger Bereich mit einer Handle-Nummer oder? Wenn ja, dann musst du mouse_event_() benutzen.

#BM_CLICK ist nur auf WinAPI-Button (ButtonGadget oder CreateWindowEx_(..., "Button", ...)) einsetzbar.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Delle
Beiträge: 1118
Registriert: 10.05.2005 22:48

Re: Auf fremdes Fenster klicken

Beitrag von Delle »

RSBasic hat geschrieben:wenn ich deinen Screenshot anschaue, dann ist es keine typische Win32-Anwendung, sondern eine Anwendung mit selbstgemachter Benutzeroberfläche.
Ja ist alles vektorbasiert...
RSBasic hat geschrieben:Dann musst du wohl doch mit mouse_event_() arbeiten. :|
Find ich nicht sooo schlimm, aber irgendwie "konfliktiert" das zwischen meinem Stickyfenster und dem Zielprogramm.
RSBasic hat geschrieben:Da ich das Programm nicht habe, kann ich dir leider nicht helfen.
Ist FL Studio, ehemals Fruity Loops ;)
RSBasic hat geschrieben:Wenn du mit WinSpy oder mit dem "Handle unter Maus"-Code auf das Fenster und auf die Controls zeigst, was kann ermittelt werden?
Wahrscheinlich nur ein einziger Bereich mit einer Handle-Nummer oder? Wenn ja, dann musst du mouse_event_() benutzen.
Schön wäre es, es sind leider verschiedene Controls/Panels:

Bild

Hab es jetzt mal so nacheinander probiert - kein Erfolg:

SetForegroundWindow_(5441062) ; Main Form
SetForegroundWindow_(2099040) ; Panel wo geklickt werden soll

Ich glaub eher das Sticky muss weg sein und das "richtige" Fenster von der Anwendung den "echten" Focus haben.

Aktuell versuch ich ja nur Panels in diesem Fenster irgendwie in den Vordergrund zu holen...
PB 6.02 LTS + Win 11
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Auf fremdes Fenster klicken

Beitrag von RSBasic »

Delle hat geschrieben:Schön wäre es, es sind leider verschiedene Controls/Panels:
Je mehr auffindbare Controls desto besser eigentlich, damit man per WinAPI gezielter darauf zugreifen kann.

Wenn du mit dem Window Picker auf das Element zeigst, ist es einzelnes Element oder ein ganzer Bereich, in dem sich mehrere Elemente befinden?

Nachdem du das gewünschte Element gepickt hast, kannst du anschließend auf den ToolBar-Button "Generate FindWindow Code..." klicken (das letzte ToolBar-Icon).
Damit hast du eine Vorlage, wie du beispielhaft mit FindWindow_() und FindWindowEx_() zugreifen kannst, um das Zielelement als Handle zu bekommen.

Ich kann ja mal am Wochenende, falls du bis dahin noch keine Lösung gefunden hast, FL Studio installieren.
Auf welches Element möchtest du gerne klicken? Auf "Randomize"?
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Delle
Beiträge: 1118
Registriert: 10.05.2005 22:48

Re: Auf fremdes Fenster klicken

Beitrag von Delle »

RSBasic hat geschrieben:Je mehr auffindbare Controls desto besser eigentlich, damit man per WinAPI gezielter darauf zugreifen kann.

Wenn du mit dem Window Picker auf das Element zeigst, ist es einzelnes Element oder ein ganzer Bereich, in dem sich mehrere Elemente befinden?
Sind immer nur Bereiche, keine einzelnen Buttons oder so :(

Das wäre mal eine Quick&Dirty-Variante um überhaupt mal das Klicken zu testen:

Code: Alles auswählen

Delay(3000)

handle=FindWindow_(0,"FL Studio 20")
SetForegroundWindow_(handle)
        
x=570
y=200
SetCursorPos_(x,y)

mouse_event_(#MOUSEEVENTF_LEFTDOWN,x,y,0,0)
mouse_event_(#MOUSEEVENTF_LEFTUP,x,y,0,0)
    
End

Da passiert aber wiederum gar nix!

1) Die Mausposition wird nicht verändert. Kann es sein, dass dies nur geht, wenn ein PB-Fenster offen ist und den Focus hat? Die Maus wird also dann nur auf der "PB-Ebene" bewegt?

2) Angeklickt wird nichts, Fensterhandle stimmt aber - Fenster wird aber auch nicht automatisch in den Vordergrund gezogen - muss ich manuell machen.
RSBasic hat geschrieben:Ich kann ja mal am Wochenende, falls du bis dahin noch keine Lösung gefunden hast, FL Studio installieren.
Auf welches Element möchtest du gerne klicken? Auf "Randomize"?
Ich wette Du machst dann erstmal wochenlang Musik und meldest Dich nicht mehr :-D Kennst Du die Software? War halt damals irgendwie die logische Konsequenz wenn man mit Trackern Musik gemacht hat...
PB 6.02 LTS + Win 11
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Auf fremdes Fenster klicken

Beitrag von RSBasic »

Delle hat geschrieben:Da passiert aber wiederum gar nix!
Vielleicht musst du nach dem Setzen des Fokus auf das Zielfensters ein Delay() einfügen? Vielleicht ist dein Code zu schnell und klickt noch auf etwas, bevor das Fenster erscheint.

Ich habe hier einen kleinen Beispielcode geschrieben:

Code: Alles auswählen

EnableExplicit

Define RECT.RECT

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(1, 10, 10, 200, 30, "Button-Klick simulieren", 0)
  ButtonGadget(2, 10, 50, 200, 30, "Button", 0)
 
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            GetWindowRect_(GadgetID(2), RECT)
            
            SetCursorPos_(RECT\left+1, RECT\top+1)
            
            mouse_event_(#MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
            mouse_event_(#MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
            
          Case 2
            Debug "Auf den Button wurde geklickt"
        EndSelect
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
Ich schau mir am Wochenende mal an.
Delle hat geschrieben:Ich wette Du machst dann erstmal wochenlang Musik und meldest Dich nicht mehr :-D Kennst Du die Software? War halt damals irgendwie die logische Konsequenz wenn man mit Trackern Musik gemacht hat...
Die Software kenne ich, ja. Damit (davor mit Ejay-Software) habe ich damals gerne Musik gemacht, ist aber sehr lange her. :D
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Delle
Beiträge: 1118
Registriert: 10.05.2005 22:48

Re: Auf fremdes Fenster klicken

Beitrag von Delle »

RSBasic hat geschrieben:Vielleicht musst du nach dem Setzen des Fokus auf das Zielfensters ein Delay() einfügen? Vielleicht ist dein Code zu schnell und klickt noch auf etwas, bevor das Fenster erscheint.
Hab ich auch schon probiert :(

Letzter Stand für heute:

Code: Alles auswählen

x=570
y=200

handle=FindWindow_(0,"FL Studio 20")

SetCursorPos_(x,y)

Delay(1000)

SetForegroundWindow_(handle)
ShowWindow_(handle, #SW_MAXIMIZE)
UpdateWindow_(handle)

Delay(1000)

mouse_event_(#MOUSEEVENTF_LEFTDOWN,x,y,0,0)
mouse_event_(#MOUSEEVENTF_LEFTUP,x,y,0,0)

End
Das holt immerhin das Programm in den Fokus und plaziert auch die Maus da wo ich sie haben will, klickt aber nicht.

Witzigerweise muss man die Maus VOR der Fensteraktivierung plazieren, danach funzt es nicht mehr (und deswegen wohl die Klicks auch nicht).
PB 6.02 LTS + Win 11
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Auf fremdes Fenster klicken

Beitrag von RSBasic »

Es ist zwar noch nicht Wochenende, aber ich habe jetzt trotzdem FL Studio (Version 20) installiert.
Bei mir sieht es leicht anders aus. Ich habe den Text "Presets < >" nicht wie in deinem Screenshot.
Ich habe versucht, mit meinem Code irgendwo einen Rechtsklick und einen Linksklick zu simulieren und es funktioniert.
Code:

Code: Alles auswählen

EnableExplicit

Define Handle

Handle = FindWindow_("TFruityLoopsMainForm", 0)
If Handle = 0
  MessageRequester("", "Programm nicht gefunden")
  End
EndIf

If OpenWindow(0, 0, 0, 500, 400, "Window", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  ButtonGadget(1, 10, 10, 100, 20, "Start", 0)
  
  StickyWindow(0, 1)
  
  Repeat
    Select WaitWindowEvent()
      Case #PB_Event_Gadget
        Select EventGadget()
          Case 1
            SetForegroundWindow_(Handle)
            Delay(250)
            SetCursorPos_(1500, 20)
            mouse_event_(#MOUSEEVENTF_RIGHTDOWN, 0, 0, 0, 0)
            mouse_event_(#MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0)
            SetCursorPos_(1500, 40)
            mouse_event_(#MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
            mouse_event_(#MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)
            
        EndSelect
      Case #PB_Event_CloseWindow
        End
    EndSelect
  ForEver
EndIf
So sieht es aus: https://www.rsbasic.de/temp/2019-07-04%2014-52-17.mp4
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Antworten