Fensterinformationen via Linksklick entziehen

  • Hallo Leute,

    ich arbeite zur Zeit nebenbei an einem kleinen Tool, welches uns die Dokumentation von Installationen erleichern soll.

    Das Tool soll, im wesentlichen, Screenshots generieren, wenn man einen Linksklick ausführt.

    Hinzu kommen noch eine Pausenfunktion und ein paar weitere Hotkeys mit anderen Funktionen.

    Das ganze Script funktioniert soweit einwandfrei. Nun kommt allerdings ein Punkt, an dem ich nicht weiterkomme:

    Ich möchte nämlich keinen Full Screen Screenshot Machen sondern ein Screenshot des Fensters, auf das ich Klicke.

    (bzw. auf dessen Button ich gerade Klicke. Wenn kein Fenster gedrück wurde gibt es einfach wieder einen Full Screen Screenshot.)

    Am Ende findet Ihr den Quellcode des Scriptkerns.

    Wie ihr dort sehen könne "scanne" ich in einer Schleife mittels "_IsPressed()" nach bestimmten Tasten.

    Wird eine dieser Tasten gedrückt wird ein Screenshot ausgeführt, die Pause gestartet oder die Funktion beendet.

    Ich habe sowohl die Funktionen "TakeScreenshot()" als auch "TakeFullScreenScreenshot()". Aktuell enthalten beide den Code des Full Screen.

    Einen Code für den "normalen" Screenshot suche ich noch.

    Dabei dachte ich an https://www.autoitscript.com/autoit3/docs/l…_CaptureWnd.htm

    Hier kann ich ein Screenshot eines Fensters Machen. Allerdings benötige ich dazu die Informationen des Fensters.

    Meine Frage ist an euch wie ich innerhalb dieser Funktionsstruktur (vermutlich innerhalb der jeweilen If-Abfrage) an die Fensterinformationen komme.

    Gibt es eine Möglichkeit an diese mittels _isPressed zu kommen?

    Vielen Dank für jede Hilfe!

    LG

    Einmal editiert, zuletzt von Reiterfuchs (21. Dezember 2017 um 10:08)

    • Offizieller Beitrag

    Meine Frage ist an euch wie ich innerhalb dieser Funktionsstruktur (vermutlich innerhalb der jeweilen If-Abfrage) an die Fensterinformationen komme.


    Gibt es eine Möglichkeit an diese mittels _isPressed zu kommen?

    Schau Dir mal in der Hilfe das Beispiel zu "_WinAPI_WindowFromPoint" an. So bekommst Du das Window-Handle unter der Mausposition.

  • Läuft!

    Vielen Dank nochmal.

  • Okay, ich muss mich korregieren: Es läuft leider nicht.

    Wie zu Beginn erwähnt soll das Script zur Dokumentation von Installationen dienen. Leider erziehle ich nicht das gewünschte Ergebnis.

    Das Problem ist, was als Fenster erkannt wird: Nehmen wir ein typisches Installationsfenster mit den Buttons "Next" und "Cancel".

    Anstatt das Fenster des Setups festzuhalten wird bei einem Druck auf den "Next"-Button ausschließlich dieser Button fotografiert und nicht das Fenster.

    Ich habe keine Ahnung, was man hier machen könnte.

    Ich zeige euch hier noch die Funktionen, die die Aufnahme managen, Screenshots Machen und die Cursorposition ermitteln:

    Vielen Dank für eure Hilfe!

    AutoIt: TakeFullScreenSnapshot
    Func TakeFullScreenSnapshot($bCursor) ;Take Snapshot of the current window (Full Screen Modus)
    
       _ScreenCapture_Capture($sPath & GetFullPicName(), 0, 0, -1, -1, $bCursor)
    
    EndFunc   ;==>TakeSnapshot
    AutoIt: GetMousePosition
    Func GetMousePosition() ;Update the position value
    
       DllStructSetData($g_tStruct, "x", MouseGetPos(0))
       DllStructSetData($g_tStruct, "y", MouseGetPos(1))
    
    EndFunc   ;==>Position
  • Manchmal ist die Welt so einfach... oder auch nicht.

    Diese Idee war wirklich super. So kann ich ohne Probleme nach oben populieren und einen Screenshot des Fensters Machen.

    Denn mit dieser Methode populiere ich immer nach ganz oben. Das möchte ich aber unter Umständen nicht. Dieser Umstand ist, wenn ich ein modales Fenster habe. Denn er populier bis zum "Main" Fenster. Wenn ich also beispielsweise das "Find" Fenster I'm Notepad haben möchte populiert er bis zum Notepad Main Fenster.

    Ich habe schon einiges probiert und z.B. für die WPF, also .NET Lösungen gefunden aber keine konnte ich auf AutoIt übertragen.

    z.B. habe ich versucht die Schleife wie folgt zu erweitern:

    AutoIt
    While _WinAPI_GetParent($hWnd) <> 0 And _WinAPI_GetWindow($hWnd, $GW_OWNER) == 0

    Problem: Damit mache ich nun wieder Screenshot von den Buttons, da diese ja auch Childelemente sind.

    Außerdem habe ich folgende Ansätze gefunden:

    https://blogs.msdn.microsoft.com/oldnewthing/20111212-00/?p=8923

    https://stackoverflow.com/questions/3689…window-is-modal

    Es wäre super, wenn du/ihr mir helfen könntet das Erkennen eines modalen Fensters in die Methode einzubausen.

    Vielen lieben Dank!

  • Hier noch ein paar Funktionen, die hilfreich sein könnten, die gewünschten Fenster zu finden...

    _WinAPI_GetAncestor()

    _WinAPI_GetClassName() ; ein Button ist z. B. "Static"

    _WinAPI_GetWindowLong() ; $GWL_STYLE, $GWL_EXSTYLE

    _WinAPI_IsChild()

    _WinAPI_GetTopWindow()

    _WinAPI_EnumWindowsTop()

    _WinAPI_EnumWindows()_WinAPI_EnumChildWindows()

    _WinAPI_EnumProcessWindows()

    und noch viele mehr... im Anhang noch ein Script mit Demo, dass dir sicher auch nützliche Infos liefert...

  • Erstmal Danke für die Antwort.

    Diese ganzen Funktionen bin ich bereits durchgegangen.

    Wie oben beschrieben ist allerdings auch z.B. ein Button ein Childelement, somit fällt "IsChild" leider heraus.

    Ich möchte explizit prüfen, ob es sich bei meinen herausgezogenen Windowelement um ein modales Fenster handelt.

    Man muss das doch irgendwie überprüfen können.

    Nur ein Beispiel um mein Problem zu veranschaulichen:

    Folgende Elemente sind vorhanden und bauen jeweils aufeinander auf:

    "Main Window" -> "Modal Window 1" -> "Modal Window 2" -> "Button"

    Lösungsansatz "Aktuelles Element auf Child prüfen":

    Nutze ich dies werde ich immer das angeklickte Element bekommen, da auch "Button" ein Childelement ist. Allerding soll ja auf "Modal Window 2" populiert warden. Wenn ich auf eines der Fenster drücke stimmt die Information natürlich.

    Lösungsansatz "Übergeordnetes Element auf Main prüfen":

    Da ich bisher nicht weis ob/wie man ein Element auf Modal überprüft bleibt mir noch die Möglichkeit die Parentkomponente zu überprüfen.

    Ich könnte z.B. überprüfen, ob mein Parentelement das "Main Window" ist und dann aufhören nach oben zu populieren.

    Dabei gibt es ein Problem:

    Drücke ich nicht auf das Main Window bleibe ich immer auf der direct untergeordneten Ebene stecken.

    Drücke ich im oben gezeigten Beispiel auf Button nimmt er "Modal Window 1", es soll aber logischerweise "Modal Window 2" sein.

    Selbiges Problem, wenn ich auf einen Button des "Main Window" drücke werde ich nur die Informationen dieses Buttons bekommen, da, wie gesagt, der Button genau wie ein modales Fenster als Child erkannt wird.

    4 Mal editiert, zuletzt von Reiterfuchs (9. Januar 2018 um 10:16)

  • Ein weiterer Lösungsansatz wäre herauszufinden ob es sich bei dem herausgezogenen hWnd-Element um ein "richtiges" Fenster handelt oder nur um ein Label, Button oder irgendetwas anderes. Gibt es da eine Möglichkeit dies eindeutig zu indentifizieren?

    Also, ich hole mir zunächst das Objekt via.

    $hWnd = _WinAPI_WindowFromPoint($g_tStruct)

    und möchte nun überprüfen, ob es sich hierbei um ein "richtiges" Fenster oder ein anderes Element wie z.B. einen Button handelt.

  • Kannst du nicht mit _WinAPI_GetClassName das ganze prüfen?

    Hier ein kleiner Test:

    AutoIt
    #include <WinAPI.au3>
    
    $hForm = GUICreate("Form1",200,200)
    $hButton = GUICtrlCreateButton("Button", 5, 5, 190, 190)
    GUISetState()
    
    MsgBox(0,0,_WinAPI_GetClassName(WinGetHandle($hForm)))
    MsgBox(0,0,_WinAPI_GetClassName(ControlGetHandle($hForm, "", $hButton)))

    Sollte das nicht reichen kannst du ja mit WinList nach dem Titel suchen und schauen ob es dort existiert, sollte es dort vorhanden sein, dann ist es ein richtiges Fenster.

  • Ich bin zwar noch am probieren, aber ich antworte trotzdem jetzt schon einmal. Weil ich vermute, dass dies nicht so einfach ist.

    Mit dem ClassName alleine kann ich hier nicht arbeiten. Das könnte ich nur, wenn jeder seine GUI-Element auch ordentlich benennen würde. Das ist leider Gottes nicht der Fall. Ich lese hier ja Fenster aus, die von Dritten stamen.

    Das mit der WinList werde ich jetzt mal ausprobieren. Allerdings vermute ich, dass das nicht klappen wird.

    Denn zumindest Buttons führt Windows intern als Fenster... Ist also gut möglich, dass er bei einem Vergleich die Buttons durchlässt.

    Jetzt aber erstmal ausprobieren!

  • Ich habe schon in diese Richtung gedacht. Damit meine ich mir irgendwie eine Liste mit allen Fenstern zu holen und diese dann mit meinem selektierten Objekt abzugleichen. Mit welchen Value würdest du eigentlich die Elemente vergleichen?

    In WinList tauchen nur Fenster auf und keine Buttons auch wenn intern diese mit einem Window-Handle identifiziert werden.

    Wenn ich folgendes nutze:

    AutoIt
    Local $aList = WinList()
    _ArrayDisplay($aList)

    Bekomme ich eine Liste mit gut 321 Elementen angezeigt bei ... 7 offenen Fenstern.

    Bist du dir da also sicher?

    Mich interessiert hierbei natürlich was die anderen 314 Objekte sind. Vielleicht kannst du mich da aufklären.

    2 Mal editiert, zuletzt von Reiterfuchs (10. Januar 2018 um 13:03)

  • So, ich habe es durchprobiert und mich schlau gemacht.

    In der Liste sind u.a. auch Icons von der Taskbar und einige andere Dinge drin. Aber keine Buttons - Yay!

    Ich stele hier noch den Code rein, wie ich mein Objekt auf ein "richtiges" Fenster überprüfe.

    (Wer weis, ob das einmal jemand benötigt)

  • Ich stele hier noch den Code rein, wie ich mein Objekt auf ein "richtiges" Fenster überprüfe.

    (Wer weis, ob das einmal jemand benötigt)

    In deinem Code ist die Variable $g_tStruct nicht deklariert., weshalb das Script mit einer Fehlermeldung abbricht. Damit dein Code funktioniert, muss die DllStruct aber auch die aktuellen Maus-Koordinaten enthalten, die du auch an keiner Stelle setzt. Zudem liefert dein Code nicht immer nur ein Window-Handle... welches davon ist das richtige, wenn es mehrere sind?

    Beispiel: SciTE

    $hWnd = 0x00AE0D8C    $sWinTitle = Source

    $hWnd = 0x00611584    $sWinTitle = M:\GetWindowInformation.au3 - SciTE [2 von 2]

    Das geht aber auch kürzer...

    5 Mal editiert, zuletzt von Bitnugger (10. Januar 2018 um 16:44)