PBToolboxAI v1 ← Site

3. Gemeinsame Basis u_pbt_base #

← Erste Schritte · Inhalt · Designs →


Alle visuellen Komponenten erben von u_pbt_base, das den Lebenszyklus, die Eigenschaften-Engine, den Transport zur Web-Komponente und die Fehlerbehandlung bereitstellt. Die Eigenschaften selbst — einschließlich Design und Tooltips — werden von jeder Komponente veröffentlicht: die Seite der Komponente führt sie vollständig auf. Sie verwenden u_pbt_base nie direkt — Sie setzen eine konkrete Komponente ein —, aber alles Folgende steht Ihnen überall zur Verfügung.


3.1 Die Eigenschaften-Engine #

Zuweisen #

Jeder steuerbare Wert ist eine öffentliche Instanzvariable und wird direkt zugewiesen:

uo_progress.id_value   = 42.5
uo_progress.is_label   = "Import läuft…"
uo_progress.ib_animated = true

Das ungarische Präfix gibt den Typ an: is_ string, ib_ boolean, ii_ integer, il_ long (häufig eine RGB()-Farbe), id_ double.

Ein skalares of_set_xxx gibt es nicht: Eine Eigenschaft wird per Zuweisung gesetzt. Methoden bleiben für Hinzufügen, Entfernen und Aktionen (of_add_*, of_remove_*, of_select_*, of_reset, of_set_layout…).

Zurücklesen #

Das Lesen liefert den zuletzt gesetzten Wert (Cache auf der PowerBuilder-Seite):

if uo_progress.id_value >= 100 then …

Eine Web-Komponente lässt sich nicht synchron abfragen: Dieser Cache wird daher von den Events aufgefrischt. Immer wenn die Komponente eine Eigenschaft selbst verändert — der Benutzer folgt einem Link, zoomt mit dem Rad, klappt das Ribbon ein, tippt Text — aktualisiert das Event, das Sie benachrichtigt, die Eigenschaft gleich mit. Das Zurücklesen liefert dann den tatsächlichen Zustand, und der neue Wert steht bereits, wenn Ihr Event-Code läuft.

Dasselbe gilt für Items: Nach einem Klick des Benutzers liefert of_item(...) den Zustand, der auf dem Bildschirm steht — der ausgewählte Eintrag, der eingeklappte Abschnitt, die angehakte Schaltfläche.

Eine Eigenschaft, zu der es kein Event gibt, bleibt dagegen auf dem zuletzt von Ihnen gesetzten Wert.

Änderungen bündeln #

Eine Folge von Zuweisungen löst ebenso viele Renderings aus. of_set_redraw fasst sie zu einem einzigen zusammen:

uo_grid.of_set_redraw(false)
… zwanzig Zuweisungen und of_add_* …
uo_grid.of_set_redraw(true)     // EIN einziges Neuzeichnen

Rufen Sie stets beide auf (das abschließende true ist nicht optional).


3.2 Die Items #

Eine Komponente mit Inhalt (Registerkarten, Schaltflächen, Panels, Kacheln, Abschnitte…) stellt ihre Elemente über typisierte Handles bereit, die von der Komponente selbst oder von ihrem übergeordneten Element stammen.

Hinzufügen #

Das Hinzufügen liefert das Handle des erzeugten Elements zurück:

n_pbt_tab_page lnv_page

uo_tab.of_add_page("clients", "Kunden", uo_page_clients)
lnv_page = uo_tab.of_item("clients")
lnv_page.is_icon = "img\clients.png"

Abrufen und ändern #

of_item(id) — oder die Factory der betreffenden Ebene — liefert das Handle eines vorhandenen Elements; seine Eigenschaften werden genau wie die einer Komponente gesetzt:

uo_toolbar.of_bar("main").of_item("save").ib_enabled = false
uo_tab.of_item("clients").is_title = "Kunden (128)"

Hierarchien: Ein Bezeichner ist nur innerhalb seines übergeordneten Elements eindeutig #

Eine mehrstufige Komponente bietet keine Abkürzung bis zum Blatt: Der vollständige Pfad ist Pflicht, wodurch garantiert ist, dass kein Bezeichner mehrdeutig ist.

// Menueband: Registerkarte > Gruppe > Steuerelement > Menueeintrag
uo_ribbon.of_tab("home").of_group("clipboard").of_item("paste").ib_enabled = false

Auch die Events tragen den vollständigen Pfad:

// Event ue_clicked von uo_toolbar: (string as_bar, string as_id)
choose case as_bar + "/" + as_id
    case "main/save" ; of_enregistrer()
end choose

Item-Events #

Auf dem Vorfahren gibt es keine generischen Item-Events: ein Blatt-Bezeichner allein wäre mehrdeutig, sobald Items verschachtelt sind (eine Toolbar hat mehrere Leisten, eine Tilesbox mehrere Gruppen…). Jede Komponente deklariert daher ihre eigenen Item-Events mit dem vollständigen Pfad: ue_item_selected (as_section, as_id) für die Listbar, ue_tile_clicked (as_group, as_id) für die Tilesbox, ue_clicked (as_bar, as_id) für die Toolbar…

Siehe die Seite der jeweiligen Komponente: dort steht die genaue Liste.


3.3 Events, die allen Komponenten gemeinsam sind #

EventAusgelöst wenn
ue_ready ( )Die Komponente ist fertig geladen; alles zuvor Gesendete wurde nachgespielt
ue_runtime_missing ( )Die WebView2-Runtime fehlt — siehe Installation
ue_bg_color (long al_color)Die Komponente hat ihre Design-Hintergrundfarbe berechnet; das Userobject hat diese Farbe bereits übernommen (backcolor), Sie passen bei Bedarf das Fenster an

Befehle, die vor ue_ready gesendet werden, gehen nicht verloren: Sie werden in eine Warteschlange gestellt und der Reihe nach nachgespielt. Sie können also bereits im constructor oder im open alles konfigurieren.

// Event ue_bg_color: das Fenster an den Hintergrund der Komponente anpassen
parent.backcolor = al_color

3.4 Optionale Eigenschaften und Events (Opt-in) #

Manche Funktionen sind nicht standardmäßig aktiviert: Sie werden nur von den Komponenten veröffentlicht, bei denen sie sinnvoll sind, und Sie müssen sie anfordern.

Automatische Höhe — ib_auto_height #

Die Komponente misst ihre ideale Höhe und ändert die Größe des Userobjects; das Event ue_auto_height(al_height) erlaubt Ihnen, die benachbarten Steuerelemente neu zu positionieren.

uo_entete.ib_auto_height = true
// Event ue_auto_height von uo_entete
il_hauteur_entete = al_height
of_relayout()          // positioniert den darunter liegenden Inhalt neu

Veröffentlicht von: picture und statictext.

Die Bänder veröffentlichen diese Eigenschaft nicht — ihre Höhe ist intrinsisch. ribbon und toolbar scrollen nicht vertikal: Eine fest vorgegebene Höhe kann nur Leerraum unter dem Band oder abgeschnittenen Inhalt erzeugen (eingeklapptes Menüband, auf zwei Zeilen umgebrochene Symbolleiste …). Sie passen sich deshalb immer an, ohne dass etwas zu aktivieren wäre, und lösen trotzdem ue_auto_height aus, damit Sie neu positionieren können, was darunter liegt.

Automatische Breite — ib_auto_width #

Dasselbe Prinzip für die Breite. Wird ausschließlich von listbar veröffentlicht, der einzigen Komponente, deren natürliche Breite eine Bedeutung hat.

Eine zur Symbolleiste eingeklappte listbar schrumpft von selbst und gibt die Breite beim Ausklappen wieder frei: ib_auto_width nützt Ihnen nur dann, wenn Sie auch der ausgeklappten Breite folgen wollen (die Leiste richtet sich dann nach der längsten Beschriftung).

Umgebende Maus-Events — ib_track_mouse #

Maus-Events mit hoher Frequenz werden an der Quelle abgeschnitten: Ohne Abonnement gibt die Komponente sie gar nicht aus (nichts überquert die Brücke zu PowerBuilder).

uo_bouton.ib_track_mouse = true    // aktiviert ue_mouse_enter / ue_mouse_leave / ue_rclicked

Veröffentlicht von: button, picture, statictext.

Diskrete Events (Klick, Auswahl, Menü, Drop…) werden immer ausgegeben, ohne Abonnement.


3.5 Tastenkombinationen #

Eine Tastenkombination löst eine Komponente aus, gleichgültig wo der Fokus im Fenster liegt — der Anwender muss nicht erst zum Button zurückkehren, um ihn zu betätigen. Jede visuelle Komponente nimmt sie entgegen, ohne dass etwas aktiviert werden müsste.

uo_enregistrer.of_register_shortcut("Ctrl+S")
uo_actualiser.of_register_shortcut("F5")

Eine Tastenkombination schreiben #

Die Kombination ist eine freie Zeichenkette, die von der Bibliothek normalisiert wird: Groß- und Kleinschreibung, Leerzeichen und die Reihenfolge der Modifikatoren spielen keine Rolle. "Ctrl+Shift+S", "ctrl + shift + s" und "SHIFT+CTRL+S" bezeichnen dieselbe Tastenkombination — es ist unmöglich, versehentlich zwei Varianten zu registrieren.

ElementZulässige Schreibweisen
ModifikatorenCtrl (oder Control), Alt, Shift — kombinierbar, in beliebiger Reihenfolge
Tasteein Buchstabe AZ, eine Ziffer 09, F1F24, Enter (oder Return), Escape (oder Esc), Delete (oder Del), Insert, Home, End, PageUp, PageDown

Diese Liste ist abschließend: Eine nicht aufgeführte Taste (Tab, Leertaste, eine Taste des Ziffernblocks, ein Satzzeichen) löst keine Tastenkombination aus.

Eine einzelne Taste ist eine gültige Kombination ("F5"). Eine leere Zeichenkette entfernt die Tastenkombination von der Komponente.

"Enter" und "Escape" lassen sich allein nicht als Tastenkombination registrieren: Diese beiden Tasten bleiben dem Standard-Button und dem Abbrechen-Button vorbehalten (ib_default / ib_cancel des button). In Verbindung mit einem Modifikator werden sie wieder zu gewöhnlichen Kombinationen ("Ctrl+Enter").

Wer bei einem Konflikt gewinnt #

Zwei Komponenten dürfen dieselbe Kombination anfordern — das kommt häufig vor, wenn ein Fenster mehrere Bereiche beherbergt, die jeweils ihr eigenes „Speichern“ haben. Die Entscheidung fällt in dieser Reihenfolge:

  1. die Komponente mit dem Tastaturfokus setzt sich gegen alle anderen durch: Die Tastenkombination eines aktiven Bereichs wird niemals von einem Nachbarn verdeckt;
  2. andernfalls gewinnt die zuerst registrierte.

Es treten nur die sichtbaren und aktiven Komponenten des Fensters im Vordergrund an. Wird eine Kombination auf einer Komponente erneut registriert, die bereits eine hatte, so ersetzt sie diese, ohne deren Rang zu ändern: Ein Fenster neu zu konfigurieren mischt die Prioritäten nicht neu.

Tastenkombinationen für Items #

Die Überladung mit zwei Argumenten bindet die Kombination an ein Item der Komponente statt an die gesamte Komponente — das zweite Argument ist der Bezeichner des Items:

uo_barre.of_register_shortcut(/*Kombination*/ "Ctrl+N", /*Item*/ "nouveau")
uo_barre.of_register_shortcut(/*Kombination*/ "Ctrl+P", /*Item*/ "imprimer")

Tastenkombinationen entfernen #

uo_barre.of_clear_shortcuts()      // Komponente UND Items

of_reset() und das Zerstören der Komponente rufen of_clear_shortcuts() für Sie auf: Eine verschwundene Komponente behält niemals eine Kombination reserviert.

Die Alt-Taste #

Alt allein wird nicht abgefangen: Sie gibt den Fokus an das Menüband, das daraufhin seine Keytips einblendet (siehe ribbon). Die Bibliothek fängt die nachfolgenden Tastenanschläge also nicht ab — das Menüband liest sie, so als hätte der Anwender es angeklickt. Esc oder ein zweites Alt geben den Fokus an das verlassene Steuerelement zurück. Deklariert kein Menüband des Fensters einen Keytip, behält Alt sein gewohntes Windows-Verhalten.

ElementWirkung
of_register_shortcut (string as_chord)Deklariert eine Tastenkombination für die Komponente; eine leere Zeichenkette entfernt sie
of_register_shortcut (string as_chord, string as_key)Deklariert eine Tastenkombination für ein Item, bezeichnet durch seinen Bezeichner
of_clear_shortcuts ( )Entfernt alle Tastenkombinationen der Komponente, einschließlich der Items

3.6 Eine Komponente zurücksetzen: of_reset() #

of_reset() versetzt die Komponente in ihren Neuzustand zurück, so als wäre sie gerade geladen worden:

uo_grid.of_reset()          // mit einem leeren Raster neu beginnen
// ... und dann neu aufbauen

⚠️ Wenn Sie eine Instanz für etwas anderes wiederverwenden, ohne of_reset() aufzurufen, bleibt der vorherige Zustand erhalten (eine Farbe, ein Modus, eine automatische Höhe). Das ist die häufigste Ursache für einen unerklärlichen „Anzeigerest“.


3.7 Diagnose #

ElementWirkung
of_is_created ( ) → booleanDie native Komponente existiert (Runtime vorhanden, Host gültig)
of_is_ready ( ) → booleanDer Web-Inhalt ist geladen (ue_ready bereits ausgelöst)
of_get_last_error ( ) → stringLetzte ausführliche Fehlermeldung der DLL, nach einem Rückgabewert < 0

Rückgabecodes der of_*-Methoden:

RückgabeBedeutung
≥ 0OK (angewendet oder in die Warteschlange gestellt)
-2Komponente nicht erstellt (Runtime fehlt, Host ungültig)
-4Vorgang fehlgeschlagen (Bildschirmfoto, Schreiben einer Datei…)
-5Ungültiges Argument (leerer Bezeichner, Wert außerhalb des Bereichs)
-6WebView2-Runtime zu alt für die angeforderte Funktion (Drucken)

3.8 Die Darstellung als Bild exportieren #

Jede Komponente kann sich als Bild exportieren, genau so, wie sie angezeigt wird:

uo_pivot.of_save_as_png("C:\temp\tableau.png")
uo_pivot.of_save_as_jpg("C:\temp\tableau.jpg")

Zum Drucken statt zum Exportieren siehe Drucken.

Praktisch für einen Bericht, einen E-Mail-Anhang oder einen Störungsnachweis. Die Komponente muss erstellt und ihr Inhalt geladen sein.


3.9 Lebenszyklus #

  1. Erstellung: Die WebView wird bereits bei der Konstruktion des Userobjects erzeugt — unerlässlich für das Hosting (Registerkarten, andockbare Panels): Eine WebView, die nach dem Umhängen ihres HWND erzeugt wird, wird nicht angezeigt.
  2. Warteschlange: Ihre Befehle werden in eine Warteschlange gestellt, solange ue_ready nicht ausgelöst wurde.
  3. Bereit: ue_ready; die Warteschlange wird der Reihe nach nachgespielt.
  4. Größenänderung: automatisch, die Komponente folgt der Größe des Userobjects.
  5. Zerstörung: beim Schließen des Fensters; die WebView wird freigegeben, kein verwaister Prozess bleibt zurück.

Rufen Sie PBT_Warmup() einmal beim Start der Anwendung auf, damit dieser Zyklus unbemerkt bleibt (Installation).


3.10 Best Practices #


← Erste Schritte · Inhalt · Designs →