[UIBB.au3] User Interface mit automatischer Anordnung der Ctrls - Vorschläge / Wünsche / Ideen

  • Moin,

    Habe gemerkt, dass scheinbar etwas interesse daran besteht eine UDF zu haben die das GUI Erstellen (vorallem für Skalierbare Fenster) etwas vereinfacht. Ein großes Problem ist üblicherweise, dass man unmengen hardgecodete Zahlen braucht und mit GUICtrlSetResizing irgendwie nicht das hinbekommt was man gerne hätte.

    Da ich nur eine einzige Person bin unterliege ich dem "Funktioniert schon, weil es für mich funktioniert" Bias. Daher bitte ich darum, dass ein paar Leute einfach zum Spaß ein kleines UI mit dieser UDF bauen um Fehler zu finden / Vorschläge zu machen / Wünsche zu äußern / etc.

    Im Anhang ist eine sehr "dahingetackerte" Version der UDF, die aber schon für einige Anwendungen funktioniert. Ich möchte die aber erst "in Form bringen", wenn sich sicher bin, dass die UDF keine gravierenden Designschwächen mehr hat (dann muss man nämlich einiges Umschreiben was unnötige Arbeit ist und grundsätzlich unmengen Bugs erzeugt).

    Funktionsweise:

    - Ein GUI hat eine ClientArea (via user32::GetClientRect abrufbar). Diese entspricht der "Root" Box.

    - Eine Box kann entweder Horizontal (HBOX), Vertikal (VBOX), oder "Egal" (EMPTY) sein

    - Boxen und GuiCtrlXXX können in Boxen gelegt werden. Sie werden dann automatisch skaliert um die umgebende Box auszufüllen.

    Es gibt schon ein paar Feintuningmöglichkeiten:

    - _UIBB_Insert($PARENT, $CHILD, $nScale) ermöglicht es die "default" Skalierung von Boxen und Ctrls einzustellen.

    - _UIBB_SetSize($ANY, $nPxSize) setzt die Pixelgröße einer Box relativ zum Parent. Parent = HBOX -> $nPxSize = Breite, Parent = VBOX -> $nPxSize = Höhe

    - _UIBB_SetPadding($ANY, $left, $right, $top, $bot) setzt den INNEREN Rand einer Box in Pixeln

    - Genaue Anleitungen wie man was macht gibt es nicht, dazu muss man die Beispiele ansehen.

    Hinweise:

    - Alle Größenangaben die man setzt sind nur ein "Vorschlag". Sie werden nicht zwingend eingehalten (z.B. wenn man ein 100px breites Feld mit 3 Ctrls mit je 50px breite befüllt. Dann werden die logischerweise etwas gestaucht).

    - Tabs und Groups sind "nonblocking" da sie keinen Platz verbrauchen. Sie erhalten Implizites Padding, sodass der Innenraum automatisch passt.

    - Es gibt keine DPI unterstützung, ich habe nur auf Win10 getestet, Es gibt keine Schriftgrößenskalierung, etc.

    Wenn die UDF fertig ist gibts dazu nen eigenen Thread in "Skripte", erstmal geht es aber darum die Idee überhaupt in Form zu bringen, und das kann ich nicht alleine. Fehler, Wünsche und Ideen von anderen sind wichtig, damit nicht "nur ich" mit dem Ergebnis zufrieden bin, sondern jeder der es potentiell verwendet. (gesucht sind also quasi "Feature Requests")



    Known Issues:

    - [TODO] Wenn man das Fenster extrem verkleinert verschwinden einige Ctrls (z.B. TABs). Danach ist das Fenster nicht mehr ansprechbar (vermutlich Messageloop unterbrochen, da Ctrl "kaputt"). Needs investigation, vielleicht ein AutoIt Problem, vielleicht ein UDF problem.

    - [TODO] Größe von Boxen/Ctrls werden Iterativ angeglichen, das ist ziemlich langsam und ungenau. Das muss überarbeitet werden.

    - [TODO] Tabs "ordentlich" in die UDF integrieren.

    Requests:

    - [DONE] Mindestgröße für das Komplette Fenster vorgeben (z.B. 600x400 px. Macht man das Fenster kleiner wird nicht mehr Skaliert. Die Ctrls werden dann "aus dem Fenster herausgeschoben", aber nicht mehr verkleinert. (Moombas #2)

    - [HOLD] Dynamisches UI (man kann zur Laufzeit z.B. eine Elementbreite etc. einstellen damit sich das UI dynamisch verhalten kann) -> Problem: AutoIt hat keine Pointer und das UI ist komplett in einer Baumstruktur (verschachtelte Maps) untergebracht. Ein Direktzugriff auf ein spezielles Element ist nur mit extremem Overhead möglich, daher [On Hold] bis mir dazu etwas einfällt... (Mars)

    Changelog:

    - Mindestgröße für komplettes Fenster wird durch die Parameterreihenfolge in _UIBB_Box($UIBB_HBOX, 500, 300, $hGUI) zwingend erforderlich wenn man die UDF nutzen will. Damit wird verhindert, dass sich jemand keine Gedanken darüber macht.

    - Mindestgröße für Boxen ist diekt in _UIBB_Box($UIBB_VBOX, 120) integriert. Kein redundantes "setSize" mehr nötig. Da Boxen (außer der Root-Box) nur eine Dimension haben (Breite oder Höhe) ist _UIBB_Box($UIBB_VBOX, 120, 200) stellvertretend für 120 = MindestWert & 200 = Maximalwert)

    lg

    M

  • Zitat

    Hinweise:

    - Alle Größenangaben die man setzt sind nur ein "Vorschlag". Sie werden nicht zwingend eingehalten (z.B. wenn man ein 100px breites Feld mit 3 Ctrls mit je 50px breite befüllt. Dann werden die logischerweise etwas gestaucht).

    Hmm, wäre dann nicht evtl. besser das diese im "nicht sichtbaren Bereich" der Box landen. Also Diese Werte als min. Wert angesehen werden?

    Wenn der Programmierer sich das dann anschaut wird er merken, das da was nicht passt (3*50 kann nicht in 100 passen) und muss es halt anpassen. Ich kenne das zumindest so von Lazarus / Delphi, wobei man dort ggf. noch das Problem hat, das diese dann beim Vergrößern des Fensters trotzdem mit skalieren und im "unsichtbaren" Bereich bleiben (unschön), was ggf. zu Problemen führen kann um über haupt die entspr. Elemente zu packen zu bekommen.

    Alternativ: sowas führt dazu, das das Parent vergrößert wird (müsste dann rekursiv passieren falls notwendig).

    Alternative 2: Eine Fehlermeldung (Consolewrite/MsgBox) generieren, wenn x+breite oder y+höhe größer sind als die Höhe bzw. Breite des Parents und das Programm geschlossen wird?

  • Schaltflächen nicht in Schleife erstellen, weil sie sonst nicht nutzbar sind.

    Das musst du mir mal erklären?

    Mache ich regelmäßig (wenn der Name egal ist und die X,Y,W,H Werte errechnet werden können), dann wird ein Array genutzt um die Handles abzulegen und damit sind die Buttons einwandfrei nutzbar.

  • Das Handle ist aber im Beispiel nicht drin.

    BTW:

    Die Schaltflächen sollten sich in der Größe anpassen. Bei mir bleiben sie in der Größe gleich, auch wenn ich die GUI auf 1700x1000 setze.

  • Ok, dann hättest du diene Antwort anders formulieren müssen.

    Ja, anstatt

    AutoIt
    For $i = 0 to 12 Step 1
        $btn = _UIBB_Insert($hLeftTop, GUICtrlCreateButton)
        GUICtrlSetData($btn, 'Button Nummer ' & $i)
        GUICtrlSetBkColor($btn, Random(0, 0xFFFFFF)) ; _UIBB_Insert gibt die original Ctrl-IDs zurück mit denen man alles wie üblich machen kann.
    Next

    müsste dort dann eben der Arrayverweis rein:

    AutoIt
    #include <Array.au3>
    ;...
    Global $aBtn[], $btn
    ;...
    For $i = 0 to 12 Step 1
        $btn = _UIBB_Insert($hLeftTop, GUICtrlCreateButton)
        _ArrayAdd($aBtn, $btn)
        GUICtrlSetData($btn, 'Button Nummer ' & $i)
        GUICtrlSetBkColor($btn, Random(0, 0xFFFFFF)) ; _UIBB_Insert gibt die original Ctrl-IDs zurück mit denen man alles wie üblich machen kann.
    Next

    Zugriff auf die Buttons wäre dann über $aBtn[X] möglich.

    Wegen der GUI Größe Anhand der Auflösung, müsste man 2 Sachen machen:

    1. Eine default Auflösung (z.B. 1024*768) (Ohne Angabe einer Default Auflösung = Multiplikator immer * 1)

    2. Darauf aufbauend dann die aktuelle Auflösung auslesen und sämtliche Größen mit dem entsprechendem Faktor multiplizieren.

    Wobei dabei das ganze mit Vorsicht zu genießen ist, da ggf. das Seitenverhältnis leidet, sprich eigentlich muss man den kleineren der beiden Multiplikatoren nehmen.

    Beispiel:

    Default: 1024 * 768

    Du hast: 1700 * 1000

    Multiplikatoren: 1,66 * 1,30 => finaler Multiplikator muss dann 1,3 sein damit das Seitenverhältnis der GUI bestehen bleibt und du keine Verzerrungen produzierst.

    Und das Gleiche müsste man dann für DPI skalierung etc. machen aber das übersteigt meine Kenntnisse :Glaskugel:

    Oder habe ich da gerade einen Denkfehler? :/

  • Kann man machen, wird aber nicht immer benötigt und kann alleine für die GUI Erstellung echt zu einem Monstercode werden.

    Ich habe mir das so angewöhnt, das der "sprechende Name" das Array selber ist ($aFileButtons) ich aber durch die erstellte Reihenfolge etc. trotzdem weiß welcher was ist und habe einen viel übersichtlicheren Code.

    Je nach GUI dann natürlich auch mehrere solcher Arrays. Aber im Ernst: Es ist der Beispielcode, wie man das final selber umsetzt muss jeder selber wissen, es geht hier um das dynamische Verhalten der GUI beim Verändern der Fenstergröße und das funktioniert doch super soweit ich sehe. Mit fehlt halt nur der "min. Wert".

  • Also bei mir funktionieren die Schaltflächen nicht..

    Code
    Global $btFileExit = _UIBB_Insert($hMidPadded, GUICtrlCreateTab)
    GUICtrlSetData(-1, 'Roter Button')
    Code
    While True
            $aMsg = GUIGetMsg(1)
            Switch $aMsg[0]
                  ; Programm beenden
                  Case $btFileExit
                       Exit
        EndSwitch
    WEnd
  • Aaaaah, jetzt verstehe ich das erst :D

    Dazu musst du bei der GUI Erstellung die ensprechenden Flags setzen:

    AutoIt
    Global $hGUI = GUICreate('test', 800, 800, -1, -1, 0x00040000 + 0x00020000 + 0x00010000) ; Resizable GUI

    (In der Hilfe findet man alles: https://www.autoitscript.com/autoit3/docs/a…x/GUIStyles.htm)

    lg

    M

  • Danke! Ich hab es zuerst mit BitOR($GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_TABSTOP) (Koda Code) probiert. Funktioniert aber nicht wen ich 0x00040000 stehen lasse.

  • Für "einzelne" Flags ist BitOr und "+" das Selbe, da hier immer nur ein einziges Bit gesetzt ist. Für Kombinierte Flags ist das nicht mehr gegeben.

    (nur zur Info, falls dich das verwirrt. Beide Schreibweisen können richtig sein, sofern man weiß was man tut)

    Beispiel (binär):

    0001 + 0100 = 0101 ist gleichbedeutend mit BitOr(0001, 0100) = 0101

    0101 + 0100 = 1001 ist NICHT gleichbedeutend mit BitOr(0101, 0100) = 0101

    Im ersten Fall ist jeweils nur 1 Bit gesetzt -> BitOr und "+" sind identisch.

    Im zweiten Fall sind mehrere Bits gesetzt -> BitOr ist die einzige richtige Lösung.

    lg

    M

  • Ich meine das Viereck zwischen Schließkreuz und "Minimieren". Das muss ja aktiv sein, damit man das Verhalten testen kann.

    Nein das Verhalten kann man schon testen, in den man am Rand die Fenstergröße ändert und das Verhalten sich anschaut. Ein maximiertes Fenster (Viereck = Maximieren) wird halt nur autom. auf die maximal möglichen Werte gesetzt, macht aber im Prinzip nichts anderes.

    Den Rest hat Mars bereits erklärt.

    (Folgendes ist nicht böse gemeint) Bitte überlege mal wenn du sowas schreibst ob andere verstehen können was du möchtest bevor du es abschickst, das macht es einfacher die korrekte Antwort zu geben ohne immer wieder Nachfragen zu müssen.

  • Mars 8. April 2024 um 19:14

    Hat das Label [ gelöst ] hinzugefügt.