GUI mit benutzerdefinierter Titelleiste

  • Hi zusammen 👋 ,

    hier nur ganz kurz vorgestellt, ein kleines Skript welches eine GUI darstellt, die eine benutzerdefinierte Titelleiste hat. Ich bin mir sicher das es da bereits etliche Varianten gibt, wie Metro GUI usw., trotzdem wollte ich es einfach mal geteilt haben. Vielleicht hilft es den einen oder anderen (vielleicht auch nur als Ideengeber für andere Projekte oder so).

    💡 Warum? Den Hintergrund der Titelleiste und die Schriftfarbe der Titelleiste zu ändern, ist gar nicht so trivial. Daher hier ein Weg eine eigene Titelleiste stattdessen zu nutzen.

    Gut zu wissen:

    • man kann das Fenster ganz normal mittels der Titelleiste ziehen
    • man kann den Minimize- und den Schließen-Button ganz normal benutzen
      • klingt trivialer als es ist 😅
    So sieht das bspw. dann aus

    Vielleicht kann es ja mal jemand gebrauchen 🤞 .

    Viele Grüße
    Sven

  • Hi,

    das schaut doch schon recht gut aus :)

    Ich hab das gleiche vor kurzem in JavaFX gemacht um bei nem Fenster Darktheme zu unterstützen.

    Deshalb hab ich ein paar Verbesserungsvorschläge für dich :)

    Erstmal ein Fehler (vmtl. vom posten des Codes):

    1. Bei mir haben der Schließen (Í) und Maximieren-button (£) ein falsches Symbol (auch hier auf der Webseite; keine Ahnung, wo es falsch konvertiert wurde). Ich würde empfehlen mit ChrW die UTF-codes direkt zu nutzen, dann kann sowas nicht passieren. Für mein Tool hab ich z.B. minimize: ChrW(0x2015), maximize: ChrW(0x2610) und close: ChrW(0x2715)

    Verbesserung:

    1. Doppelkick auf die Titleleiste maximiert/entmaximiert ein Fenster, sollte recht leicht zu implementieren sein.

    2. Eigenes resize implementieren; relativ einfach, aber aufwändiger.

    3. AeroSnap: Wenn man ein Fenster an den Bildschirmrand zieht, füllt es je nach Rand einen Bereich. Linker Rand: linke hälfte, Ecke links oben/unten jeweiles die obere/untere linke Hälfte und das gleiche auch Rechts. Der obere Rand maximiert.

    Dafür muss man aber die Maus fangen und verhindern, dass sie auf andere Bildschirme an dem Rand übergeht, wenn man die Maus nicht zu schnell über die Kante bewegt. Außerdem zeigt Windows mittlerweile die Option, die andere freie Hälfte mit nem anderen Tool zu füllen,...

    Leider gibt es keine API dafür, sodass es nicht möglich ist das ganze exakt umzusetzen, aber zumindest die eigene Fenstergröße kann man anpassen. Auch wenn es nicht ganz so einfach ist.

    ?4. Vor kurzem hab ich mitbekommen, dass es mittlerweile in Windows auch FancyPages gibt; So ähnlich wie AeroSnap, nur mit mehr möglichkeiten, ABER auch wieder ohne API... X(

    Das standard Verhalten von GUIs nachzubauen ist also leider ziemlich schwer... (insbesondere, wenn man wie ich mit JavaFX auch Linux/Mac unterstützen will).

    Es ist leider ziemlich nervig, dass sobald man die Standard Titlebar wegnimmt (Window style undecorated), fast alle Funktionalität für ein normales Fenster mit verschwindet... Vor allem, weil auch die Standard Testenkombinationen mit wegfallen. Win+Left funktioniert z.B. nicht mehr um ein Fenster auf die linke Bildschirmhälfte zu packen (AeroSnap),... Das alles nachzubauen ist echt nervig. :/

  • Mir sind ein paar Kleinigkeiten aufgefallen die ich vermutlich irgendwo eingebaut hätte:

    - Kleiner Hinweis wie du die Events nicht andauernd via Adlib durchlaufen musst: Verwende GUIOnEventMode und registriere dir GUI_EVENT_MOUSEMOVE. Dann wird die Funktion nur aufgerufen, wenn die Maus bewegt wird. Dadurch wird dein Programm nebenbei auch sehr viel reaktiver, weil nicht "alle 100ms" geprüft wird, sondern "sobald sich die Maus einen Pixel bewegt". Gleichzeitig wird keine Rechenleistung verbraucht wenn die Maus stillsteht.

    - Noch eine Idee wäre WM_NCHITTEST & Return $HTCAPTION (klappt nur, wenn die Maus "nicht" über einem Ctrl mit einem eigenen Handle ist, z.B. für GDI+ Stuff). Damit kann man ein Fenster bewegen, wenn man auf den Hintergrund des Fensters (und nicht auf ein Ctrl) klickt. Bin gerade nicht sicher ob, und wie das sinnvoll ist, aber vielleicht bringt die die Info ja etwas :) (PS: NCHITTEST feuert 1x pro Frame, also alle 16.6ms. Wenn man es nicht braucht sollte man es also vllt doch lieber weglassen^^)

    - GUIGetCursorInfo trägt bereits informationen zum Ctrl in [4], da braucht man nicht mehr umständlich via Positionen zu berechnen wo die Maus ist.

    - Bei Ctrls Farben zu aktualisieren tendiert zu flackern (auch wenn man es hier jetzt nicht wirklich sieht). Versuche die aktuellen Daten (Farbe, Schriftfarbe, Symbol, etc) nur dann zu aktualisieren wenn sich etwas ändert.

    Anbei ein Minimalbeispiel wie man ein Fenster bewegt und ein Ctrl umfärbt. Das Beispiel verwendet "alles" oben angesprochene, ob es sinnvoll ist UND nicht :D

    Edit: Es gibt auch noch eine Menge andere WM_XXX die man gebrauchen könnte. Am besten mal alle durchlesen (sind leider ziemlich viele^^).

    Edit2: https://www.autoitscript.com/wiki/Moving_an…zing_PopUp_GUIs <- Pflichtlektüre 8)

    lg

    M

  • Hi ihr beiden ( Kanashius, Mars) 👋 ,

    zunächst einmal Danke 😀 .

    Vielleicht kurz zur Intension:
    Das Ganze war nicht mehr als ein proof of concept (POC) und zum Spaß. Zugegebenermaßen gab es eine Frage dazu im engl. Forum, doch das spielte nicht wirklich eine Rolle.

    Nun zu euren Anmerkungen:

    Bei mir haben der Schließen (Í) und Maximieren-button (£) ein falsches Symbol (auch hier auf der Webseite; keine Ahnung, wo es falsch konvertiert wurde). Ich würde empfehlen mit ChrW die UTF-codes direkt zu nutzen, dann kann sowas nicht passieren. Für mein Tool hab ich z.B. minimize: ChrW(0x2015), maximize: ChrW(0x2610) und close: ChrW(0x2715)

    Das sind nicht die falschen Symbole sondern die, die ich aus der Zeichentabelle (Character Map) von Windows bzgl. der Schriftart Wingdings 2 entnommen habe.

    Allerdings hast du Recht, ChrW zu nutzen ist sicherlich sinnvoller und führt weniger zu Verwirrung (wie wir festgestellt haben 😅). Ich ändere das im Beitrag #1 ab.

    Verbesserung:

    1. Doppelkick auf die Titleleiste maximiert/entmaximiert ein Fenster, sollte recht leicht zu implementieren sein.

    2. Eigenes resize implementieren; relativ einfach, aber aufwändiger.

    Für dieses Beispiel out of scope, dennoch ein absolut relevanter Verbesserungsvorschlag 👍 .

    AeroSnap und FancyPages [...]

    Ebenfalls out of scope, verstehe aber deine Ausführungen absolut.

    Es ist leider ziemlich nervig, dass sobald man die Standard Titlebar wegnimmt (Window style undecorated), fast alle Funktionalität für ein normales Fenster mit verschwindet... Vor allem, weil auch die Standard Testenkombinationen mit wegfallen.

    Auch hierzu kann ich nur Beipflichten und sagen ja, nervig! Danke dir Kanashius 🤝 .


    Kleiner Hinweis wie du die Events nicht andauernd via Adlib durchlaufen musst: Verwende GUIOnEventMode und registriere dir GUI_EVENT_MOUSEMOVE. Dann wird die Funktion nur aufgerufen, wenn die Maus bewegt wird. Dadurch wird dein Programm nebenbei auch sehr viel reaktiver, weil nicht "alle 100ms" geprüft wird, sondern "sobald sich die Maus einen Pixel bewegt". Gleichzeitig wird keine Rechenleistung verbraucht wenn die Maus stillsteht.

    Sehr guter Hinweis Mars. Bisher habe ich nie mit Opt('GUIOnEventMode', 1) gearbeitet. Kenne die Variante zwar, braucht sie nur bisher nie. Auf Grund deines Beispiels sehe ich jedoch die Sinnhaftigkeit absolut gegeben, Danke 👍 .

    Noch eine Idee wäre WM_NCHITTEST & Return $HTCAPTION [...] ob, und wie das sinnvoll ist, aber vielleicht bringt die die Info ja etwas :)
    [...] (PS: NCHITTEST feuert 1x pro Frame, also alle 16.6ms. Wenn man es nicht braucht sollte man es also vllt doch lieber weglassen^^)

    Danke für den Exkurs, sehr angenehm wie du das beschreibst 🤣 .

    GUIGetCursorInfo trägt bereits informationen zum Ctrl in [4], da braucht man nicht mehr umständlich via Positionen zu berechnen wo die Maus ist.

    Sehr guter Hinweis, hätte ich eigentlich selbst wissen müssen/sollen 🤔 . Versuche es zeitnah in den Code einzupflegen (oben zu aktualisieren).

    Bei Ctrls Farben zu aktualisieren tendiert zu flackern (auch wenn man es hier jetzt nicht wirklich sieht). Versuche die aktuellen Daten (Farbe, Schriftfarbe, Symbol, etc) nur dann zu aktualisieren wenn sich etwas ändert.

    Ja das ist mir klar. Ich denke hier war einfach der prototypische Ansatz interessanter und ausreichender, als es in den Reifegrad "produktiv" zu bringen 😅 .

    Edit: Es gibt auch noch eine Menge andere WM_XXX die man gebrauchen könnte. Am besten mal alle durchlesen (sind leider ziemlich viele^^).


    Edit2: https://www.autoitscript.com/wiki/Moving_an…zing_PopUp_GUIs <- Pflichtlektüre 8)

    Auf Grund von anderer Arbeit, kann ich dir hier nichts versprechen, dass ich mir dies zu Gemüte führe (auch wenn es "Pflichtlektüre" ist 😁), trotzdem sehr guter Hinweis Mars , Danke dir 🤝 .

    Viele Grüße
    Sven