Gibt es eine "Tag"-Eigenschaft für Controls?

  • Ziel ist es, Controls eine zusätzliche Information mitzugeben, die man für alle Controls einheitlich setzen und auslesen kann. Die Information soll verschiedenen Zwecken dienen, z. B. um bestimmte Controls zu taggen (markieren). Man könnte dann in einer Schleife alle Controls einer GUI durchlaufen und für die getaggten Controls z. B. eine andere Farbe setzen.

    Zu diesem Zweck gibt es in verschiedene Programmiersprachen (z. B. VB/VBA) eine "Tag"-Eigenschaft für jedes Control. Gibt es sowas auch für AutoIt oder kann man es einfach (ohne großen Aufwand) "nachbauen"?

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Im Prinzip kann man bei jedem Fenster (die Control-Elemente sind auch Fenster) mit "_WinAPI_SetWindowLong" den Wert von "$GWL_USERDATA" verändern.

    Das Problem bei AutoIt ist bloß, dass dort die Control-ID abgespeichert ist und ich weiß nicht, wie AutoIt reagiert, wenn man dort andere Sachen speichert.

    Aber warum willst Du die zusätzlichen Marker nicht in einem Array (oder Dictionary) speichern?

  • SetWindowLong/SubClassing assoziiere ich mit Macht, im Sinne einer mächtigen Funktion und mit großer Macht kommt große Verantwortung. - Das ist nicht gewollt (zumindest nicht hierfür).

    Aber warum willst Du die zusätzlichen Marker nicht in einem Array (oder Dictionary) speichern?

    Ein Marker, der direkt mit dem Control verbunden ist, wäre das Coolste! 8) Um eine (lieber Musashi, wie heißt das?) Allegorie zu benutzen: Man geht in einen Diskouter und will die Preise von Waren wissen. Eine Tag-Eigenschaft fühlt sich für mich so an, wie wenn die Preise direkt an der Ware ausgeschildert sind. - Ein Array fühlt sich dagegen so an, als stünden die Preise in einem Katalog und man müsste erst für jeden Artikel den Katalog hernehmen und nachschlagen. Es geht schon, aber ist umständlich.

    Wenn es aber keine Möglichkeit gibt, User-Daten über eine Eigenschaft "fest" mit einem Control zu verbinden, sind deine Vorschläge wirklich gut! Das Array wäre hierfür nicht mein Geschmack, aber für das Dictionary könnte mich mich glatt erwärmen. Ich weiß nicht mehr, wer mich hier auf den Geschmack gebracht hat, aber Dictionaries finde ich gut! :rock:

    Falls nicht noch jemand eine bessere Möglichkeit weiß, werde ich wahrscheinlich ein Dictionary benutzen. Danke für euere Beiträge!

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Zur Zeit arbeite ich gerade an einer Lösung für "Suche einfach erweiterbaren Einstellungen-Dialog (Program Settings)". Die Betonung liegt auf "einfach" und ich finde ein 2D-Array zu handhaben nicht einfach. Je weiter das Projekt voran schreitet, desto komplexer wird es. Deshalb will ich den "Bedienteil" vom "Hintergrund-Code" trennen. Ein 2D-Array wäre in dem Fall vielleicht fehleranfällig bei der Handhabung durch dritte.

    In einem Settings-Dialog gibt es viele Controls, die auf jeder Settings-Page variieren und es gibt Haupt-Elemente, die gleich bleiben, z. B. das Main-TreeView links und die Main-Buttons "Save", "Apply" und "Cancel". Für die Main-Buttons benutze ich Labels (= Label-Buttons) ;) und einen Frame-Label, das als Highlight-Rahmen gezeigt wird, wenn der Mouse-Cursor drüber hovert. Damit nicht alle Labels den Hover-Effekt zeigen, solle sie getaggt werden. Bei lediglich 3 Label(-Button)s geht das mit einer Switch-Case Auswahl. Wenn auf den Settings-Pages weiter Label-Buttons hinzukommen und es 10 oder mehr werden, wäre die Case-Liste recht lang.

    Wie gesagt, ein Dictionay wäre mein Favorit, auch weil die Handhabung für den User gut einzurichten wäre.

    Dennoch ein guter Vorschlag von dir!

    Edit: Nachdem ich mir den Beitrag nochmal durchgelesen hatte, kam mir manches nicht so klar vor, wie es mir vorher erschien. Ich habe versucht, es besser zu formulieren.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    Einmal editiert, zuletzt von Professor Bernd (18. August 2020 um 21:58)

  • Um eine (lieber Musashi, wie heißt das?) Allegorie zu benutzen ...

    [OT] Ja, Allegorie trifft es ;) !

    Du musst die ID eines Control doch sowieso speichern. Wenn du dafür ein 2D-Array verwendest, kannst du auch problemlos zusätzliche Infos in unbegrenzter Menge ablegen.

    Sehe ich auch so !

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Wie schon gesagt, ich finde ein 2D-Array nicht so einfach zu handhaben. Zudem kommt, dass das Array bei der entsprechenden Abfrage auch aufwendiger zu handhaben ist.

    Array per Schleife

    Code
    For $i = 0 To Ubound($aCtrlIDs) - 1
      If $aCInfo[4] = $aCtrlIDs[$i][0] Then
        _ShowHoverEffekt($i)
        ExitLoop
      EndIf
    Next

    Dictionary als Einzeiler

    Code
    If $g_oDict_CtrlIDs.Exists($aCInfo[4]) Then _ShowHoverEffekt($i)

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Gerade ist mir nochwas eingefallen. Im Dictionary kann der selbe Wert nur 1x vorhanden sein (Key) - im Array kann der einundselbe Wert mehrfach aufgenommen werden und somit mehrfach vorkommen. Wie gesagt, es geht um die Dritt-Partei, den User. Das kann problemlos funktionieren, kann aber auch zu seltsamen Fehler führen, die man nicht so einfach findet.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Für das Handling schreibt man eine Managementfunktion mit Get() und Set(), ist absolut trivial. Habe ich auch schon mehrfach hier gepostet.

    Was spricht gegen das Dictionary?

    Hast du eine Link für Get/Set? Kann bestimmt noch irgendwann nützlich sein.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Was spricht gegen das Dictionary?

    Kommt auf den Anwendungsfall an. Wenn ich mich recht erinnere, gibt es beim Dictionary Probleme mit Handle. Dann kannst du nur einen Wert je Key speichern (könntest auch ein Array als Wert nehmen, aber dann lieber gleich 2D-Array).

    Für den Anwender ist es doch völlig wurscht, ob du für die Verwaltung Array, Dictionary oder Structs oder Mischformen davon oder etwas völlig anderes verwendest. Zum Zugriff erstellt man eine Funktion, die das interne Handling (neuen Wert anlegen, Wert ändern, Wert löschen oder was auch immer) vornimmt. Das ist absolut vergleichbar mit dem Speichermanagement von AutoIt. Du schreibst z. B. in einer Funktion:

    Local $Variable = 123

    und AutoIt reserviert beim Aufruf den erforderlichen Speicher und setzt den Wert. Wird die Funktion beendet, gibt AutoIt den Speicher wieder frei. Du machst aber nur die Zuweisung. Somit kann dir doch egal sein, ob das Hintergrundhandling kompliziert oder einfach ist.

  • Ich würde das ganze via Hashtable regeln.

    Ein Ctrl hat einige Eigenschaften die es mehr oder weniger eindeutig identifizieren:

    1. Ctrl-ID (Die Zahl die z.B. GuiCtrlCreateXYZ zurückgibt): kann mehrfach vergeben werden, wenn man Ctrls löscht.

    2. Handle (ein 32Bit Wert): habe kurz geschaut und es sieht so aus als würde selbst bei Neuerstellung eine um 0x10000 verschobene Adresse erzeugt werden.

    3. Ctrl-"Typ" (via GetWindowLong $GWL_WNDPROC, das ist eine vom Typ abhängige Adresse glaube ich): Ist für jeden CtrlTyp eindeutig.

    Bastel eine Hashfunktion mit Hash(ID, Handle, Typ) -> z.B. "Irgendein kurzer String" und benutze eine geeignete Liste (wie Dict, da gibt es aber noch weitere, schau dir die auch mal an) mit dem String als Key. Dann ist natürlich der Tag wieder nicht "direkt" an das Ctrl angehängt, aber man kann eine GuiCtrlGetTag/SetTag($iCtrl) Funktion schreiben, die über die ID an alles drankommt was gebraucht wird (ID, Handle, Typ) um einen eindeutigen Tag zuzuordnen.

    Allerdings müsstest du ggf. alte Tags löschen (also eine benutzerdefinierte GuiCtrlDelete-Funktion basteln), weil AutoIt-Intern soweit ich weiß keine direkte Möglichkeit besteht etwas "vor den destruktor" zu schieben, sodass das automatisch ausgeführt wird. Aber man weiß ja nie, villeicht kann man über ein paar dreckige Tricks an den Pointer kommen, diesen Umleiten (in eine eigene Proc) und von da aus wieder an den Interpreter weiterleiten. :D

    M

  • Vielleicht ein bisschen overdressed!? Es geht nur darum, aus einer Gesamtmenge an Labels einige davon als "Buttons" zu markieren.

    Im Projekt gibts Labels die als Labels benutzt werden und es gibt Labels die als Buttons benutzt werden. (Natürlich gibts in einem Settings-Dialog auch andere Controls.) Nur die Label-Buttons bekommen einen weißen Rahmen, der beim Hovern erscheint. Somit genügt es, wenn die Label-Buttons als solche erkennbar sind.

    Hover-Funktion

    Die Hover-Funktion wird in der Haupt-Schleife der GUI ständig aufgerufen. Als Erkennung dient die Switch-Case Auswertung, die oben zu sehen ist. Zur Zeit sind da schon 5 Labels drin und wenn weitere in den Settings-Pages hinzu kommen, wirds schnell voll in der Case-Zeile.

    Wie man sieht, ermittelt GUIGetCursorInfo()[4] die ID des Controls, über dem der Cursor schwebt. Im Switch-Case erfolgt ein einfacher Vergleich der ermittelten ID mit den IDs der 5 angegebenen Labels. Kein Hashwert, kein Handle wird benötigt und kein Löschen von Controls findet statt, die Control-ID ist der einzige Wert, der benötigt wird. Somit würde ein 1D-Array genügen, bzw. bei einem Dictionary würden nur die Keys belegt, die Items blieben leer. - Wie gesagt, es geht hierbei um Einfachheit.

    Das dient der Beschreibung meines Vorhabens. Über eure Vorschläge habe ich mich sehr gefreut, und sie haben mir die Möglichkeiten gezeigt, die ich verwenden kann.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Wenn du tatsächlich nur Label, die als Button verwendet werden markieren willst, kannst du diese doch in einem anderen Style erstellen und auf diesen Style prüfen.

    z.B. so:

  • Damit der User seine Labels nach seinem Geschmack einstellen kann, soll die Erkennung unabhängig von den Eigenschaften des Labels sein. Wäre doch blöd, wenn der User den Style verändert und dadurch die Hover-Erkennung nicht funktioniert. 8o

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Nur die Label-Buttons bekommen einen weißen Rahmen, der beim Hovern erscheint. Somit genügt es, wenn die Label-Buttons als solche erkennbar sind.

    So richtig habe ich dein System noch nicht verstanden. Legst du was fest oder legt der Anwender was fest?

    Irgendwoher muss ja der Rahmen kommen (den erstellt doch nicht der Anwender, sondern du?). Dann frag doch einfach ab: Label(Left.Top) - n Pixel = Position Rahmen.

  • So richtig habe ich dein System noch nicht verstanden.

    Das habe ich nicht weiter ausgeführt, weil es in diesem Thread eigentlich nur um eine Tag-Eigenschaft ging. In diesem Fall ist es für das bessere Verständnis vielleicht sinnvoll, den (Verwendungs-)Zweck zu erläutern, für das die Tag-Eigenschaft eigentlich gedacht war.

    Wie gesagt, zur Zeit arbeite ich an einer Lösung für "Suche einfach erweiterbaren Einstellungen-Dialog (Program Settings)". Es geht um ein Script, das der User als Vorlage benutzen kann, um einen Settings-Dialog einzurichten. Ich nenne das Projekt "Settings-Dialog-PB".

    Legst du was fest oder legt der Anwender was fest?

    Im Script werden verschiedene Dinge von mir festgelegt, die quasi das Grundgerüst darstellen. Zum Beispiel ein TreeView in dem man die Settings-Pages auswählen kann. Die Settings-Pages sind Child-Windows, die der User nach seinen Vorstellungen mit Controls bestücken kann. Usw. Ihr wisst ja, wie ein Settings-Dialog funktioniert.

    Der User legt vorallem die Controls in den Settings-Pages fest, bekommt aber auch Einfluss auf Dinge, die das Grundgerüst betreffen. So kann er zwischen verschiedenen Farben für die Main-GUI und die Main-Controls wählen (Schrift und Hintergrund). Auch den Hover-Effekt für Label-Buttons kann der User festlegen. Er kann z. B. wählen zwischen einem weißen, schwarzen oder gar keinem Rahmen. Er kann sich aber auch für einen ganz anderen Hover-Effekt entscheiden, z. B. beim Hovern die Hintergrundfarbe der Labels ändern.

    Zusammengefasst heißt das, die Grundeinstellungen werden von mir gesetzt und der User kann sie übernehmen oder aber ändern. Das Projekt "Settings-Dialog-PB" wird KEINE fertige Anwendung, sondern eine Vorlage, die der User an seine Vorstellungen anpassen kann.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.