PBToolboxAI v4 ← Site

4. Designs und Erscheinungsbild #

← Gemeinsame Basis · Inhalt · Sprache und RTL →


4.1 Die Designs: zwei Achsen #

Ein Design besteht aus einem Stil und einem Modus:

AchseWerte
Stil (is_theme_style)fluent · metro · office · office2007 · office2003
Modus (is_theme_mode)light · dark

Das ergibt zehn Designs mit dem Namen <style>-<mode>: fluent-light, fluent-dark, office2007-light, metro-dark…


4.2 Das Standarddesign der Anwendung (empfohlen) #

Setzen Sie das Design einmal für die gesamte Anwendung, bevor das erste Fenster geöffnet wird. Es wird in jede Komponente vor deren erstem Rendering eingespeist: kein Aufblitzen eines hellen Stils in einer dunklen Anwendung.

// Event open des Anwendungsobjekts
PBT_SetDefaultTheme("fluent-dark")
PBT_SetDefaultThemeAccent(RGB(0, 120, 212))   // optional

Ein Wechsel im laufenden Betrieb ist jederzeit möglich: Alle bereits geöffneten Komponenten erhalten sofort das neue Design.

Ein Wechsel des Standarddesigns lässt den Akzent der Anwendung unberührt: der mit PBT_SetDefaultThemeAccent gesetzte bleibt von einem Design zum nächsten erhalten, bis Sie einen anderen oder -1 setzen.

// Umschalten hell / dunkel ueber eine Schaltflaeche der Anwendung
PBT_SetDefaultTheme("fluent-light")
FunktionWirkung
PBT_SetDefaultTheme (string as_name)Standarddesign des Prozesses, an alle Komponenten verteilt; ein unbekannter Name wird abgelehnt (-5), das vorherige Design bleibt
PBT_GetDefaultTheme ( ) → stringAktuelles Standarddesign
PBT_SetDefaultThemeAccent (long al_accent)Akzent der Anwendung, dem alle Komponenten folgen — auch die mit lokalem Design, solange sie keinen eigenen haben; -1 entfernt ihn (jedes Design nimmt seinen eigenen Akzent zurück); eine PowerBuilder-Systemfarbe (über 0xFFFFFF) wird abgelehnt (-5)
PBT_GetDefaultThemeAccent ( ) → longAkzent der Anwendung, -1, wenn keiner gesetzt ist
PBT_SetDefaultFont (string as_family, long al_size_px)Schrift der ganzen Anwendung; Größe in Pixeln, 0 = die des Designs (siehe 4.4)

4.3 Das Design einer bestimmten Komponente #

Eine Komponente kann vom Design der Anwendung abweichen, Achse für Achse:

// Nur der Stil: der Modus bleibt der der Anwendung und folgt ihr
uo_editor.is_theme_style = uo_editor.THEME_STYLE_OFFICE2007

// Beide Achsen: ein vollstaendig lokales Design
uo_editor.is_theme_mode  = uo_editor.THEME_MODE_DARK
uo_editor.il_theme_accent = RGB(200, 60, 40)     // -1 = Akzent der Anwendung

// Zurueck zum Design der Anwendung: beide Achsen leer
uo_editor.is_theme_style = ""
uo_editor.is_theme_mode  = ""
EigenschaftTypStandardZweck
is_theme_stylestring""Visueller Stil (Konstanten THEME_STYLE_*). Leer = der Stil der Anwendung, bei jeder Änderung übernommen
is_theme_modestring""Helle oder dunkle Variante (Konstanten THEME_MODE_*). Leer = der Modus der Anwendung, bei jeder Änderung übernommen
il_theme_accentlong-1Akzentfarbe dieser Komponente. -1 = Akzent der Anwendung, oder der des Designs, wenn die Anwendung keinen setzt

Ein of_reset() gibt beide Achsen und den Akzent an die Anwendung zurück: die Komponente folgt wieder deren Design und Akzent.

Die beiden Achsen sind unabhängig: eine leer gelassene Achse folgt dem Design der Anwendung bei jeder seiner Änderungen, nicht nur dem, das beim Setzen der anderen Achse galt. Leerzeichen und Groß-/Kleinschreibung spielen keine Rolle; ein unbekannter Wert ("office2010", "sombre") wird ignoriert, und die Achse behält ihren Wert. Das Lesen von is_theme_style oder is_theme_mode liefert, was die Komponente anzeigt — bei einer leeren Achse Stil und Modus der Anwendung —, und il_theme_accent liefert -1, solange die Komponente keinen eigenen Akzent hat. Auch eine Komponente mit lokalem Design folgt dem Akzent der Anwendung, solange sie keinen eigenen hat.

💡 Am gepflegtesten bleibt ein einziges Design für die gesamte Anwendung. Behalten Sie das lokale Design Sonderfällen vor (einem bewusst kontrastierten Bereich, einer Designvorschau).


4.4 Eine Komponente, eine Gruppe oder ein Element umfärben #

Drei Reichweiten, dieselben Eigenschaften. Nichts zu benennen, nichts zu erraten.

// Die ganze Komponente
uo_ribbon.il_theme_accent = RGB(0, 120, 90)

// Eine Gruppe : alles darin folgt
uo_ribbon.of_group(/*keys*/ "home/clipboard").il_accent = RGB(0, 120, 90)

// Ein Element
uo_list.of_item(/*keys*/ "delete").il_text_color = RGB(200, 70, 70)
uo_list.of_item(/*keys*/ "delete").il_back_color = RGB(255, 235, 235)

// Dieselben zwei, unter dem Zeiger
uo_list.of_item(/*keys*/ "delete").il_back_color_hover = RGB(255, 220, 220)

// Zurueck zur Farbe der Komponente
uo_list.of_item(/*keys*/ "delete").il_text_color = -1
EigenschaftWoWas sie umfärbt
il_theme_accentdie Komponenteihren Akzent und alles daraus Abgeleitete: Hover- und Gedrückt-Zustand der Akzent-Schaltflächen, getönte Auswahl- und Häkchen-Zustände, den lesbaren Text darauf, den Anwendungshintergrund, die Registerkarten-Unterstreichung
il_accentein Element-, Gruppen-, Registerkarten- oder Leisten-Handlewas diese Zone mit dem Akzent malt, einschließlich ihrer Nachfahren
il_back_color · il_text_colorditoHintergrund und Text des Elements
il_back_color_hover · il_text_color_hoverditodieselben zwei, unter dem Zeiger

-1 stellt die Farbe wieder her, die die Komponente vorgibt und die selbst aus dem Thema stammt. Eine Elementfarbe übersteht den Neuaufbau der Komponente: sie wird von einer Stilregel getragen, die auf das Element zielt, nicht von einer Eigenschaft auf dem Knoten des Augenblicks. of_reset() löscht alles.

il_accent färbt nur um, was die Zone mit dem Akzent malt — eine Auswahl, eine aktive Unterstreichung, einen Fortschrittsbalken. Eine Komponente, die ihn nie benutzt, zeigt davon nichts: für „diesen Eintrag in Rot“ sind il_back_color und il_text_color die richtigen Werkzeuge, gelesen von jeder Komponente mit Elementen.

Die Schrift der ganzen Anwendung #

PBT_SetDefaultFont("Segoe UI", 14)

Ein Aufruf kleidet jede lebende Komponente und die danach erzeugten — die Schrift wird ihnen vor dem ersten Zeichnen eingespielt. Eine leere Familie oder eine Größe von 0 gibt diese Hälfte dem Thema zurück. Die Größe wird in Pixeln angegeben.


4.5 Der Hintergrund der Komponente wird an PowerBuilder gemeldet #

Jede Komponente zeichnet ihren Hintergrund gemäß dem Design und meldet dann ihre Farbe: Das Userobject übernimmt diese Farbe (backcolor) und löst ue_bg_color aus, damit das Fenster und die benachbarten PowerBuilder-Steuerelemente dazu passen.

// Event ue_bg_color einer Komponente
parent.backcolor = al_color
st_title.backcolor = al_color

Genau dadurch lassen sich PBToolboxAI-Komponenten und native PowerBuilder-Steuerelemente im dunklen Design ohne sichtbaren Übergang mischen.


4.6 Bilder und Symbole #

Überall dort, wo eine Komponente einen Bildpfad erwartet (Symbol einer Schaltfläche, Kachel, [picture=…]…), werden vier Formen akzeptiert:

FormBeispielVerwendung
Dateiimg\logo.pngBild unverändert (png, jpg, gif, bmp, ico, svg, webp)
DLL-Ressourceimg\packimages.dll:RIBBONIn einer Ressourcen-DLL verpacktes Bild
mono:mono:img\save.svgEinfarbige Fläche in der Designfarbe: nur die Form zählt
tint:tint:img\logo_couleur.pngDuotone: Die innere Schattierung moduliert die Designfarbe

Die Form pfad.dll:name lädt eine Ressource aus einer Bilder-DLL (nach Art von packimages.dll), die schreibgeschützt geöffnet wird (LOAD_LIBRARY_AS_DATAFILE, es wird kein Code ausgeführt). So müssen Sie nicht Hunderte einzelner Dateien ausliefern.

Sofortige Anzeige: of_icon #

Eine kleine Glyphe, die über of_icon() übergeben wird, ist in den Befehl eingebettet (kein Ladevorgang hin und zurück): Sie erscheint schon beim ersten Rendering, ohne das Flackern eines nachträglich geladenen Symbols.

n_pbt_utils lnv_utils   // autoinstantiate : nichts zu erzeugen, nichts zu zerstoeren

uo_toolbar.of_add_button(/*keys*/ "main/save", /*text*/ "Speichern", /*image*/ lnv_utils.of_icon(/*path*/ "mono:img\save.svg"), /*tooltip*/ "Speichern")

Für einen im Voraus bekannten Satz von Symbolen wärmt of_preload_icons() den Cache auf einmal beim Start auf: das erste Zeichnen wartet dann auf nichts mehr.

Im Gebrauch transparent: Ab einer bestimmten Größe liefert of_icon den ursprünglichen Pfad zurück (das Bild wird dann wie gewohnt geladen und zwischengespeichert).


4.7 Rich-Text-Auszeichnung #

Jede beliebige Beschriftung jeder Komponente akzeptiert eine Auszeichnung nach Art von BBCode: Titel einer Registerkarte, Beschriftung einer Schaltfläche, Text der Statusleiste, Toast-Meldung, Titel eines Panels, Text eines Tooltips…

Die Einträge der integrierten Menüs folgen derselben Regel — Kontextmenü einer Registerkarte, ···-Liste der nicht mehr passenden Registerkarten, Spaltenmenüs eines Rasters: Die im Menü angezeigte Beschriftung ist die des Steuerelements, samt Auszeichnung.

Der Text wird als Textknoten und <span> gerendert: eine HTML-Injektion ist nicht möglich.

TagWirkung
[b] [i] [u] [s] / [strike]Fett, kursiv, unterstrichen, durchgestrichen
[sub] [super]Tiefgestellt, hochgestellt
[red]…[/red] (benannte Farben)Textfarbe (red, green, blue, orange, teal…)
[accent]…[/accent]Akzentfarbe des aktuellen Designs
[color=#rrggbb] / [color=accent]Textfarbe
[bk=#rrggbb] / [backcolor=accent]Hintergrundfarbe
[font=Consolas]Schriftart
[size=14]Absolute Größe in Punkt (6 bis 200)
[size+=30] / [size-=20]Relative Größe in % (standardmäßig 20 %)
[picture=pfad] / [picture=pfad,breite,höhe]Eingebettetes Bild. Akzeptiert auch, was of_icon() liefert (eine Data-URI); die Abmessungen werden am Ende des Werts gelesen. Ein Netzwerkpfad wird dort abgelehnt (siehe unten)
[symbol=name]Eingebautes Symbol, einfarbig, in der Farbe des umgebenden Texts gezeichnet (es folgt dem Design, dem Überfahren, einem [accent]) — keine Datei mitzuliefern: clock, location, person, people, calendar, repeat, lock, bell, phone, mail, video, note, tag, link, check, star, info, warning. Ein unbekannter Name wird unverändert angezeigt
[br] / [linebreak] / [br:3]Zeilenumbruch (oder n Umbrüche)
[gap=N]Zeilenumbruch, gefolgt von einem Leerraum von N % einer Zeile: [gap=100] entspricht [br][br], [gap=50] einer halben Leerzeile
[separator]Waagerechte Linie
[hyperlink=url]…[/hyperlink]Klickbarer Bereich: Der Link öffnet sich immer im Browser des Benutzers, in jeder Komponente. Das Event ue_hyperlink(as_url) wird zusätzlich ausgelöst, bei den Komponenten, die es anbieten
[action=id]…[/action]Klickbarer Bereich → Event ue_action(as_key), als Link dargestellt
[invisibleaction=id]…[/invisibleaction]Klickbarer Bereich → ue_action, ohne den Linkstil
[bullet]…[/bullet]Aufzählungspunkt: Listeneintrag, dessen Folgezeilen an der ersten ausgerichtet werden statt unter dem Zeichen (hängender Einzug). [bullet=-] ändert das Zeichen
[foldarea:Titel]…[/foldarea]Einklappbarer Block: anklickbare Kopfzeile (− / +) über einem eingerückten Inhalt. Der Titel akzeptiert Auszeichnungen
[foldarea-closed:Titel]…[/foldarea]Derselbe Block, bei der Anzeige eingeklappt
[[ / ]]Maskierung: [[b]] zeigt [b] an, ohne es zu interpretieren
uo_text.is_text = "Willkommen bei [b][accent]PBToolboxAI[/accent][/b] [size-=20]v1.0[/size-=20]" &
                   + "[br]Lesen Sie die [hyperlink=https://pbtoolboxai.net]Dokumentation[/hyperlink]."

uo_tab.of_add_page(/*key*/ "clients", /*title*/ "[b]Kunden[/b] [size-=20](128)[/size-=20]", /*page*/ uo_clients)

uo_st.is_text = "Das Tag [[b]] macht [b]fett[/b]"   // zeigt an: Das Tag [b] macht fett

Daten unverändert anzeigen. Ein Wert aus Ihrer Datenbank kann ein bekanntes Tag enthalten — [b], [red], [picture=…]: Er würde interpretiert (ein unbekanntes Wort in Klammern wird so angezeigt, wie es geschrieben ist). of_escape_markup(), eine Funktion von n_pbt_utils, verdoppelt sie für Sie — umschließen Sie die Daten, nie die Auszeichnung, die Sie selbst geschrieben haben.

n_pbt_utils lnv_utils   // autoinstantiate : nichts zu erzeugen, nichts zu zerstoeren
// Fachdaten koennen ein BEKANNTES Tag enthalten : ohne Maskierung wird es
// INTERPRETIERT -- das [b] verschwindet und der Rest wird fett.
ls_label = "Rabatt [b]VIP"
uo_st.is_text = "Kunde : " + ls_label                          // zeigt : Kunde : Rabatt VIP (VIP fett)
uo_st.is_text = "Kunde : " + lnv_utils.of_escape_markup(/*text*/ ls_label)  // zeigt : Kunde : Rabatt [b]VIP

Ein Text ohne Tag verursacht keinerlei Mehraufwand (schneller Pfad). Ein unbekanntes Tag wird so angezeigt, wie es geschrieben ist (Saldo [netto] bleibt Saldo [netto]). Ein schließendes Tag schließt nur sein eigenes Tag, und ein schließendes Tag ohne öffnendes wird ignoriert. Ein [hyperlink] öffnet sich überall — Beschriftung, Registerkartentitel, Statusleistenfeld, Toast, Dialog: der Unterbau erledigt das. Das Event ue_action dagegen wird nur von interaktiven Textkomponenten (statictext) ausgegeben; anderswo dient [action] allein der Formatierung.

Nur http, https und mailto werden geöffnet, unabhängig von der Groß- und Kleinschreibung (HTTPS:// ebenso). Eine Beschriftung trägt oft Daten aus Ihrer Datenbank: dem System ein beliebiges Schema zu übergeben, würde eine Beschriftung in einen Programmstarter verwandeln. Aus demselben Grund greift ein Bild der Auszeichnung nie auf eine Netzwerkfreigabe zu ([picture=\\server\freigabe\x.png] wird abgelehnt): ein nicht maskierter Kommentar würde sonst schon beim Anzeigen eine Netzwerksitzung zu einem beliebigen Rechner öffnen. Ein Netzwerkbild in einem Text läuft über of_icon(), das es einbettet; is_picture und die Symbole der Komponenten behalten den Netzwerkzugriff.

Ein [foldarea] ist ein Block: Er nimmt die gesamte Breite ein und klappt bei einem Klick auf seine Kopfzeile ein — ohne Umweg über PowerBuilder. Blöcke lassen sich verschachteln, und wenn die Komponente der Höhe ihres Inhalts folgt (ib_auto_height), wird diese Höhe bei jedem Ein- und Ausklappen erneut gemeldet. Der Titel ist ebenfalls Auszeichnungstext: Nichts wird für Sie fett gesetzt, [foldarea:[b]Total[/b]] erledigt das.


← Gemeinsame Basis · Inhalt · Sprache und RTL →

4.8 Animationen und die Einstellung des Arbeitsplatzes #

Windows bietet eine Barrierefreiheits-Einstellung — Einstellungen > Barrierefreiheit > Visuelle Effekte > Animationseffekte — und die Komponenten beachten sie: Ist sie aus, läuft kein Keyframe und keine Transition. Das Diagramm ist an seinem Platz, es fährt nicht dorthin.

Das ist die richtige Voreinstellung und steht nicht zur Debatte: Wer sein System um weniger Bewegung bittet, meint es so. ib_animated = true ändert daran nichts.

Eine Anwendung darf dennoch darauf bestehen:

// Einmal deklarieren : Function long PBT_SetAnimationPolicy (long al_policy)
//                      Library "pbtoolboxai.dll"
PBT_SetAnimationPolicy(1)   // 1 = immer animieren, 0 = Arbeitsplatz beachten (Vorgabe)

Der Aufruf gilt für den ganzen Prozess und ist jederzeit möglich: lebende Komponenten folgen sofort, spätere erhalten ihn beim Öffnen.

Setzen Sie 1 nur mit einem echten Grund — ein Kiosk, eine Wandanzeige, eine Vorführung, deren Aufgabe genau darin besteht, diese Animationen zu zeigen. In einer Fachanwendung bleibt die Vorgabe.


4.9 Das Erscheinungsbild Ihrer Anwendung zusammenstellen #

Die Bibliothek liefert zehn Themes und erlaubt einer Anwendung nicht, ein elftes zu definieren: das Token-Vokabular ist intern und bleibt es. Was sie stattdessen bietet, sind drei Hebel, die sich kombinieren lassen — so bekommt man „unsere Farben", ohne ein Theme zu schreiben.

// 1. DIE BASIS: das mitgelieferte Theme, das dem Ziel am naechsten kommt.
PBT_SetDefaultTheme("office-light")

// 2. DER AKZENT: EINE Farbe kleidet jede Komponente, auch die spaeter
//    erzeugten, und alles, was das Theme daraus ableitet.
PBT_SetDefaultThemeAccent(RGB(0, 105, 92))

// 3. DIE SCHRIFT der ganzen Anwendung, in einem Aufruf.
PBT_SetDefaultFont("Segoe UI Semibold", 0)

Setzen Sie diese drei Zeilen in das open-Event des Anwendungsobjekts: sie erreichen jede Komponente vor ihrem ersten Zeichnen, also ohne jedes Flackern.

HebelReichweiteWas er ändert
PBT_SetDefaultThemeder ProzessStil und Modus: Formen, Rundungen, Stärken, die ganze Palette
PBT_SetDefaultThemeAccentder Prozessden Akzent und was das Theme daraus ableitet — Hover und Gedrückt der Akzent-Schaltflächen, Auswahl, lesbarer Text darüber, Tab-Unterstreichung; Komponenten mit lokalem Design eingeschlossen, und er übersteht einen Designwechsel
PBT_SetDefaultFontder ProzessFamilie und Größe; eine leere Familie oder Größe 0 gibt diese Hälfte an das Theme zurück
il_theme_accenteine Komponenteihren eigenen Akzent, wenn sich ein Fenster abheben soll
il_back_color · il_text_colorein Elementeinen genauen Eintrag, rot weil er löscht (siehe 4.4)

Was damit nicht geht #

Die vollständige Palette neu zu definieren — die Flächengrautöne, die Rahmen, den Eckenradius — wird nicht angeboten. Ein Theme ist ein stimmiger Satz von rund sechzig Werten, die aufeinander antworten: die Hälfte davon zu öffnen ergäbe unlesbare Kombinationen, die niemand geprüft hätte. Wenn Ihr Corporate Design mehr als diese drei Hebel verlangt, schreiben Sie uns: ein weiteres Theme in der Bibliothek ist eine Option, Ihr Theme in Ihrem Code nicht.

In der Demo-Anwendung: Menüband Home > Erscheinungsbild > Stil > Corporate (composed). Der Eintrag kombiniert diese drei Hebel — nichts, was uns vorbehalten wäre — mit zwei Abweichungen: das Design ist office-light oder office-dark, je nach Hell/Dunkel-Schaltfläche des Menübands, und die Schrift wird mit 16 Pixeln gesetzt. Der Code ist wf_apply_style im Fenster w_demo_home.


4.10 Der hohe Kontrast von Windows #

Wenn der Benutzer ein Windows-Design Hoher Kontrast aktiviert, ersetzt die Engine die Farben der Seite durch die des Systems, unabhängig vom Design der Bibliothek. Die Komponenten berücksichtigen das: einfarbige Symbole (mono:, tint:) übernehmen die Textfarbe des Systems — auf einer ausgewählten Zeile die des hervorgehobenen Textes —, Fokusringe und als Schatten gezeichnete Markierungen erhalten eine echte Kontur, und was seine Bedeutung über die Farbe trägt (ein Statuspunkt, eine von der Anwendung gewählte Farbe), behält sie. Auf Anwendungsseite ist nichts zu tun: keine Eigenschaft, kein Aufruf.


4.11 Fremde Inhalte: Webbrowser und PDF-Viewer #

webbrowser und pdfviewer zeigen Inhalte, die die Bibliothek nicht zeichnet: eine Website oder den PDF-Viewer der Engine. Diese Inhalte kennen die Designs der Bibliothek nicht, lesen aber die Hell- oder Dunkel-Präferenz, die der Browser ihnen meldet, so wie eine Website die von Windows liest. Diese Präferenz folgt dem Standarddesign der Anwendung (PBT_SetDefaultTheme) — nicht dem Windows-Modus, nicht dem lokalen Design einer Komponente: eine Anwendung in fluent-dark zeigt die dunkle Version einer Website, die eine anbietet, und den PDF-Viewer in seinen dunklen Farben. Bevor die fremde Seite gezeichnet hat, nimmt der Bereich den Hintergrund des Designs an statt eines weißen Rechtecks.