PBToolboxAI v5 ← Site

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 #

Userobjectu_pbt_shellexplorer
Sert àChoisir un dossier, ou naviguer, sans quitter l'application
PrincipeVous 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_selected vous 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éTypeDéfautRôle
is_rootstring""Où commence l'arbre (constantes ROOT_*). Vide = la racine du shell. Un chemin y commence à la place
ib_show_filesbooleanfalseAffiche 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_hiddenbooleanréglage de l'ExplorateurMontre 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_filterstring""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_enabledbooleantrueFaux : 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_stylestring""Style visuel du composant (constantes THEME_STYLE_*) ; vide = celui de l'application, suivi à chaque changement
is_theme_modestring""Variante claire ou sombre (constantes THEME_MODE_*) ; vide = celle de l'application, suivie à chaque changement
il_theme_accentlong-1Couleur d'accent de ce composant (-1 = l'accent de l'application, ou celui du thème)
is_tooltipstring""Info-bulle simple affichée au survol du composant
is_super_tooltip_titlestring""Titre de l'info-bulle enrichie (prend le pas sur is_tooltip)
is_super_tooltip_textstring""Texte de l'info-bulle enrichie (balisage riche accepté)
is_super_tooltip_imagestring""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éthodeRô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énementDé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 .dwg porte 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.

ConstanteCe qu'elle dit
REASON_NOT_FOUNDLe chemin n'existe pas
REASON_NOT_SHOWNLe 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_ROOTLe chemin n'est pas sous is_root
REASON_THE_ROOTLe chemin est la racine elle-même : ce n'est pas un nœud de l'arbre
REASON_NOT_A_BRANCHof_expand d'un fichier, ou d'un dossier sans enfant
REASON_ACCESS_DENIEDLe shell refuse : pas de droits
REASON_TIMEOUTPas 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_UNREADABLETout autre refus du shell : as_message de ue_error en donne le texte
REASON_DEMO_LIMITMode démonstration : au-delà des nœuds dessinés par niveau

Clavier et souris #


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 #

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.

MembresRôleDétaillé dans
of_resetRemettre le composant à zéro3.6 Remettre un composant à zéro : of_reset()
of_register_shortcut · of_clear_shortcutsRaccourcis clavier du composant3.5 Les raccourcis clavier
of_is_created · of_is_ready · of_get_last_errorS'il est né, s'il est prêt, ce qui a échoué3.7 Diagnostic
of_save_as_png · of_save_as_jpgExporter le rendu en image3.8 Exporter le rendu en image
of_set_redrawGrouper les modifications en un seul repaint3.10 Bonnes pratiques
of_preload_iconsIcônes affichées sans délaiAffichage instantané : of_icon
of_set_translationTraduire un libellé du composant5.2 Adapter un libellé : of_set_translation
of_focus_webviewDonner le focus au composant6.4 Clavier et focus
of_print · of_print_to_pdfImprimer, ou écrire un PDF6.9 Imprimer
of_set_property · of_get_property · of_component_namePiloter une propriété par son nom3.1 Le moteur de propriétés
is_accessible_name · is_accessible_descriptionLe nom et la description que dit un lecteur d'écran3.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.


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