shellexplorer — u_pbt_shellexplorer #
← Référence des composants · Sommaire du guide
L'arborescence du shell Windows : Bureau, Ce PC, lecteurs, dossiers, Réseau — avec les vraies icônes du poste.
▶ Le voir en vrai — Application de démonstration, tuile Shell explorer : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Userobject | u_pbt_shellexplorer |
| Sert à | Choisir un dossier, ou naviguer, sans quitter l'application |
| Principe | Vous dites où commencer ; le shell dit ce qu'il y a, et vous recevez ce que l'utilisateur choisit |
Démarrage rapide #
// Open event of the window : the tree starts where the application works
uo_tree.is_root = "C:\Projects"
Puis, dans l'événement ue_selected de l'arbre :
// Event ue_selected : the folder the user chose, by its display name
st_folder.text = as_name
Le shell, pas le système de fichiers #
Le composant n'énumère pas des répertoires : il interroge le shell (IShellFolder). C'est ce qui met dans l'arbre Ce PC, le Réseau, la Corbeille et les dossiers virtuels — c'est-à-dire l'arbre que l'utilisateur connaît, au lieu d'une liste de lecteurs.
Chaque nœud est identifié par son nom d'analyse : un chemin pour ce qui est sur le disque, une forme ::{GUID} pour le reste. C'est la seule clé que le shell sait relire — donc la seule à stocker si vous voulez rouvrir une branche demain.
🚨
ue_selectedvous donne le nom EN PLUS du chemin, et ce n'est pas une commodité. Le nom affiché d'un dossier virtuel n'est pas la fin de son chemin : « Ce PC » n'a pas de fin. Une application qui découpe le chemin pour en tirer un libellé affichera::{20D04FE0-…}à son utilisateur.
L'arbre se construit au fur et à mesure qu'on le parcourt : une branche n'est demandée qu'à son ouverture. Lire un disque entier pour dessiner un arbre gèlerait l'application pendant des minutes sur un lecteur réseau — et c'est le cas normal dans les applications où cette bibliothèque vit.
// Event ue_selected : the path AND the display name
st_path.text = as_path
st_name.text = as_name
Propriétés #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_root | string | "" | Où commence l'arbre (constantes ROOT_*). Vide = la racine du shell. Un chemin y commence à la place |
ib_show_files | boolean | false | Affiche aussi les fichiers. Faux par défaut : un arbre sert à choisir un lieu, et un dossier de quatre mille fichiers n'est plus un lieu |
ib_show_hidden | boolean | réglage de l'Explorateur | Montre les fichiers et dossiers masqués. Tant que l'application ne la pose pas, elle suit le réglage « Éléments masqués » de l'Explorateur du poste — et le relit. Les fichiers protégés du système ne suivent jamais que l'Explorateur |
is_file_filter | string | "" | Les fichiers montrés quand ib_show_files est vrai : motifs séparés par un point-virgule (*.pdf;*.docx), jugés sur le vrai nom du fichier. Les dossiers passent toujours, pour que l'utilisateur marche jusqu'au fichier. Vide = tous. Posé tant que ib_show_files est faux, il ne relit rien : il part avec les fichiers |
ib_enabled | boolean | true | Faux : l'arbre reste affiché, estompé, et ne répond plus ni au clic ni au clavier ; il sort de l'ordre de tabulation. L'application le pilote toujours (of_select, of_expand, of_refresh) |
is_theme_style | string | "" | Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement |
is_theme_mode | string | "" | Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement |
il_theme_accent | long | -1 | Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème) |
is_tooltip | string | "" | Info-bulle simple affichée au survol du composant |
is_super_tooltip_title | string | "" | Titre de l'info-bulle enrichie (prend le pas sur is_tooltip) |
is_super_tooltip_text | string | "" | Texte de l'info-bulle enrichie (balisage riche accepté) |
is_super_tooltip_image | string | "" | Image de l'info-bulle enrichie |
Une propriété écrite avec la valeur qu'elle a déjà ne relit rien au shell : une fenêtre peut appliquer ses réglages à chaque ouverture sans rien payer.
Méthodes #
| Méthode | Rôle |
|---|---|
long of_expand ( string as_path ) | Ouvre une branche, et les branches fermées au-dessus d'elle : un seul appel pour un chemin profond, même pas encore dessiné, depuis n'importe quelle racine (sous le Bureau, C:\ s'atteint par Ce PC). Un dossier créé après la lecture de son parent est trouvé en relisant ce parent une fois. La casse et l'antislash final ne comptent pas. Un chemin inatteignable, ou qui n'est pas une branche, lève ue_path_not_found. Comme le chevron, lève ue_expanded pour chaque branche qui s'ouvre en chemin (aucun pour une branche déjà ouverte). Renvoie 0 une fois envoyé, -5 pour un chemin vide, -2 si le composant n'est pas créé |
long of_collapse ( string as_path ) | Ferme une branche. Ses enfants restent en place, donc la rouvrir ne coûte rien. Une sélection qui était dedans remonte sur la branche. Comme un clic sur son chevron, lève ue_collapsed, et ue_selected quand la sélection remonte sur la branche ; rien si la branche est déjà fermée ou n'est pas dessinée (il n'y a rien à fermer). Un chemin dessiné deux fois ferme UNE ligne, celle qu'atteindrait of_select. Renvoie 0 une fois appliqué, -5 pour un chemin vide, -2 si le composant n'est pas créé |
long of_select ( string as_path ) | Sélectionne un nœud. Les branches au-dessus de lui s'ouvrent, la sélection est à l'écran ; un nœud pas encore dessiné s'atteint comme avec of_expand, un nœud inatteignable lève ue_path_not_found. Comme un clic, lève ue_selected (rien si le nœud est déjà sélectionné) ; of_selected_key le relit une fois arrivé. Renvoie 0 une fois envoyé, -5 pour un chemin vide, -2 si le composant n'est pas créé |
long of_refresh ( { string as_path } ) | Relit l'arbre auprès du shell — après que l'application a écrit sur le disque. Les branches ouvertes se rouvrent et la sélection revient, retrouvées par leur chemin ; ce qui n'existe plus est abandonné, et une sélection disparue lève ue_selected avec deux textes vides. Avec un chemin, seule cette branche est relue (une branche jamais ouverte n'a rien à relire). Renvoie 0 une fois demandé, -5 pour un chemin vide, -2 si le composant n'est pas créé |
string of_selected_key ( ) | Le nom d'analyse du nœud choisi. La seule clé que le shell sait relire |
string of_selected_name ( ) | Le nom affiché, tel que l'Explorateur le montre. Ne le déduisez jamais du chemin |
boolean of_selected_is_folder ( ) | Vrai quand le nœud choisi est un dossier, faux pour un fichier ou si rien n'est sélectionné. Les événements ne donnent que le chemin |
boolean of_has ( string as_keys ) | Vrai quand ce chemin est dessiné dans l'arbre, ouvert ou non. Un chemin est UNE clé : ses antislashs ne sont pas des niveaux. La casse ne compte pas, ni / écrit pour \ (C:/Data est C:\Data). La racine (son chemin, ou "") y est dès que le shell l'a lue |
long of_count ( { string as_keys } ) | Sans chemin : le nombre de lignes que l'arbre affiche (une branche fermée cache ses enfants). Avec un chemin : le nombre d'enfants lus sous lui — 0 tant qu'il n'a jamais été ouvert, une branche n'étant lue qu'à son ouverture. La racine compte aussi, par son chemin ou par "" : of_count(is_root) est le nombre de nœuds du premier niveau, quoi qu'il y ait d'ouvert dessous |
string of_keys_at ( string as_keys, long al_index ) | Le chemin de l'enfant de rang al_index (à partir de 1) sous un chemin, "" au-delà des bornes. Un chemin d'enfant est déjà entier : il se réinjecte tel quel dans of_has, of_count, of_select ou of_expand. of_keys_at(is_root, i) parcourt le premier niveau ; of_keys_at(al_index) parcourt de même les lignes affichées |
long of_reset ( ) | Revient à la racine du shell, dossiers seuls, rien de sélectionné. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
Événements #
| Événement | Déclenché quand |
|---|---|
ue_selected (string as_path, string as_name) | Un nœud est sélectionné — par l'utilisateur (clic, clavier) ou par of_select / of_collapse : son chemin et son nom d'affichage. Levé aussi avec deux textes vides quand une relecture trouve que le nœud sélectionné a disparu |
ue_expanded (string as_path) | Une branche s'ouvre — par l'utilisateur (chevron, double-clic, clavier) ou par of_expand / of_select, une fois par branche ouverte en chemin. L'événement part avant l'arrivée des enfants — le shell est interrogé à cet instant, et sur un partage réseau il prend son temps |
ue_activated (string as_path) | Double-clic, ou touche Entrée. C'est là qu'une application ouvre le dossier, le charge, ou referme un sélecteur. Sur une branche, ils l'ouvrent ou la ferment aussi : ue_expanded ou ue_collapsed suit |
ue_error (string as_path, string as_reason, string as_message) | Le shell refuse une branche ou la racine — lecteur déconnecté, dossier sans droits, partage qui ne répond pas en 30 secondes — : as_path est son chemin ("" pour le Bureau), as_reason une constante REASON_* que votre code teste (REASON_ACCESS_DENIED, REASON_TIMEOUT, REASON_NOT_FOUND, REASON_UNREADABLE), as_message le texte du shell pour un humain, chemin : texte ((root) : … pour le Bureau). La branche se referme (ue_collapsed) et sera redemandée à sa prochaine ouverture ; une racine illisible l'écrit dans l'arbre |
ue_collapsed (string as_path) | Une branche se ferme — par l'utilisateur, par of_collapse, ou par l'arbre lui-même quand une branche annoncée ouverte par ue_expanded revient vide ou est refusée par le shell. Une sélection qui était dedans remonte sur la branche, et ue_selected le rapporte |
ue_path_not_found (string as_path, string as_action, string as_reason) | Un of_expand ou un of_select n'a pas pu être servi. as_action vaut expand ou select ; as_reason une constante REASON_* (voir plus bas) : le chemin n'existe pas, l'arbre ne le montre pas, il sort de la racine, est la racine, n'est pas une branche, dépasse la limite de la démonstration, ou sa branche est illisible |
ue_node_rclicked (string as_path, long al_x, long al_y) | Un clic droit sur un nœud — sélectionné d'abord, comme dans l'Explorateur, donc ue_selected vient avant quand la sélection change —, ou la touche du menu contextuel (ou Maj + F10) sur le nœud sélectionné. al_x, al_y sont des pixels d'écran (au clavier, le coin bas-gauche du nœud), ceux que prend un contextmenu : uo_menu.of_show(al_x, al_y) ; pour un menu PowerBuilder, PopMenu(PointerX(), PointerY()) de votre fenêtre |
Les icônes viennent de l'imagelist système du poste, pas de nous : un fichier
.dwgporte l'icône d'AutoCAD si AutoCAD est installé, et l'icône générique sinon. C'est ce que l'utilisateur attend, et rien d'autre ne peut le donner.
Raisons d'un échec : les constantes REASON_* #
ue_path_not_found et ue_error donnent leur raison par une constante de u_pbt_shellexplorer, la même dans les deux événements et dans toutes les langues de Windows : testez-la, jamais le texte.
| Constante | Ce qu'elle dit |
|---|---|
REASON_NOT_FOUND | Le chemin n'existe pas |
REASON_NOT_SHOWN | Le chemin existe, l'arbre ne le montre pas : un fichier alors que ib_show_files est faux, un élément masqué, un fichier écarté par is_file_filter |
REASON_OUTSIDE_ROOT | Le chemin n'est pas sous is_root |
REASON_THE_ROOT | Le chemin est la racine elle-même : ce n'est pas un nœud de l'arbre |
REASON_NOT_A_BRANCH | of_expand d'un fichier, ou d'un dossier sans enfant |
REASON_ACCESS_DENIED | Le shell refuse : pas de droits |
REASON_TIMEOUT | Pas de réponse en 30 secondes (un partage disparu) ; ce serveur répond ensuite timeout tout de suite, pendant 30 secondes, jusqu'à une lecture réussie ; of_refresh et F5 le retentent tout de suite |
REASON_UNREADABLE | Tout autre refus du shell : as_message de ue_error en donne le texte |
REASON_DEMO_LIMIT | Mode démonstration : au-delà des nœuds dessinés par niveau |
Clavier et souris #
- Clic sur un nœud : il est sélectionné (
ue_selected, jamais une seconde fois pour le nœud déjà sélectionné) ; sur son chevron : il s'ouvre ou se ferme ; double-clic :ue_activated, et une branche s'ouvre ou se ferme ; clic droit : le nœud est sélectionné, puisue_node_rclicked. - Haut / Bas : le nœud précédent, le suivant ; Début / Fin : le premier, le dernier ; Page haut / Page bas : d'un écran. Ctrl + Haut / Bas fait défiler sans changer la sélection.
- Droite ouvre le nœud, puis descend sur son premier enfant ; Gauche le ferme, puis remonte au parent — inversées dans une application de droite à gauche. Retour arrière remonte au parent ;
*du pavé numérique ouvre le nœud et les branches déjà lues dessous. - Entrée :
ue_activated(et une branche s'ouvre ou se ferme) ; F5 relit la branche en main (of_refresh) ; touche du menu contextuel ou Maj + F10 :ue_node_rclicked. - Les premières lettres d'un nom, espace compris, sélectionnent le nœud affiché qui commence ainsi ; la même lettre tapée de nouveau passe au suivant.
Exemples #
Commencer ailleurs qu'au Bureau #
// Only the drives, nothing above them
uo_tree.is_root = u_pbt_shellexplorer.ROOT_COMPUTER
// Or somewhere the application already knows
uo_tree.is_root = "C:\Projects"
Ouvrir ce que l'utilisateur a validé #
// Event ue_activated : a double-click, or Enter
of_open_folder(as_path)
Dire pourquoi une branche ne s'ouvre pas #
// Event ue_error : test the reason, never the text of the shell
if as_reason = u_pbt_shellexplorer.REASON_TIMEOUT then
st_status.text = "The network folder " + as_path + " does not answer"
else
st_status.text = as_message
end if
Ouvrir votre menu sur un clic droit #
// The entries of the menu, once : uo_menu is a contextmenu of the window, and
// is_menu_path a string instance variable that keeps the folder right-clicked
uo_menu.of_add_item(/*keys*/ "open", /*text*/ "Open")
uo_menu.of_add_item(/*keys*/ "refresh", /*text*/ "Refresh")
// event ue_node_rclicked of uo_tree : (string as_path, long al_x, long al_y)
// The folder is selected first, as in the Explorer : the menu opens where the
// user clicked (from the keyboard, under the folder)
is_menu_path = as_path
uo_menu.of_show(/*x*/ al_x, /*y*/ al_y)
// event ue_item_selected of uo_menu : (string as_keys)
// The entry chosen acts on the folder right-clicked
choose case as_keys
case "open"
of_open_folder(is_menu_path)
case "refresh"
uo_tree.of_refresh(/*path*/ is_menu_path)
end choose
Bonnes pratiques #
- 🚨 Stockez
of_selected_key(), affichezof_selected_name(). Découper le chemin pour en tirer un libellé marche pourC:\Clientset affiche::{20D04FE0-…}pour Ce PC. - Laissez
ib_show_filesà faux tant que vous cherchez un dossier. Les fichiers rendent l'arbre illisible et sa lecture lente. - Prévoyez
ue_errordès la première version : un lecteur réseau déconnecté est le cas ordinaire, pas l'exception. Testezas_reason, jamais le texte :REASON_TIMEOUTdit qu'un partage ne répond pas dans toutes les langues de Windows. - Utilisez
ue_activated, pasue_selected, pour valider. Sélectionner, c'est regarder ; double-cliquer, c'est décider. - Relisez la branche qui a changé. Après avoir écrit dans un dossier,
of_refresh(chemin)relit ce dossier seul ;of_refresh()relit tout ce qui est ouvert — l'état est gardé, mais sur un partage réseau chaque branche ouverte coûte un aller-retour. - Un chemin de départ étroit vaut mieux qu'un arbre entier quand l'application sait déjà où elle travaille : partez de
C:\Projets, l'utilisateur n'a plus rien à chercher.
Hérité du socle commun #
Ces membres existent sur tous les composants visuels — ils ne sont pas propres à celui-ci. Ils sont détaillés une seule fois, dans les chapitres transverses ; cette table dit seulement où les lire.
| Membres | Rôle | Détaillé dans |
|---|---|---|
of_reset | Remettre le composant à zéro | 3.6 Remettre un composant à zéro : of_reset() |
of_register_shortcut · of_clear_shortcuts | Raccourcis clavier du composant | 3.5 Les raccourcis clavier |
of_is_created · of_is_ready · of_get_last_error | S'il est né, s'il est prêt, ce qui a échoué | 3.7 Diagnostic |
of_save_as_png · of_save_as_jpg | Exporter le rendu en image | 3.8 Exporter le rendu en image |
of_set_redraw | Grouper les modifications en un seul repaint | 3.10 Bonnes pratiques |
of_preload_icons | Icônes affichées sans délai | Affichage instantané : of_icon |
of_set_translation | Traduire un libellé du composant | 5.2 Adapter un libellé : of_set_translation |
of_focus_webview | Donner le focus au composant | 6.4 Clavier et focus |
of_print · of_print_to_pdf | Imprimer, ou écrire un PDF | 6.9 Imprimer |
of_set_property · of_get_property · of_component_name | Piloter une propriété par son nom | 3.1 Le moteur de propriétés |
is_accessible_name · is_accessible_description | Le nom et la description que dit un lecteur d'écran | 3.4 Propriétés et events optionnels |
Deux aides ne sont pas héritées : of_icon et of_escape_markup vivent sur n_pbt_utils. Déclarez-en une — n_pbt_utils lnv_utils, rien à créer — et appelez-les dessus.