# 6. Übergreifende Funktionen #

← Sprache und RTL · Inhalt · FAQ →

Dieses Kapitel bündelt die Dienste, die unabhängig von der Komponente verfügbar sind: Tooltips, Hosting von PowerBuilder-Steuerelementen, Drag & Drop aus dem Explorer, Tastaturfokus, Bildexport und die nicht visuellen Hilfsobjekte.

## 6.1 Einfache und erweiterte Tooltips #

### Tooltip der Komponente #

    uo_bouton.is_tooltip = "Die Akte speichern (Strg+S)"

Der Text nimmt die Rich-Text-Auszeichnung an: `[b]`, `[br]`, `[color=…]`, `[picture=…]`…

### Rich-Tooltip (Titel + Text + Bild) #

Für eine kontextbezogene Hilfe im Stil des Office-Menübands:

    uo_bouton.is_super_tooltip_title = "Speichern"
    uo_bouton.is_super_tooltip_text  = "Schreibt die Änderungen auf den Server." &
                                       + "[br][br][size-=15]Tastenkürzel: Strg+S[/size-=15]"
    uo_bouton.is_super_tooltip_image = "img\help_save.png"

Die drei Eigenschaften sind voneinander unabhängig: ein Titel allein oder ein Titel mit Text ohne Bild sind gültig. Sobald eine Eigenschaft `is_super_tooltip_*` gesetzt ist, hat sie Vorrang vor `is_tooltip`.

### Tooltip eines Items #

Jede Item-Klasse (`n_pbt_item` und ihre Nachfahren) trägt dieselben vier Eigenschaften:

    uo_toolbar.of_bar("main").of_item("save").is_tooltip = "Speichern"

    uo_tab.of_item("clients").is_super_tooltip_title = "Kunden"
    uo_tab.of_item("clients").is_super_tooltip_text  = "128 Datensätze, letzte Synchronisierung um 09:12"

### Verhalten #

- Der Tooltip ist ein natives, dem Design folgendes Fenster, in allen Komponenten identisch (er wird nicht durch die Grenzen des Webviews eingeschränkt).
- Er erscheint nicht, wenn Ihre Anwendung nicht den Fokus hat: Mit der Maus über ein Fenster im Hintergrund zu fahren, löst nichts aus.
- Er verschwindet, sobald Sie zu einer anderen Anwendung wechseln, und spätestens nach 10 Sekunden.
- `of_reset()` entfernt die Tooltips, die auf der Instanz und auf ihren Items gesetzt wurden.

## 6.2 Echte PowerBuilder-Steuerelemente hosten #

Die Container-Komponenten zeigen an der Stelle Ihrer Masken kein HTML an: Sie nehmen echte PowerBuilder-Steuerelemente auf (Userobjects, DataWindows, Steuerelementgruppen), die als untergeordnete Win32-Fenster umgehängt werden. Ihre vorhandenen Masken werden unverändert weiterverwendet.

    // Registerkarten: jede Seite ist ein PB-Userobject
    uo_tab.of_add_page("clients",   "Kunden",   uo_page_clients)
    uo_tab.of_add_page("factures",  "Rechnungen",  uo_page_factures, /*schliessbar*/ true)

    // Andockbare Panels: genauso
    uo_dock.is_main = "doc"                       // zentraler Bereich
    uo_dock.of_add_panel("doc",      uo_dock.POSITION_STACK, "", 0,   "Dokument",    uo_editeur)
    uo_dock.of_add_panel("explorer", uo_dock.POSITION_START, "", 240, "Explorer", uo_arbre)
    uo_dock.of_add_panel("props",    uo_dock.POSITION_END,   "", 260, "Eigenschaften",  uo_props)

Was Ihnen abgenommen wird:

- die Positionierung und die Größenanpassung des gehosteten Steuerelements, wenn sich die Größe der Registerkarte oder des Panels ändert;
- das Anzeigen / Ausblenden beim Wechsel der aktiven Registerkarte oder des aktiven Panels;
- die schwebenden, angedockten oder automatisch ausgeblendeten Panels (dockcontainer);
- die saubere Zerstörung beim Schließen des Fensters.

> ⚠️ Ein gehostetes Steuerelement ist ein natives Fenster: Es wird über der Web-Ebene gezeichnet. Das ist so gewollt (Ihr DataWindow bleibt scharf und schnell), bedeutet aber, dass kein Web-Effekt — Schatten, Transparenz, Animation — darüber gelegt werden kann.

## 6.3 Dateien aus dem Windows-Explorer entgegennehmen #

Eine Komponente kann zum Ablageziel für Dateien werden, die aus dem Explorer gezogen werden. Die Bibliothek installiert ein natives Ablageziel: Sie erhalten die vollständigen Pfade, was eine HTML-Ablage nicht ermöglicht.

    uo_editeur.ib_allow_drop = true

    // Event ue_drop_files von uo_editeur: (string as_files[])
    long ll_i

    for ll_i = 1 to UpperBound(as_files)
        of_ouvrir_fichier(as_files[ll_i])
    next

Event | Ausgelöst wenn
--- | ---
`ue_drag_enter ( )` | Ein Dateiziehvorgang tritt in die Komponente ein
`ue_drag_leave ( )` | Er verlässt sie ohne Ablage
`ue_drop_files (string as_files[])` | Die Dateien werden abgelegt — vollständige Pfade

Die Komponente liefert die visuelle Rückmeldung beim Überfahren selbst (Hervorhebung der Ablagezone). Veröffentlicht von den Komponenten, bei denen eine Ablage sinnvoll ist: `statictext`, `codeeditor`.

## 6.4 Tastatur und Fokus #

Eine PBToolboxAI-Komponente nimmt an der Tastaturnavigation Ihres Fensters teil wie ein natives Steuerelement:

- die Tabulatortaste erreicht sie in der Tabulatorreihenfolge des Fensters;
- die Tasten (Pfeile, Eingabe, Escape, Eingaben) werden von der Komponente verarbeitet, die den Fokus hat;
- die Fenster-Tastenkürzel (Eingabe = Standardschaltfläche, Escape = Abbrechen) funktionieren weiterhin, auch wenn der Fokus in einer Komponente liegt.

Um dem Inhalt einer Komponente ausdrücklich den Fokus zu geben (zum Beispiel nach dem Öffnen eines Suchbereichs):

    uo_editeur.of_focus_webview()

## 6.5 Die Darstellung als Bild exportieren #

Zur Erinnerung aus der gemeinsamen Basis: Jede Komponente lässt sich so exportieren, wie sie angezeigt wird.

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

Nützlich, um ein Diagramm an eine E-Mail anzuhängen, einen Bericht zu versorgen oder einen Anwenderzwischenfall zu dokumentieren.

## 6.6 Dialogfelder und Benachrichtigungen #

Zwei Dienste, für die kein Steuerelement im Fenster platziert werden muss:

    // Modales Dialogfeld im Design (synchrone Rueckgabe)
    n_pbt_messagebox lnv_mb

    lnv_mb = create n_pbt_messagebox
    lnv_mb.is_title   = "Löschen"
    lnv_mb.is_message = "[b]12 Akten[/b] endgültig löschen?"
    lnv_mb.is_icon    = lnv_mb.ICON_QUESTION
    lnv_mb.of_add_button("Löschen", /*standard*/ false, /*abbruch*/ false)
    lnv_mb.of_add_button("Abbrechen",   /*standard*/ true,  /*abbruch*/ true)

    if lnv_mb.of_show(Handle(this)) = 1 then of_supprimer()
    destroy lnv_mb

    // Nicht blockierende "Toast"-Benachrichtigung in einer Bildschirmecke
    n_pbt_toaster lnv_toast

    lnv_toast = create n_pbt_toaster
    lnv_toast.is_title = "Import abgeschlossen"
    lnv_toast.is_text  = "1.240 Zeilen übernommen."
    lnv_toast.is_kind  = lnv_toast.KIND_SUCCESS
    lnv_toast.of_show()
    destroy lnv_toast

Vollständige Einzelheiten: messagebox und toaster.

## 6.7 Nicht visuelle Hilfsobjekte #

In derselben PBL ausgeliefert, ohne Webview und ohne Darstellung: Es sind einfache Hüllen um die DLL. Erzeugen Sie sie, verwenden Sie sie, zerstören Sie sie.

### Base64-Codierung — `u_pbt_base64` #

    u_pbt_base64 lnv_b64
    string ls_encode

    lnv_b64 = create u_pbt_base64
    ls_encode = lnv_b64.of_encode("Guten Tag")   // Text -> UTF-8 -> Base64
    ls_texte  = lnv_b64.of_decode(ls_encode)     // "" wenn die Eingabe ungueltig ist
    destroy lnv_b64

### Prüfsummen — `u_pbt_hash` #

    u_pbt_hash lnv_hash

    lnv_hash = create u_pbt_hash
    ls_empreinte = lnv_hash.of_sha256("Kennwort")                // Hexadezimal in Kleinbuchstaben
    ls_fichier   = lnv_hash.of_file("SHA256", "C:\livraison.zip")
    destroy lnv_hash

Methode | Zweck
--- | ---
`of_string (string as_algo, string as_texte)` | Prüfsumme einer Zeichenfolge — `MD5`, `SHA1`, `SHA256`, `SHA384`, `SHA512`
`of_file (string as_algo, string as_chemin)` | Prüfsumme des Inhalts einer Datei (`""` wenn unlesbar)
`of_md5` · `of_sha1` · `of_sha256` · `of_sha512` | Kurzformen

### Reguläre Ausdrücke — `u_pbt_regex` #

ECMAScript-Syntax, die es in PowerScript nicht gibt.

    u_pbt_regex lnv_re
    string ls_trouves[]

    lnv_re = create u_pbt_regex

    if lnv_re.of_is_match("^[\w.]+@[\w.]+\.\w{2,}$", ls_email) then …

    ls_annee = lnv_re.of_match("(\d{4})-(\d{2})-(\d{2})", ls_date, /*gruppe*/ 1)
    ls_propre = lnv_re.of_replace("\s+", ls_saisie, " ")
    ll_nb = lnv_re.of_match_all("[A-Z]{2}\d{6}", ls_texte, ls_trouves)

    destroy lnv_re

Methode | Zweck
--- | ---
`of_is_match (Muster, Text [, ab_ignore_case | al_flags])` | Passt der Text?
`of_match (Muster, Text, ai_groupe [, al_flags])` | Erste Fundstelle (`0` = alles, `1..` = einfangende Gruppe)
`of_match_all (Muster, Text [, ai_groupe, al_flags], ref as_res[])` | Alle Fundstellen; gibt die Anzahl zurück
`of_replace (Muster, Text, Ersetzung)` | Ersetzt alle Vorkommen (`$1`… erlaubt)

Kombinierbare Optionen: `FLAG_IGNORE_CASE` (1), `FLAG_SINGLELINE` (2, der `.` überschreitet Zeilenumbrüche).

### Eindeutige Bezeichner — `u_pbt_guid` #

    u_pbt_guid lnv_guid

    lnv_guid = create u_pbt_guid
    ls_id = lnv_guid.of_new()          // 1b4e28ba-2fa1-11d2-883f-0016d3cca427
    ls_id = lnv_guid.of_new_braces()   // {1b4e28ba-...}
    ls_id = lnv_guid.of_new_plain()    // 1b4e28ba2fa111d2883f0016d3cca427
    destroy lnv_guid

### ZIP-Archive — `u_pbt_zip` #

    u_pbt_zip lnv_zip

    lnv_zip = create u_pbt_zip
    lnv_zip.of_compress("C:\temp\livraison.zip", "C:\appli\export")   // Datei ODER Ordner
    lnv_zip.of_extract("C:\temp\livraison.zip",  "C:\appli\import")   // Ordner wird angelegt, falls er fehlt
    destroy lnv_zip

Beide Methoden geben einen `boolean` zurück.

## 6.8 Informationen über die Bibliothek #

    // Version der DLL
    string ls_version

    ls_version = Space(32)
    PBT_GetVersion(ls_version, 32)

Globale Funktion | Zweck
--- | ---
`PBT_GetVersion (ref string, long)` | Version der Bibliothek
`PBT_CheckRuntime (ref string, long)` | Version der installierten WebView2-Laufzeitumgebung (`≤ 0` = nicht vorhanden)
`PBT_GetLastErrorMessage (ref string, long)` | Letzte Fehlermeldung des Prozesses
`PBT_LicenseStatus ( )` | Zustand der Lizenz — siehe Lizenz

## 6.9 Drucken #

Jede Komponente kann sich selbst drucken, so wie sie angezeigt wird, ohne zwischengeschaltetes DataWindow.

    // Lautlos: ein PDF auf der Platte, nichts zum Anklicken
    uo_grille.of_print_to_pdf("C:\etats\ventes.pdf")

    // Querformat, fuer ein breites Raster
    uo_grille.of_print_to_pdf(/*fichier*/ "C:\etats\ventes.pdf", /*paysage*/ true)

    // Mit Dialog: der Benutzer waehlt seinen Drucker und sieht die Vorschau
    uo_grille.of_print()

    // Direkt der Systemdruckdialog
    uo_grille.of_print(/*dialogue systeme*/ true)

Methode | Zweck
--- | ---
`of_print_to_pdf (string as_path)` · `of_print_to_pdf (string, boolean ab_landscape)` | Schreibt ein PDF, ohne etwas anzuzeigen. Kehrt erst zurück, wenn die Datei geschrieben ist (`0` = erledigt)
`of_print ( )` · `of_print (boolean ab_system_dialog)` | Öffnet den Druckdialog. Kehrt zurück, sobald der Dialog steht: was der Benutzer damit macht, ist seine Sache

> ⚠️ Gedruckt wird, was GERENDERT ist. Ein virtualisiertes Raster druckt nur die Zeilen, die es hält: für einen vollständigen Bericht zuerst auf ein Layout wechseln, das alle zeigt (Seitennummerierung), oder die Daten statt der Darstellung exportieren.

Der Rückgabewert `-6` bedeutet, dass die WebView2-Runtime zum Drucken zu alt ist (1.0.1108 für das PDF, 1.0.1587 für den Dialog). Alles Übrige folgt den gemeinsamen Rückgabewerten.

← Sprache und RTL · Inhalt · FAQ →