Kleines AutoIt-Capture Programm

  • Um mal zu zeigen, wie man mit der _ScreenCapture-UDF ein kleines Capture-Programm in AutoIt schreiben kann, habe ich hier mal die wichtigsten Funktionen in einem Programm zusammengefasst:

    Edit 11.09.2021:

    - Die "Ganzer Bildschirm"-Funktion funktioniert jetzt auch mit mehreren Monitoren korrekt.

    - Außerdem kann man jetzt auswählen, ob der Mauszeiger mit aufgenommen werden soll oder nicht.

    Edit 13.09.2021:

    - Die Capture-Funktion umgeschrieben, weil die Funktionen "_ScreenCapture_Capture" und "_ScreenCapture_CaptureWnd" nicht korrekt mit negativen Screenkoordinaten umgehen ("-1" als Defaultwert).

    Edit 14.09.2021:

    - Der Anwender kann jetzt den Hotkey selbst im Programm registrieren (Tasten begrenzt). Die Tastenkombination wird in der Registry gespeichert.

    - Die Capture-Funktion noch etwas umgeschrieben.

    - Statuszeile hinzugefügt.

    - Icon für das Fenster hinzugefügt.

    Edit 15.09.2021:

    - Hotkey-Funktion nochmal überarbeitet, damit bereits registrierte Hotkeys erkannt werden.

    - Icon (rotes X / grüner Haken) für (nicht) registrierten Hotkey hinzugefügt.

  • Schön... die Funktion _ScreenCapture_CaptureWnd scheint bei mehreren Monitoren jedoch fehlerhaft zu sein, denn bei mir werden dann zwei Fenster nebeneinander angezeigt. Ziehe ich min. 16 Pixel von der tatsächlichen Breite des aktiven Windows ab, dann funktioniert es.

    $hCapture = _ScreenCapture_CaptureWnd('', $hWnd, 0, 0, -1, -1, False)

    Local $aPos = WinGetPos($hWnd)

    $hCapture = _ScreenCapture_CaptureWnd('', $hWnd, 0, 0, $aPos[2] - 16, -1, False)

  • die Funktion _ScreenCapture_CaptureWnd scheint bei mehreren Monitoren jedoch fehlerhaft zu sein, denn bei mir werden dann zwei Fenster nebeneinander angezeigt. Ziehe ich min. 16 Pixel von der tatsächlichen Breite des aktiven Windows ab, dann funktioniert es.

    Das kann ich bei mir nicht bestätigen.

    _ScreenCapture_Capture hingegen benutzt immer nur den "Haupt"-Monitor (Desktop).

    Die Funktion müsste man mal umschreiben.

  • Das habe ich mal geändert. Die neue Version (Post #1) funktioniert jetzt auch mit mehreren Monitoren.

    Nein, auch jetzt funktioniert es nicht mit mehreren Monitoren und an den _ScreenCapture-Funktionen hast du ja auch nichts geändert.


    Anzeige 1: -1920,     0,     0,  1080 - sekundärer Bildschirm (Totoal Commander)

    Anzeige 2:     0,     0,  1920,  1080 - primärer Bildschirm (SciTE)

    Ganzer Bildschirm

    - funktioniert auf beiden Monitoren korrekt

    Aktives Fenster

    - auf Anzeige 1: funktioniert korrekt, wenn das Fenster nicht maximiert ist, andernfalls werden beide Bildschirme angezeigt

    - auf Anzeige 2: funktioniert immer korrekt

    Einmal editiert, zuletzt von Bitnugger (11. September 2021 um 19:00)

  • Nein, auch jetzt funktioniert es nicht mit mehreren Monitoren und an den _ScreenCapture-Funktionen hast du ja auch nichts geändert.

    Das ist ja das Problem!

    Bei mir funktioniert das mit dem aktiven Fenster. Egal auf welchem Monitor und egal ob maximiert oder nicht.

    Wie soll ich einen "Fehler" beheben, der bei mir gar nicht auftritt?

    Bei mir ist zwar der primäre Bildschirm links, aber das sollte wohl keine Rolle spielen.

  • Bei mir ist zwar der primäre Bildschirm links, aber das sollte wohl keine Rolle spielen.

    Anscheinend wohl doch... stelle ich es bei mir so um, dass Anzeige 1 auf der rechten Seite ist (was ja nicht der Fall ist), klappt es auch bei mir. Du kannst die Anordnung der Bildschirme ja mal temporär bei dir umstellen... dann wirst du es selbst sehen.

    In der Funktion _Capture habe ich testweise mal folgende Zeile geändert...

    $hCapture = _ScreenCapture_CaptureWnd('', $hWnd, 0, 0, -1, -1, $bCursor)

    Local $tRECT = _WinAPI_GetWindowRect($hWnd)

    $hCapture = _ScreenCapture_Capture('', DllStructGetData($tRECT, 1), DllStructGetData($tRECT, 2), DllStructGetData($tRECT, 3), DllStructGetData($tRECT, 4), $bCursor)

    ...so wird immer nur ein Fenster angezeigt, allerdings stimmt es dann mit dem Border nicht mehr... daran kannst du aber sehen, dass da was mit den Berechnungen bei _ScreenCapture_CaptureWnd falsch läuft.

    Im Else-Zweig machst du $hCapture zu einer lokalen Variable... warum?

  • Anscheinend wohl doch... stelle ich es bei mir so um, dass Anzeige 1 auf der rechten Seite ist (was ja nicht der Fall ist), klappt es auch bei mir. Du kannst die Anordnung der Bildschirme ja mal temporär bei dir umstellen... dann wirst du es selbst sehen.

    Stimmt! So tritt der Fehler auch bei mir auf.

    Das Problem sind die Defaultwerte ("-1") bei den Funktionen.

    Man kann nicht "-1" benutzen, wenn dieser Wert eine korrekte Position darstellt.

    Ich lasse also _ScreenCapture_CaptureWnd jetzt ganz weg und benutze _ScreenCapture_Capture mit den ermittelten Koordinaten.

    Im Else-Zweig machst du $hCapture zu einer lokalen Variable... warum?

    Das war ein Fehler, weil ich zum testen das in einer Funktion kopiert hatte und beim zurückkopieren vergessen habe, das Local zu entfernen.

    Neue Version in Post #1.

  • Sehr schön...

    Bei HotKeySet prüfe ich übrigens mittlerweile immer, ob es funktioniert hat... PRINTSCREEN ist bei mir schon vergeben und ich hatte beim ersten Start min. 5 min gebraucht, bis ich das geschnallt habe.

    HotKeySet('{PRINTSCREEN}', '_Capture') ; Capture-Hotkey festlegen (hier: [Drucken])

    If Not HotKeySet('{PRINTSCREEN}', '_Capture') Then Exit MsgBox(16, @ScriptName, 'Capture-Hotkey "{PRINTSCREEN}" konnte nicht gesetzt werden!')

  • Kann man die Zeile "$bRet = DllCall("dwmapi.dll", "long", "DwmGetWindowAttribute" ..." nicht durch "_WinAPI_DwmGetWindowAttribute(...)" ersetzen?

  • Kann man die Zeile "$bRet = DllCall("dwmapi.dll", "long", "DwmGetWindowAttribute" ..." nicht durch "_WinAPI_DwmGetWindowAttribute(...)" ersetzen?

    Ja kannst du...

    ; needed to get rect when Aero theme is active : Thanks Kafu, Zedna

    $bRet = DllCall("dwmapi.dll", "long", "DwmGetWindowAttribute", _

    "hwnd", $hWnd, _

    "dword", $DWMWA_EXTENDED_FRAME_BOUNDS, _

    "struct*", $tRECT, _

    "dword", DllStructGetSize($tRECT))

    If (@error Or $bRet[0] Or (Abs(DllStructGetData($tRECT, "Left")) + Abs(DllStructGetData($tRECT, "Top")) + _

    Abs(DllStructGetData($tRECT, "Right")) + Abs(DllStructGetData($tRECT, "Bottom"))) = 0) Then

    $tRECT = _WinAPI_DwmGetWindowAttribute($hWnd, $DWMWA_EXTENDED_FRAME_BOUNDS)

    If (@error Or (Abs(DllStructGetData($tRECT, "Left")) + Abs(DllStructGetData($tRECT, "Top")) + _

    Abs(DllStructGetData($tRECT, "Right")) + Abs(DllStructGetData($tRECT, "Bottom"))) = 0) Then

  • Wenn die Strukturen Variablen mit Alias enthalten, finde ich diese Darstellung übersichtlicher:

    Stimmt... muss ich mir endlich mal angewöhnen, vergesse es immer wieder, obwohl es so superpraktisch ist.

    Tweaky

    Dann kannst du folgende Zeile...

    If (@error Or (Abs(DllStructGetData($tRECT, "Left")) + Abs(DllStructGetData($tRECT, "Top")) + _

    Abs(DllStructGetData($tRECT, "Right")) + Abs(DllStructGetData($tRECT, "Bottom"))) = 0) Then

    so ändern...

    If (@error Or (Abs($tRECT.Left) + Abs($tRECT.Top) + Abs($tRECT.Right) + Abs($tRECT.Bottom)) = 0) Then

  • Ich habe das Programm jetzt dahingehend geändert, dass der Anwender den Hotkey selbst festlegen kann (Tasten begrenzt).

    _SetHotkey funktioniert nicht, wenn PRINTSCREEN bereits von einer anderen Anwendung gesetzt wurde... und hat man es einmal geändert, z.B. auf F4, kann man PRINTSCREEN nicht mehr auswählen, weil es im Combo nicht angezeigt wird.

    Tasten begrenzt... weniger geht ja nicht... was mache ich, wenn ich z. B. Strg + Shift + F4 benötige? Das solltest du aber dringend noch mal überarbeiten... ansonsten - sehr schön!

  • GUI mit 1x1 Pixel Größe OnTop in eine Ecke setzen und mit GuiSetAcceletator arbeiten, dann gibt es keine Hotkey-Probleme.

    Das funktioniert nur, wenn das Accelerator-Fenster aktiv ist. Und das ist etwas kontraproduktiv, wenn ich ja das aktive Fenster capturen will.


    Tasten begrenzt... weniger geht ja nicht... was mache ich, wenn ich z. B. Strg + Shift + F4 benötige?

    Naja, das ist ja kein Programm zum starten von dutzenden von Funktionen.

    Es geht hier doch nur darum, einen Hotkey zum capturen festzulegen und IMHO sollten die 64 Möglichkeiten doch wohl ausreichen.

    Das Problem mit dem bereits registrierten Hotkey habe ich jetzt nochmal überarbeitet. So sollte das jetzt funktionieren. Neue Version in Post #1.

  • Naja, das ist ja kein Programm zum starten von dutzenden von Funktionen.

    Es geht hier doch nur darum, einen Hotkey zum capturen festzulegen und IMHO sollten die 64 Möglichkeiten doch wohl ausreichen.

    Ja, ok... hast ja Recht... mir persönlich hat die vorherige Version besser gefallen, weil ich da genau den Hotkey festlegen kann, den ich haben will.

    Was du noch ändern könntest... für die HotkeyModifiers (Alt|Ctrl|Shift|Win) kein Combo verwenden, mit dem ich ja nur einen davon auswählen kann, sondern Checkboxen, denn so wäre dann z.B. auch Alt + Ctrl + Shift + F4 möglich.

    Alternativ kannst du für die Auswahl des Hotkey aber auch eine kleine UDF verwenden, mit der dir alle Möglichkeiten offenstehen - (korrigierte) UDF inkl. Demo im Anhang. Link dazu ist im Script hinterlegt.