# webbrowser — `u_pbt_webbrowser` #

← Référence des composants · Sommaire du guide

> Navigateur web intégré à votre fenêtre : affichage d'une page, barre d'adresse, historique Précédent / Suivant, menu contextuel de navigation.

> ▶ Le voir en vrai — Application de démonstration, tuile Web browser : l'aperçu, le code qui le produit et cette page, côte à côte.

## En bref #

Userobject | `u_pbt_webbrowser`
Classe d'items | — (composant sans items)
Sert à | Afficher une page web, un portail interne, une documentation en ligne ou un contenu HTML généré, sans quitter l'application
Deux modes d'affichage | intégré (par défaut) ou pleine page, selon la tolérance du site visité

## Démarrage rapide #

    // event open de la fenetre
    uo_navigateur.ib_address_bar = true    // barre d'adresse + boutons de navigation
    uo_navigateur.is_address = "https://fr.wikipedia.org/wiki/PowerBuilder"

Poser `is_address` est l'acte de navigation : chaque affectation ouvre la page demandée. Une adresse sans protocole (`"exemple.com"`) reçoit automatiquement `https://`.

## Propriétés #

Propriété | Type | Défaut | Rôle
--- | --- | --- | ---
`is_address` | string | `""` | Adresse affichée. Affecter cette propriété déclenche la navigation. La relire donne la page réellement affichée : si l'utilisateur suit un lien, elle suit aussi (`ue_load_completed` vous prévient). Tous les schémas sont acceptés, y compris `data:` et `file:`
`ib_address_bar` | boolean | `false` | Affiche la barre d'adresse intégrée : champ URL, boutons Précédent / Suivant / Recharger
`ib_context_menu` | boolean | `false` | Active le menu contextuel de navigation au clic droit : Précédent, Suivant, Recharger
`is_theme_style` | string | `fluent` | Style visuel du composant (constantes `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante claire ou sombre (constantes `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Couleur d'accent de ce composant (`-1` = accent du thème)

## Méthodes #

Méthode | Rôle
--- | ---
`of_refresh ( )` | Recharge la page courante
`of_go_back ( )` | Revient à la page précédente
`of_go_forward ( )` | Avance à la page suivante
`of_can_go_back ( )` → boolean | `true` si une page précédente existe — pour activer ou griser votre bouton Précédent
`of_can_go_forward ( )` → boolean | `true` si une page suivante existe
`of_stop ( )` | Interrompt le chargement en cours
`of_execute_javascript (string as_script)` | Exécute un script dans la page affichée et renvoie sa valeur sous forme de chaîne (du JSON : un texte revient entre guillemets, un nombre non). Une seule condition, et elle est structurelle : la page doit être chargée, donc appelez-la depuis `ue_load_completed`, jamais juste après avoir posé `is_address`. Renvoie une chaîne vide si le script échoue ou s'il n'y a pas de page
`of_reset ( )` | Remet le composant à neuf : page vidée, historique de navigation effacé, barre d'adresse masquée, menu contextuel désactivé, retour au mode intégré
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Exporte le rendu en image

## Événements #

Événement | Déclenché quand
--- | ---
`ue_load_completed (string as_url)` | Une page a fini de se charger ; `as_url` est l'adresse effectivement affichée
`ue_ready ( )` | Le composant a fini de charger ; tout ce qui a été envoyé avant a été rejoué
`ue_runtime_missing ( )` | Le runtime WebView2 est absent : le composant reste vide
`ue_bg_color (long al_color)` | Le composant a calculé sa couleur de fond de thème ; l'userobject l'a déjà adoptée (`backcolor`)

## Naviguer #

### La barre d'adresse intégrée #

C'est la solution la plus rapide : une propriété, et l'utilisateur dispose d'un champ URL et des boutons Précédent / Suivant / Recharger, thémés comme le reste de l'application.

    uo_navigateur.ib_address_bar = true
    uo_navigateur.is_address = "https://fr.wikipedia.org/wiki/PowerBuilder"

Les boutons se grisent tout seuls quand il n'y a nulle part où aller.

### Vos propres boutons #

Si vous préférez piloter la navigation depuis votre propre barre d'outils, masquez la barre intégrée et utilisez les méthodes :

    // Boutons Precedent / Suivant de votre fenetre
    uo_navigateur.of_go_back()
    uo_navigateur.of_go_forward()

    // event ue_load_completed de uo_navigateur : (string as_url)
    // Mettre a jour l'etat de vos boutons apres chaque page
    uo_barre.of_bar("main").of_item("precedent").ib_enabled = uo_navigateur.of_can_go_back()
    uo_barre.of_bar("main").of_item("suivant").ib_enabled   = uo_navigateur.of_can_go_forward()

    // Et refleter l'adresse reelle (redirections comprises)
    sle_url.text = as_url

### Le menu contextuel de navigation #

`ib_context_menu` ajoute au clic droit un petit menu Précédent / Suivant / Recharger, thémé et rendu par l'application. Il partage exactement le même historique que la barre d'adresse : les deux restent donc toujours cohérents.

    uo_navigateur.ib_context_menu = true

### Arrêter un chargement #

    // Bouton Stop : interrompt une page qui tarde
    uo_navigateur.of_stop()

## Sites qui refusent l'affichage intégré #

Certains sites — Google, la plupart des banques, beaucoup d'applications SaaS — envoient des en-têtes de sécurité qui interdisent leur affichage à l'intérieur d'une autre page. Le composant n'est pas concerné : il n'affiche jamais un site dans un cadre. La page est ouverte comme document principal, exactement comme le fait votre navigateur, et ces en-têtes ne s'appliquent alors plus.

Il n'y a donc rien à régler, et aucun cas particulier à prévoir dans votre code.

    // Un site qui refuse d'etre integre dans une page : rien de special a faire
    uo_navigateur.ib_address_bar = true
    uo_navigateur.is_address = "https://www.google.com"

En contrepartie, la page occupe toute la surface du composant sous la barre d'adresse : les habillages posés par-dessus (bandeaux, superpositions thémées) ne sont pas visibles pendant la navigation.

## Contenu HTML sans réseau #

Toute adresse est acceptée, y compris une page HTML fournie directement. Pratique pour un aperçu de courrier, un ticket, une facture ou un rapport généré par votre application, sans aucun appel réseau ni fichier temporaire :

    string ls_html

    ls_html = "<html><head><meta charset='utf-8'></head><body>" &
            + "<h1>Recapitulatif de commande</h1>" &
            + "<p>Merci de votre confiance.</p>" &
            + "</body></html>"

    uo_navigateur.is_address = "data:text/html," + ls_html

Un fichier local s'ouvre de la même façon avec `file:///C:/temp/rapport.html`.

## Repartir de zéro #

`of_reset()` ne se contente pas de vider la page : il efface aussi l'historique de navigation. Un utilisateur ne peut donc pas revenir, par le bouton Précédent, sur une page consultée par l'utilisateur précédent ou dans un autre dossier.

    // Changement de dossier : on repart d'un navigateur vierge, sans historique
    uo_navigateur.of_reset()

    uo_navigateur.ib_address_bar = true
    uo_navigateur.is_address = ls_url_du_dossier

C'est le réflexe à avoir chaque fois qu'un même composant sert à afficher des contenus de contextes différents.

## Exemple complet #

    // event open de la fenetre : page d'accueil du portail interne
    uo_navigateur.of_reset()                  // repartir propre (historique compris)

    uo_navigateur.ib_address_bar  = true      // champ URL + Precedent / Suivant / Recharger
    uo_navigateur.ib_context_menu = true      // meme navigation au clic droit
    uo_navigateur.is_address = "https://intranet.societe.fr/accueil"

    // event ue_load_completed de uo_navigateur : (string as_url)
    uo_statut.of_item("main").is_text = "Page chargee : " + as_url

## Bonnes pratiques #

- Affectez `is_address`, n'appelez pas de méthode de navigation : c'est la propriété qui déclenche l'ouverture de la page.
- Activez `ib_address_bar` dès que l'utilisateur peut naviguer librement ; réservez le pilotage par vos propres boutons aux parcours contraints.
- Fiez-vous à `of_can_go_back()` / `of_can_go_forward()` pour l'état de vos boutons plutôt que de compter les pages vous-même : les redirections fausseraient votre compte.
- Rien à prévoir pour les sites qui refusent l'affichage intégré : la page est toujours ouverte comme document principal, ces en-têtes ne s'appliquent pas.
- Appelez `of_reset()` en changeant de contexte : c'est le seul moyen de garantir qu'aucune page précédente n'est accessible par le bouton Précédent.
- Le composant a besoin du runtime web installé sur le poste : traitez `ue_runtime_missing` comme pour tout autre composant (Installation).

← Référence des composants · Sommaire du guide