Einige Probleme mit GUIs Topic is solved

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
Scr1pter
Posts: 1271
Joined: 06 Aug 2017, 08:21
Location: Germany

Einige Probleme mit GUIs

03 Jan 2019, 14:27

Hi Leute,

ich wollte "unser Forum" mal wieder etwas ankurbeln. :)

Kurze Erläuterung, um was genau es hier geht:
Ich hab eine Funktion programmiert, die eine GUI am unteren rechten Bildschirmrand einblendet.
Die GUI zeigt die folgenden 3 Textzeilen an:
- Titel des Skripts (Parameter - variiert also)
- Anweisungen für den User (ebenfalls Parameter)
- Hinweis, wie das Skript wieder beendet wird (kein Parameter - fester Wert)

Das ist meine GUI-Funktion:

Code: Select all

Gui_mit_Effekt(modus, titel, anweisung) ; Gui ein bzw. ausblenden, Titel anzeigen, Anweisung anzeigen
{
  if modus = 1 ; Wenn Gui angezeigt werden soll:
  {
    SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback beim Start
    Gui +E0x20 -Caption +LastFound +ToolWindow +AlwaysOnTop ; Durchklickbar, rahmenlos, zuletzt gefunden, kein Taskleistensymbol, immer im Vordergrung
    Gui, Add, Picture, x0 y0 w300 h200, %A_ScriptDir%\Guis\Hintergrund.jpg ; Hintergrund (Bild)
    Gui, Font, s18, Arial ; Schriftgröße und Schriftart für Titel
    Gui, Add, Text, BackgroundTrans x20 y10 w300 h30 cWhite, %titel% ; Titel des Skripts (Text)
    Gui, Font, s14, Arial ; Schriftgröße und Schriftart für die weiteren Textzeilen
    Gui, Add, Text, BackgroundTrans x20 y60 w300 h90 cWhite, %anweisung% ; Anweisungen an den User (Text)
    Gui, Add, Text, BackgroundTrans x20 y180 w300 h30 cWhite, Zum Beenden ESC drücken ; Hinweis, wie das Skript beendet wird (Text)
    Gui, Show, NoActivate x1600 y800 w300 h200, Gui-Information ; Gui anzeigen, Fokus nicht beeinflussen, Positionierung, Abmessung, Name (Gui ist noch unsichtbar) 
    fade := 1 ; Variable für Einblend-Effekt
    Loop 25 ; 25x die Transparenz ändern
    {
      fade := fade + 9 ; Wert für Einblend-Effekt erhöhen
      WinSet, Transparent, %fade% ; Transparenz des Fensters einstellen
      if fade = 10 ; Beim ersten Durchgang:
      {
        WinShow, NoActivate, Gui-Info ; Gui namens Gui-Info anzeigen, Fokus nicht beeinflussen
      }
      Sleep, 10 ; Alle 10 ms etwas mehr einblenden 
    }
    Sleep, 800 ; Pufferzeit (kann später entfernt werden)
  }
  if modus = 0 ; Wenn Gui ausgeblendet werden soll:
  {
    fade := 226 ; Variable für Ausblend-Effekt
    Loop 25 ; 25x die Transparenz ändern
    {
      fade := fade - 9 ; Wert für Ausblend-Effekt erhöhen
      WinSet, Transparent, %fade% ; Transparenz des Fensters einstellen
      if fade = 217 ; Beim ersten Durchgang:
      {
        WinShow, NoActivate, Gui-Info ; Gui namens Gui-Info anzeigen, Fokus nicht beeinflussen
      }
      Sleep, 10 ; Alle 10 ms etwas mehr ausblenden
    }
    Gui, Destroy ; Gui zerstören
  }
}
Wenn ich diese Funktion nun aufrufen will, schreibe ich in meinem Hauptcode nur:

Code: Select all

^Numpad1::
Gui_mit_Effekt(1, "Das ist ein Test", "1)`nKlick auf die Endposition und fahre mit diesem Test fort") ; Gui einblenden, Titel, Beschreibung
Sleep, 2000
Gui_mit_Effekt(0, "", "") ; Gui ausblenden
return
Dieses Beispiel funktioniert einwandfrei - alles läuft genau so, wie ich es will.

Allerdings gibt es 3 Probleme, die ich derzeit nicht lösen kann:
1) Ausblenden über separaten Hotkey

Code: Select all

^Numpad2::
Gui_mit_Effekt(0, "", "") ; Gui ausblenden
return
Mit diesem Code wird die Gui beendet aber nicht ausgeblendet.
Auch wenn es funktionell gesehen in Ordnung ist, verstehe ich nicht, warum der Ausblend-Effekt plötzlich nicht mehr umgesetzt wird.
Eigentlich ist es praktisch genau das gleiche wie oben, nur das es nach Sleep 800 erst weitergeht, wenn ich Strg+Num2 drücke (theoretisch).

2) Zentrieren des Textes
Ich habe es nicht hinbekommen, alle 3 Textzeilen zu zentrieren
Versuche ich es nur mit dem Titel, wird dieser nicht mehr angezeigt
Gui, Add, Text, BackgroundTrans Center w300 h30 cWhite, %titel% ; Titel des Skripts (Text) - NICHT SICHTBAR

Wenn ich es nur mit der 2. probiere (der Anweisung), klappt es halbwegs:
Gui, Add, Text, BackgroundTrans Center w300 h90 cWhite, %anweisung% ; Anweisung an User (Text) - KLAPPT
(Halbwegs, weil etwas vom Rand abgeschnitten wird)

Bei Nr 2 und 3 klappt es auch, aber hier wieder am Ende was abgeschnitten:
Gui, Add, Text, BackgroundTrans Center w300 h30 cWhite, Zum Beenden ESC drücken ; Fußbereich des Skripts (Text)

3) Ändern von Text (Anweisung)
Mit diesem Test-Skript habe ich es hinbekommen, sowohl den Text mit Hotkeys zu ändern
als ihn auch eintippen zu lassen (so als Effekt).
Es funktioniert gut:

Code: Select all

!Numpad3::
gui, add, text, w200 vText
gui, add, text,, Text mittels Numpad ändern!
gui, show, w220 h100
return

!Numpad4::
Gui_Text_Ändern("das ist ein text!", "text") ; Zeichenkette, Textfeld
return

!Numpad5::
Gui_Text_Ändern("jetzt kommt die nummer 2!", "text") ; Zeichenkette, Textfeld
return

Gui_Text_Ändern(zeichenkette, feld) ; Zeichenkette, Textfeld
{
  zeichenkette = %zeichenkette% ; Diesen Text in der Gui anzeigen
  länge := StrLen(zeichenkette) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  Loop, %länge% ; Anzahl der Vorgänge = Anzahl der Zeichen
  {
    trimmen := länge - A_Index ; trimmen = länge - Nr. des Durchgangs (z.B. 15, 14, 13 etc.)
    StringTrimRight, zeichenketteEinzeln, zeichenkette, trimmen ; In jedem Durchgang ein Zeichen weniger abschneiden
    guiControl, text, %feld%, %zeichenketteEinzeln% ; Text in der Gui aktualisieren
    Sleep, 20 ; Kurze Verzögerung
  }  
}
Wenn ich die gleiche Logik nun auf meine echte Gui-Funktion übertragen will, erscheint beim Start eine Fehlermeldung:
"Error: A control's variable must be global or static.
global Anweisung
oder
global vAnweisung
hat schon mal nicht funktioniert.

Gui, Add, Text, BackgroundTrans Center w300 h90 cWhite vAnweisung, %anweisung% ; Anweisung an User (Text)

Im Moment sieht es so hier aus:
Image
(Natürlich ohne die vAnweisung-Variante, die ja bisher noch nicht funktioniert.)

Danke für jede Hilfe!

Grüße
Please use [code][/code] when posting code!
Keyboard: Logitech G PRO - Mouse: Logitech G502 LS - OS: Windows 10 Pro 64 Bit - AHK version: 1.1.33.09
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Einige Probleme mit GUIs

04 Jan 2019, 11:01

Moin,

das sind sehr schöne Fragen. :bravo:

zu 1):
In AHK haben die unterschiedlichen (Pseudo-)Threads eigene Umgebungen bzw. A_Variablen. Zu den threadbezogenen Umgebungswerten gehört auch das last-found window. Das wird in Deiner Funktion nur gesetzt, wenn das GUI angezeigt wird:

Code: Select all

    Gui +E0x20 -Caption +LastFound +ToolWindow +AlwaysOnTop ; Durchklickbar, rahmenlos, zuletzt gefunden, kein Taskleistensymbol, immer im Vordergrung
Wenn Du nun in der Routine (dem Thread) ^Numpad1:: die Funktion zweimal aufrufst, wird beim ersten Aufruf (zum Anzeigen) das last-found-window gesetzt und bleibt auch bis zum zweiten Aufruf (zum Ausblenden) erhalten. Deshalb findet

Code: Select all

      WinSet, Transparent, %fade% ; Transparenz des Fensters einstellen
auch noch beim Ausblenden das richtige Fenster.


Der Thread ^Numpad2:: ist ebenfalls ein Nicht-GUI-Thread. Der Umgebungswert last-found window ist deshalb zunächst einmal nicht gesetzt. Wenn die Funktion dann nur zum Ausblenden aufgerufen wird, findet

Code: Select all

      WinSet, Transparent, %fade% ; Transparenz des Fensters einstellen
kein Fenster.



zu 2):

Code: Select all

    Gui, Add, Picture, x0 y0 w300 h200, %A_ScriptDir%\Guis\Hintergrund.jpg ; Hintergrund (Bild)
Du erstellst ein GUI mit einem flächenfüllenden Hintergrundbild, das auf die Position 0:0 gesetzt wird. Es gibt deshalb um das Bild herum links und oben keinen Rand.

Code: Select all

    Gui, Show, NoActivate x1600 y800 w300 h200, Gui-Information ; Gui anzeigen, Fokus nicht beeinflussen, Positionierung, Abmessung, Name (Gui ist noch unsichtbar)
Dann legst Du für den Clientbereich des GUI eine Breite und eine Höhe fest, die den der Breite bzw. der Höhe des Bildes entsprechen. Damit gibt es auch rechts und unterhalb des Bildes keinen Rand.

Code: Select all

    Gui, Add, Text, BackgroundTrans x20 y10 w300 h30 cWhite, %titel% ; Titel des Skripts (Text)
Die Textfelder legst Du auf die X-Position 20 mit einer Breiten von 300 Pixeln. Die Felder reichen deshalb bis zur Position 320 und damit über den sichtbaren Bereich des Fensters hinaus. Wenn Du diese Felder zentrierts, sieht das entweder nur schief aus oder die Anzeige wird sogar rechts abgeschnitten.


Zu 3) melde ich mich später noch einmal (falls noch erforderlich).
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Einige Probleme mit GUIs

04 Jan 2019, 11:43

zu 3):

Code: Select all

Gui, Add, Text, BackgroundTrans Center w300 h90 cWhite vAnweisung, %anweisung% ; Anweisung an User (Text)
Wenn Du diese Anweisung in die GUI-Funktion stellst, sollte Global Anweisung am Beginn der Funktion alles richten. Falls doch nicht, kannst Du in diesem Fall auch die ClassNN als Control-ID nutzen. Bild- und Textcontrols teilen sich die Klasse Static. Sie werden im Normalfall in der Reihenfolge des Hinzufügens zum Fenster durchnummeriert. Daraus ergeben sich folgende ClassNNs:

Code: Select all

Control                    ClassNN
----------------------------------
Bild                       Static1
Textfeld 1 (Titel)         Static2
Textfeld 2 (Anweisung)     Static3
Textfeld 3 (Hinweis)       Static4


P.S.: Ich danke Dir, dass ich das 'auf Deutsch' beantworten durfte. Das Übersetzen kostet mich zuweilen immer noch viel Mühe und Zeit.
User avatar
Scr1pter
Posts: 1271
Joined: 06 Aug 2017, 08:21
Location: Germany

Re: Einige Probleme mit GUIs

04 Jan 2019, 19:04

Hallo und vielen Dank für deine umfangreichen Antworten :thumbup:
Ich hatte mich heute (bevor du geantwortet hast) nochmals mit der Materie befasst.

Ok, kommen wir nun zu den Punkten.
1)
Das ergibt natürlich Sinn, was du schreibst.
In der Tat hat es einfach nur gereicht, die
Gui +E0x20 -Caption +LastFound +ToolWindow +AlwaysOnTop ; Durchklickbar, rahmenlos, zuletzt gefunden, kein Taskleistensymbol, immer im Vordergrung
über die if-Abfrage zu stellen, so dass sie nun immer aufgerufen wird.

2)
Also so richtig hingekommen hab ich es nicht (mit Center).
Hab jetzt eine Hilfsfunktion erstellt, die anhand der Feldbreite und der Anzahl der Zeichen den Text zentriert.

Code: Select all

  längeTitel := StrLen(titel) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  pixelTitel := längeTitel * 5,375 ; Pixel = Titellänge * Skallierungswert
  positionTitel := 300 / 2 - pixelTitel ; = Breite der GUI / 2 - ermittelte Pixelanzahl
Klappt ganz gut.
Werde es aber nur für Titel und Fußbereich nutzen, daher werde ich wohl keine "echte Funktion" erstellen,
sondern es einfach nur in den GUI-Code reinschreiben

3)
Mit
global Anweisung hat es nicht geklappt (wieder eine Fehlermeldung), aber die Idee mit static ist sehr gut und klappt!
Z.B.

Code: Select all

!Numpad3::
Gui_Text_Ändern("Schritt 3", "Static3") ; Zeichenkette, Textfeld
return
bzw

Code: Select all

!Numpad3::
SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback bei Textänderung
Sleep, d
Gui_Text_Ändern("Schritt 3:", "Static3") ; Zeichenkette, Textfeld
Sleep, d
Gui_Text_Ändern("Das hier ist die dritte Anweisung", "Static4") ; Zeichenkette, Textfeld
return

Code: Select all

Gui_Text_Ändern(zeichenkette, feld) ; Zeichenkette, Textfeld - #FUNKTION#
{
  guiControl, text, %feld%,  ; Text in der Gui löschen
  Sleep, 100
  zeichenkette = %zeichenkette% ; Diesen Text in der Gui anzeigen
  länge := StrLen(zeichenkette) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  Loop, %länge% ; Anzahl der Vorgänge = Anzahl der Zeichen
  {
    trimmen := länge - A_Index ; trimmen = länge - Nr. des Durchgangs (z.B. 15, 14, 13 etc.)
    StringTrimRight, zeichenketteEinzeln, zeichenkette, trimmen ; In jedem Durchgang ein Zeichen weniger abschneiden
    guiControl, text, %feld%, %zeichenketteEinzeln% ; Text in der Gui aktualisieren
    Sleep, 15 ; Kurze Verzögerung
  }  
}
Ich hab die Funktionen noch nicht optimiert, daher rufe ich sie auch 2x auf.
Obwohl es von der Funktionalität her klappt, gibt's beim Aufrufen der Text_Ändern-Funktion ab und zu ein Flackern.
Hab es als Bildschirmvideo aufgenommen, aber da sieht es gut aus (wahrscheinlich weil die FPS nicht hoch genug waren.)

Meine Idee, die Text_Ändern-Funktion für 2 Felder zu erstellen, hat nicht funktioniert:

Code: Select all


Gui_Text_Ändern("Schritt 2:", "Static3", "Dies ist die zweite Anweisung", "Static4") ; Zeichenkette, Textfeld

Gui_Text_Ändern(zeichenkette1, feld1, zeichenkette2, feld2) ; Zeichenkette, Textfeld - #FUNKTION#
{
  Loop, 2
  {
    i++ ; Zähler
    guiControl, text, %feld%%i%, ; Text in der Gui löschen
    Sleep, 100
    ;zeichenkette = %zeichenkette1% ; Diesen Text in der Gui anzeigen - KLAPPT
    zeichenkette = %zeichenkette%%i% ; Diesen Text in der Gui anzeigen - KLAPPT NICHT - Wert ist nur 1, wahrscheinlich weil es "Zeichenkette" nicht gibt, nur Zeichenkette1
    MsgBox, %zeichenkette%
    länge := StrLen(zeichenkette) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
    Loop, %länge% ; Anzahl der Vorgänge = Anzahl der Zeichen
    {
      trimmen := länge - A_Index ; trimmen = länge - Nr. des Durchgangs (z.B. 15, 14, 13 etc.)
      StringTrimRight, zeichenketteEinzeln, zeichenkette, trimmen ; In jedem Durchgang ein Zeichen weniger abschneiden
      guiControl, text, %feld%%i%, %zeichenketteEinzeln% ; Text in der Gui aktualisieren
      Sleep, 15 ; Kurze Verzögerung
    }
  }
  i = 0
}
Habe jetzt aber allgemein nochmal überlegt, ob das mit den GUI-Funktionen wirklich so viel Sinn ergibt.
Mir geht's nur darum, dass ich in meinem Hauptskript (wenn ich mal eine GUI nutzen will), nicht den Bildschirm mit GUI-Infos fülle.
(Daher wollte ich ja die GUI-Funktionen nutzen).

Alternativ kann ich aber einen GUI-Ordner in meinem AHK-Skript-Verzeichnis erstellen, in dem ich alle GUIs als einzelne Skripte reinplatziere.
Im Hauptskript schreib ich dann z.B. nur:

Code: Select all

titel = Erweiterter Filter für Spalte D ; Titel des Skripts
beschreibung = Maximal 2 Begriffe - getrennt durch Plus (UND) oder Komma (ODER): ; Beschreibung der in GUI anzeigen
#include Guis\Gui-Inputbox.ahk ; Inputbox-Artige GUI einbinden
(In den meisten Fällen reicht mir eine einfache InputBox, aber eine eigene GUI ist mir dennoch lieber.)

Das ist das aktuelle Skript - ist noch 'ne ziemliche Baustelle - morgen bzw. heute mache ich weiter.

Code: Select all

^Numpad1::
Gui_mit_Effekt(1, "Testüberschrift", "Schritt 1:", "Klick auf die Endposition und fahr mit diesem Test fort", "ESC zum Beenden drücken") ; Gui einblenden, Titel, Beschreibung
return

!Numpad2::
SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback bei Textänderung
Sleep, d
Gui_Text_Ändern("Schritt 2:", "Static3") ; Zeichenkette, Textfeld
Sleep, d
Gui_Text_Ändern("Dies ist die zweite Anweisung", "Static4") ; Zeichenkette, Textfeld
return

!Numpad3::
SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback bei Textänderung
Sleep, d
Gui_Text_Ändern("Schritt 3:", "Static3") ; Zeichenkette, Textfeld
Sleep, d
Gui_Text_Ändern("Das hier ist die dritte Anweisung", "Static4") ; Zeichenkette, Textfeld
return

Gui_mit_Effekt(modus, titel, schritt, anweisung, fußbereich) ; Gui ein bzw. ausblenden, Titel anzeigen, Anweisung anzeigen - #FUNKTION#
{
  guiMitEffekt := !guiMitEffekt ; guiMitEffekt-Modus ein- bzw. ausschalten (toggle)
  längeTitel := StrLen(titel) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  pixelTitel := längeTitel * 5,375 ; Pixel = Titellänge * Skallierungswert
  positionTitel := 300 / 2 - pixelTitel ; = Breite der GUI / 2 - ermittelte Pixelanzahl
    
  längeFußbereich := StrLen(Fußbereich) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  pixelFußbereich := längeFußbereich * 5,375 ; Pixel = Titellänge * Skallierungswert
  positionFußbereich := 300 / 2 - pixelFußbereich ; = Breite der GUI / 2 - ermittelte Pixelanzahl  
  
  Gui +E0x20 -Caption +LastFound +ToolWindow +AlwaysOnTop ; Durchklickbar, rahmenlos, zuletzt gefunden, kein Taskleistensymbol, immer im Vordergrung
  if modus = 1 ; Wenn Gui angezeigt werden soll:
  {
    SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback beim Start    
    Gui, Add, Picture, x0 y0 w300 h200, %A_ScriptDir%\Guis\Hintergrund.jpg ; Hintergrund (Bild)
    Gui, Font, s18, Arial ; Schriftgröße und Schriftart
    
    Gui, Add, Text, BackgroundTrans x%positionTitel% w300 y10 w280 cWhite, %titel% ; Titel des Skripts (Text)
    Gui, Font, s14, Arial ; Schriftgröße und Schriftart

    Gui, Add, Text, BackgroundTrans x10 y50 w280 cWhite, %schritt% ; Schritt (Text)
    Gui, Add, Text, BackgroundTrans x10 y80 w280 h90 cWhite, %anweisung% ; Anweisung an User (Text)
    
    Gui, Add, Text, BackgroundTrans x%positionFußbereich% y170 w300 cWhite, %fußbereich% ; Fußbereich des Skripts (Text)
    Gui, Show, NoActivate x1600 y800 w300 h200, Gui-Information ; Gui anzeigen, Fokus nicht ändern, Positionierung, Abmessung, Name (Gui ist noch unsichtbar) 
    fade := 1 ; Variable für Einblend-Effekt
    Loop 25 ; 25x die Transparenz ändern
    {
      fade := fade + 9 ; Einblend-Effekt
      WinSet, Transparent, %fade% ; Einblendeffekt erhöhen
      if fade = 10 ; Beim ersten Durchgang:
      {
        WinShow, NoActivate, Gui-Info ; Gui anzeigen
      }
      Sleep, 10 ; Alle 10 ms etwas mehr einblenden 
    }
  }
  if modus = 0 ; Wenn Gui ausgeblendet werden soll:
  {
    fade := 226 ; Variable für Ausblend-Effekt
    Loop 25 ; 25x die Transparenz ändern
    {
      fade := fade - 9 ; Ausblend-Effekt
      WinSet, Transparent, %fade% ; Ausblendeffekt erhöhen
      if fade = 217 ; Beim ersten Durchgang:
      {
        WinShow, NoActivate, Gui-Info ; Gui anzeigen
      }
      Sleep, 10 ; Alle 10 ms etwas mehr ausblenden
    }
    Gui, Destroy ; Gui zerstören
  }
}
Gui_Text_Ändern(zeichenkette, feld) ; Zeichenkette, Textfeld - #FUNKTION#
{
  guiControl, text, %feld%,  ; Text in der Gui löschen
  Sleep, 100
  zeichenkette = %zeichenkette% ; Diesen Text in der Gui anzeigen
  länge := StrLen(zeichenkette) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  Loop, %länge% ; Anzahl der Vorgänge = Anzahl der Zeichen
  {
    trimmen := länge - A_Index ; trimmen = länge - Nr. des Durchgangs (z.B. 15, 14, 13 etc.)
    StringTrimRight, zeichenketteEinzeln, zeichenkette, trimmen ; In jedem Durchgang ein Zeichen weniger abschneiden
    guiControl, text, %feld%, %zeichenketteEinzeln% ; Text in der Gui aktualisieren
    Sleep, 15 ; Kurze Verzögerung
  }  
}
P.S.
Ja, ab und zu muss ich auch mal bei dict.cc einige Wörter nachschlagen.
Mein Hauptproblem ist aber, dass ich meine Variablen und Kommentare gern auf Deutsch schreibe - auch wenn das nicht "Best Practice" ist.
Im englischen Forum übersetze ich daher meist immer alles - oder ich schreibe die beta-Skripte und Englisch und übersetze die finals auf Deutsch.

Viele Grüße
Please use [code][/code] when posting code!
Keyboard: Logitech G PRO - Mouse: Logitech G502 LS - OS: Windows 10 Pro 64 Bit - AHK version: 1.1.33.09
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Einige Probleme mit GUIs

05 Jan 2019, 02:49

Moin,

3)
Mit
global Anweisung hat es nicht geklappt ...
Mein Fehler! Ich habe übersehen, dass die Funktion den Variablennamen anweisung als Parameternamen nutzt. Damit ist anweisung automatisch eine funktionslokale Variable und kann nicht als global erkärt werden. Du müsstest deshalb entweder den Parameter- oder den Guivariablennamen ändern, wenn du diese Lösung überhaupt nutzen willst.

Zum Rest vielleicht später noch etwas.

Grüße,
just me
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Einige Probleme mit GUIs  Topic is solved

05 Jan 2019, 05:02

Ich nochmal!

Ja, über Sinn und Zweck des 'GuiInAFunction'-Konzept lässt sich trefflich streiten. Nach Einführung der Klassenobjekte in AHK würde ich eher in diese Richtung tendieren. Mit Deiner letzten Version von Gui_mit_Effekt() habe ich aber auch noch einige Verständnisprobleme.

Code: Select all

  guiMitEffekt := !guiMitEffekt ; guiMitEffekt-Modus ein- bzw. ausschalten (toggle)
Wird hier gesetzt aber sonst nicht verwendet.

Code: Select all

  längeTitel := StrLen(titel) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  pixelTitel := längeTitel * 5,375 ; Pixel = Titellänge * Skallierungswert
  positionTitel := 300 / 2 - pixelTitel ; = Breite der GUI / 2 - ermittelte Pixelanzahl
Das soll ja wohl eine X-Position berechnen, die zu einer zentrierten Darstellung führt. Warum lässt Du das nicht AHK erledigen? Dein GUI hat einen fest vorgegebenen Clientbereich mit einer Breite von 300 und einer Höhe von 200 Pixeln. Alles, was angezeigt werden soll, sollte vollständig in diesem Bereich liegen. Daraus folgt, dass alle Textfelder maximal 300 Pixel breit sein können, und das auch nur dann, wenn sie auf der X-Position 0 beginnen. Wenn Du einen festen linken Rand von 10 Pixeln haben willst, solltest Du die schon mal von der Maximalbreite abziehen:

Code: Select all

; überdeutliche Darstellung
MaxW := 300
X := 10
W := MaxW - X ; X für den rechten Rand -> 290
Gui, Add, Text, x%X% w%W% ...
Wenn der Inhalt des Textfeldes zentriert bezogen auf das Textfeld und das GUI dargestellt werden soll, musst Du ihm im GUI einen linken Rand verpassen, der dem rechten entspricht. Der verringert ebenfalls die maximale Breite:

Code: Select all

; überdeutliche Darstellung
MaxW := 300
X := 10
W := MaxW - X - X ; zweimal X für den rechten und den linken Rand -> 280
Gui, Add, Text, x%X% w%W% Center ...
Probleme sollte es damit nur dann geben, wenn der übergebene Text nicht in das Textfeld passt. Dein Ansatz bietet dafür aber auch keine Lösung.

Hier mal ein Beispiel.Ich habe Dein Bild durch eine einfarbige Bitmap ersetzt:

Code: Select all

^Numpad1::
Gui_mit_Effekt(1, "Testüberschrift", "Schritt 1:", "Klick auf die Endposition und fahr mit diesem Test fort", "ESC zum Beenden drücken") ; Gui einblenden, Titel, Beschreibung
return

!Numpad2::
SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback bei Textänderung
Sleep, d
Gui_Text_Ändern("Schritt 2:", "Static3") ; Zeichenkette, Textfeld
Sleep, d
Gui_Text_Ändern("Dies ist die zweite Anweisung", "Static4") ; Zeichenkette, Textfeld
return

!Numpad3::
SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback bei Textänderung
Sleep, d
Gui_Text_Ändern("Schritt 3:", "Static3") ; Zeichenkette, Textfeld
Sleep, d
Gui_Text_Ändern("Das hier ist die dritte Anweisung", "Static4") ; Zeichenkette, Textfeld
return

Gui_mit_Effekt(modus, titel, schritt, anweisung, fußbereich) ; Gui ein bzw. ausblenden, Titel anzeigen, Anweisung anzeigen - #FUNKTION#
{
   If (Modus = 1) ; Wenn Gui angezeigt werden soll:
   {
      SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback beim Start
      Gui +E0x20 -Caption +LastFound +ToolWindow +AlwaysOnTop ; Durchklickbar, rahmenlos, zuletzt gefunden, kein Taskleistensymbol, immer im Vordergrung
      Gui, Margin, 0, 0 ; wenn man die volle Kontrolle über die Ränder haben will, Automatik abschalten
      Gui, Add, Picture, x0 y0 w300 h200, % "HBITMAP:" . CreateDIB(0x008000) ; %A_ScriptDir%\Guis\Hintergrund.jpg ; Hintergrund (Bild)

      Gui, Font, s18, Arial ; Schriftgröße und Schriftart für den Titel
      Gui, Add, Text, BackgroundTrans x10 y10 w280 cWhite Center, %titel% ; Titel des Skripts (Text)

      Gui, Font, s14, Arial ; Schriftgröße und Schriftart für den Rest
      Gui, Add, Text, BackgroundTrans x10 y50 w280 cWhite, %schritt% ; Schritt (Text)
      Gui, Add, Text, BackgroundTrans x10 y80 w280 h90 cWhite, %anweisung% ; Anweisung an User (Text)
      Gui, Add, Text, BackgroundTrans x10 y170 w280 cWhite Center, %fußbereich% ; Fußbereich des Skripts (Text)
      Gui, Show, NoActivate x1600 y800 w300 h200, Gui-Information ; Gui anzeigen, Fokus nicht ändern, Positionierung, Abmessung, Name (Gui ist noch unsichtbar)
      Fade := 1 ; Variable für Einblend-Effekt
      Loop 25 ; 25x die Transparenz ändern
      {
         Fade := Fade + 9 ; Einblend-Effekt
         WinSet, Transparent, %Fade% ; Einblendeffekt erhöhen (last-found window)
         If (Fade = 10) ; Beim ersten Durchgang:
            WinShow, NoActivate ; Gui anzeigen (last-found window)
         Sleep, 10 ; Alle 10 ms etwas mehr einblenden
      }
   }
   If (Modus = 0) ; Wenn Gui ausgeblendet werden soll:
   {
      Gui, +LastFound ; sicherheitshalber das 'last-found window' setzen
      Fade := 226 ; Variable für Ausblend-Effekt
      Loop 25 ; 25x die Transparenz ändern
      {
         Fade := Fade - 9 ; Ausblend-Effekt
         WinSet, Transparent, %Fade% ; Ausblendeffekt erhöhen (last-found window)
         If (Fade = 217) ; Beim ersten Durchgang:
            WinShow, NoActivate ; Gui anzeigen (last-found window)
         Sleep, 10 ; Alle 10 ms etwas mehr ausblenden
      }
      Gui, Destroy ; Gui zerstören
   }
}

Gui_Text_Ändern(zeichenkette, feld) ; Zeichenkette, Textfeld - #FUNKTION#
{
  guiControl, text, %feld%,  ; Text in der Gui löschen
  Sleep, 100
  zeichenkette = %zeichenkette% ; Diesen Text in der Gui anzeigen
  länge := StrLen(zeichenkette) ; länge = Anzahl der Zeichen, die sich in zeichenkette befinden
  Loop, %länge% ; Anzahl der Vorgänge = Anzahl der Zeichen
  {
    trimmen := länge - A_Index ; trimmen = länge - Nr. des Durchgangs (z.B. 15, 14, 13 etc.)
    StringTrimRight, zeichenketteEinzeln, zeichenkette, trimmen ; In jedem Durchgang ein Zeichen weniger abschneiden
    guiControl, text, %feld%, %zeichenketteEinzeln% ; Text in der Gui aktualisieren
    Sleep, 15 ; Kurze Verzögerung
  }
}

; ================================================================================================================================
; Modified version of a function by SKAN, 01-Apr-2014, autohotkey.com/boards/viewtopic.php?t=3203
; Creates an uni-colored bitmap of 1 * 1 pixels.
; ================================================================================================================================
CreateDIB(Color) {
   VarSetCapacity(BMBITS, 4, 0)
   , Numput(Color, BMBITS, "UInt")
   , HBM := DllCall("CreateBitmap", "Int", 1, "Int", 1, "UInt", 1, "UInt", 24, "Ptr", 0, "UPtr")
   , HBM := DllCall("CopyImage", "Ptr", HBM, "UInt", 0, "Int", 0, "Int", 0, "UInt", 0x2008, "UPtr")
   , DllCall("SetBitmapBits", "Ptr", HBM, "UInt", 4, "Ptr", &BMBITS)
   Return HBM
}
Das ergibt für mich folgendes Fenster:
GuiTest.PNG
GuiTest.PNG (5.82 KiB) Viewed 2008 times
User avatar
Scr1pter
Posts: 1271
Joined: 06 Aug 2017, 08:21
Location: Germany

Re: Einige Probleme mit GUIs

05 Jan 2019, 11:12

Hi!

Das mit Punkt 3 ist gut zu wissen.
Ich habe es versucht und es hat geklappt.

Code: Select all

Gui_mit_Effekt(modus, titel, schritt, anweisung, fußbereich) ; Gui ein bzw. ausblenden, Titel anzeigen, Anweisung anzeigen - #FUNKTION#
{
  global schritte, anweisungen
.
.
.

    Gui, Add, Text, BackgroundTrans x10 y50 w280 cWhite vSchritte, %schritt% ; Schritt (Text)
    Gui, Add, Text, BackgroundTrans x10 y80 w280 h90 cWhite vAnweisungen, %anweisung% ; Anweisung an User (Text)
.
.
.
Der Aufruf war dann ganz einfach: (habe das Problem mit dem doppelten Aufrufen der Gui_Text_Ändern() übrigens gelöst)

Code: Select all

F2::
Gui_Text_Ändern3("Schritt 2:", "schritte", "Dies ist die zweite Anweisung", "anweisungen") ; Zeichenkette1, Textfeld1, Zeichenkette2, Textfeld2
return

Gui_Text_Ändern3(zeichenkette1, feld1, zeichenkette2, feld2) ; Zeichenkette1, Textfeld1, Zeichenkette2, Textfeld2 - #FUNKTION#
{
  SoundPlay, %A_ScriptDir%\Guis\SoundAn.wav ; Akustisches Feedback bei Textänderung
  Loop, 2 ; 1 Feld pro Durchgang bearbeiten
  {
    zeichenkette := zeichenkette%A_Index% ; zeichenkette = Aktuelle zeichenkette (wird später in der GUI angezeigt)
    feld         := feld%A_Index% ; feld = Aktuelles Feld (wird später in der GUI angezeigt)
    guiControl, text, %feld%, %zeichenkette% ; Text in der GUI aktualisieren
  }  
}

Die Idee mit static ist echt interessant gewesen, setzt aber voraus, dass ich immer die genaue Reihenfolge der Felder kenne.
global schritte, anweisungen sind da denke ich sicherer, falls ich doch mal paar neue Felder hinzufüge.

Bezüglich:
guiMitEffekt := !guiMitEffekt ; guiMitEffekt-Modus ein- bzw. ausschalten (toggle)
Sinn dieser Variable ist es, einen #if-Block zu aktivieren/deaktivieren.
Dadurch werden z.B. Mausklicks nur für die GUI-Funktion freigegeben.
(Ich hatte das testweise im Einsatz und es lief einwandfrei - in den Codes in diesem Thread war es nicht dabei, das stimmt.)

Zum Thema zentrieren:
Deine Idee mit der Positionierung habe ich umgesetzt - es klappt tadellos - super!

Code: Select all

.
.
.
  maximaleBreite := 300 ; Maximale Breite der GUI (muss händisch angepasst werden)
  marginX        := 10 ; Horizontaler Rand
  breite         := maximaleBreite - 2 * marginX ; breite = maximaleBreite - zweimal marginX für den rechten und den linken Rand -> 280
.
.
.
    Gui, Add, Text, BackgroundTrans x%marginX% w%breite% Center y10 w280 cWhite, %titel% ; Titel des Skripts zentriert (Text)
    Gui, Add, Text, BackgroundTrans x%marginX% w%breite% Center y170 cWhite, %fußbereich% ; Fußbereich des Skripts zentriert (Text)
.
.
.

Zu lange Texte werden nicht abgefangen, muss ich mal sehen ob ich da noch was baue.
(Notfalls mache ich die GUI etwas größer - ich werde ja eh keinen Roman darin verfassen.)

Zum Thema Klassen:
Klassen sind sicherlich eine klasse Sache, aber soweit bin ich denke ich noch nicht.
In Java hatte ich mit Klassen gearbeitet und es auch gut verstanden.
In AHK scheint es nicht sooo viel anders zu sein, aber ich will nicht zu viel auf einmal machen.

Ich hab keine Ahnung, ob es performance-technisch einen Unterschied macht, ob ich auf eine Klasse zugreife
oder ob ich einfach einen #include-Block einfüge.
Wie schon gesagt, Hauptsache keine 50 GUI-Codezeilen in den eigentlichen Skripten - die GUI soll nur Mittel zum Zweck sein.

Zu dem Problem mit dem Flackern:
Obwohl ich diesen "Eintipp-Effekt" wieder aus der Gui_Text_Ändern() entfernt habe, flackert die GUI dennoch öfters mal - aber nur die 2 Felder.
Bei einem Bildschirmvideo ist es nicht sichtbar, hab es daher mit dem Handy aufgenommen (2 extrahierte Fotos aus dem Video)
Image
Image

Danke nochmals für dein Engagement!

Grüße
Please use [code][/code] when posting code!
Keyboard: Logitech G PRO - Mouse: Logitech G502 LS - OS: Windows 10 Pro 64 Bit - AHK version: 1.1.33.09
just me
Posts: 9423
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Einige Probleme mit GUIs

05 Jan 2019, 11:33

Hi,

ich habe gerade gesehen, dass mein letzter Beitrag ein Recht/Links-Problem hat. ;)

Zum Thema Flackern:
Das ist bei AHK recht normal, wenn man relativ dunkle Hintergrundbilder oder Farben verwendet. Irgendwann erwischt die Bildschirmdarstellung dann von Zeit zu Zeit einen Zustand, in dem der normale und an sich helle Hintergrund durchschlägt. Zuverlässig verhindern lässt sich das nur, wenn man das Neuzeichnen kontrolliert, d.h. die Einzelaktionen zu unpassenden Zeitpunkten verhindert.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 36 guests