IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Delphi Discussion :

Utiliser le menu contextuel de l'explorateur de fichier


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 063
    Par défaut Utiliser le menu contextuel de l'explorateur de fichier
    Bonjour,

    Dans un composant perso (pour la VCL), je voudrais y voir le menu contextuel de l'explorateur de fichier, et pas celui par défaut proposé par Delphi, auriez-vous une idée de comment le récupérer et l'exploiter ?

    Merci d'avances de vos retours...

  2. #2
    Membre Expert
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 704
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 704
    Par défaut
    Moi, pour afficher le menu système sur un fichier, j'avais trouvé ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DisplayContextMenuForFile(Application.MainForm.Handle, MonFichier);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure DisplayContextMenuForFile(ApplicationMainFormHandle: THandle; szFileName: String);
    var
       ShellFolder: IShellFolder;
       Pidl: pItemIDList;
    begin
       _ApplicationMainFormHandle := ApplicationMainFormHandle;
     
       Pidl := SHGetIDListFromPath(szFileName, ShellFolder);
       if Assigned(Pidl) then
          ContextMenuForFile(ShellFolder, Pidl);
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    function SlashDirName(szDir: String): String;
    var
       s: String;
       bRootDir: Boolean;
    begin
       if szDir <> '' then
       begin
          s := szDir;
          bRootDir := ((Length(s) = 3) and (S[2] = ':')) or (s = '\');
          if not bRootDir then
             if s[Length(s)] <> '\' then
                s := s + '\';
          Result := s;
       end;
    end;
     
    function SHGetIDListFromPath(Path: TFileName; var ShellFolder: IShellFolder): pItemIDList;
    var 
       TempPath, NextDir: TFileName; 
       nSlashPos, nScanParam: Integer;
       Folder, subFolder: IShellFolder; 
       PIDL, PIDLbase: PItemIDList; 
       ParseStruct: TStrRet; 
       szParseName: String;
       EList: IEnumIDList; 
       DidGet: ULONG; 
    begin
       SHGetDesktopFolder(Folder);
       SHGetSpecialFolderLocation(0, CSIDL_DRIVES, PIDLbase);
     
       OLECheck(Folder.BindToObject(PIDLbase, nil, IID_IShellFolder, Pointer(SubFolder)));
       TempPath := Path;
       NextDir := '';
     
       //.Enumerate the path one directory at a time.
       while Length(TempPath) > 0 do
       begin
          nSlashPos := Pos('\', TempPath);
          if nSlashPos > 0 then
          begin
             if Pos(':', TempPath) > 0 then
                NextDir := Copy(TempPath, 1, 3)
             else
                NextDir := SlashDirName(NextDir) + Copy(TempPath, 1, nSlashPos - 1);
             TempPath := Copy(TempPath, nSlashPos + 1, Length(TempPath));
          end
          else
          begin
             if NextDir = '' then
                NextDir:=TempPath
             else
                NextDir := SlashDirName(NextDir) + TempPath;
             TempPath := '';
          end;
     
          Pidl := PidlBase;
          nScanParam := SHCONTF_FOLDERS or SHCONTF_INCLUDEHIDDEN;
          if (NextDir = Path) and (not DirectoryExists(Path)) then
             nScanParam := nScanParam or SHCONTF_NONFOLDERS;
     
          if S_OK = SubFolder.EnumObjects(0, nScanParam, EList) then
             while S_OK = EList.Next(1, pidl, DidGet) do
             begin
                OLECheck(SubFolder.GetDisplayNameOf(PIDL, SHGDN_FORPARSING, ParseStruct));
                case ParseStruct.uType of
                   STRRET_CSTR: szParseName := ParseStruct.cStr;
                   STRRET_WSTR: szParseName := WideCharToString(ParseStruct.pOleStr);
                   STRRET_OFFSET: szParsename := PChar(DWORD(Pidl) + ParseStruct.uOffset);
                end;
                if UpperCase(szParsename) = UpperCase(NextDir) then
                   Break;
             end
             else
             begin
                Folder := nil;
                Result := nil;
                Exit;
             end;
     
          if DidGet = 0 then
          begin
             Folder := nil;
             Result := nil;
             Exit;
          end;
          PIDLBase := Pidl;
          Folder := subFolder;
     
          //.As best as we can, determine whether or not this is a file.
          //.If so then we cannot bind it to the ShellFolder (hence "folder".) 
          if not FileExists(NextDir) then
             OLECheck(Folder.BindToObject(Pidl, nil, IID_IShellFolder, Pointer(SubFolder)));
       end;
     
       ShellFolder := Folder;
       if ShellFolder = nil then
          Result := nil
       else
          Result := Pidl;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    procedure ContextMenuForFile(Folder: IShellFolder; Pidl: pItemIDList);
    var
       aContextMenu: IContextMenu;
       aPrgOut: Pointer;
       aPopup: HMENU;
       nCmd: Integer;
       aCmdInfo: TCMInvokeCommandInfo;
       //    MenuInfo: TMenuItemInfo;
       //    t, ItemCount: integer;
       //    buf: array[0..80] of Char;
       Where: TPoint;
    begin 
       GetCursorPos(Where);
       aPrgOut := nil; 
       OLECheck(Folder.GetUIObjectOf(_ApplicationMainFormHandle, 1, Pidl, IID_IContextMenu, aPrgOut, Pointer(aContextMenu)));
       aPopup := CreatePopUpMenu;
       if aPopup = 0 then
          Exit;
     
       try
          OLECheck(aContextMenu.QueryContextMenu(aPopup, 0, 1, $7FFF, CMF_NORMAL));
          nCmd := Integer(TrackPopupMenuEx(aPopup, TPM_LEFTALIGN or TPM_RETURNCMD or TPM_RIGHTBUTTON or TPM_HORIZONTAL or TPM_VERTICAL, Where.X, Where.Y, _ApplicationMainFormHandle, nil));
          if nCmd <> 0 then
          begin
             Fillchar(aCmdInfo, Sizeof(aCmdInfo), 0);
             with aCmdInfo do
             begin
                cbSize := SizeOf(TCMInvokeCommandInfo);
                hwnd := _ApplicationMainFormHandle;
                lpVerb := MakeIntResource(nCmd - 1);
                nShow := SW_SHOWNORMAL;
             end;
     
             try
                aContextMenu.InvokeCommand(aCmdInfo);
             except
                raise Exception.Create('Erreur :  le menu système de ce fichier ne peut pas être créé !');
             end;
          end;
       finally
          DestroyMenu(aPopup);
       end;
    end;
    Avec ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    uses Windows, SysUtils, ShlObj, ComObj, Dialogs;
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. :bug: ___ "http://club.developpez.com/regles/#LIII-A"Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.3 Entreprise - Visual studio 2022
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.7)

  3. #3
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 063
    Par défaut
    Merci de ton retours, je vais tester ton code !


  4. #4
    Membre chevronné Avatar de der§en
    Homme Profil pro
    Bretagne
    Inscrit en
    Septembre 2005
    Messages
    1 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bretagne
    Secteur : Industrie

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 063
    Par défaut
    J'ai pas compris comment tu l'associes au contextmenu ?

  5. #5
    Membre Expert
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 704
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste-programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 704
    Par défaut
    Si mes souvenirs sont bons, il suffit juste d'un appel à DisplayContextMenuForFile(Application.MainForm.Handle, MonFichier); pour faire apparaitre le menu système du fichier donné.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. :bug: ___ "http://club.developpez.com/regles/#LIII-A"Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.3 Entreprise - Visual studio 2022
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.7)

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 086
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    Evidemment, si tu veux le Menu du Shell dans le deux cas, il faut un fichier (ou dossier) puisqu'il le Menu Contextuel est relatif à l'élément :
    DesignTime - Peut-être le fichier DPR si tu en trouves le nom (sinon le dossier Documents ou le CurrentDir)
    RunTime - Peut-être l'Exe ou son Dossier Parent, à quoi veux-tu lié le Context Menu, un fichier déjà ouvert dans un éditeur (ton programme serait donc un éditeur de fichier dans ce cas, il comprend peut-être un TShellTreeView/TShellListView qui affiche déjà une liste de fichier, c'est là que tu as besoin du clic-droit)


    Si c'est un composant et le menu en DesignTime faut lui faire un TComponentEditor (voire RegisterComponentEditor) et lui ajouter un Menu GetVerbCount/GetVerb
    L'appel de DisplayContextMenuForFile sera dans ExecuteVerb


    Si c'est en RunTime, tu gère le Menu dynamiquement, ajout du TMenuItem nécessaire* (Faut juste le PopupMenu attaché à la propriété Menu si c'est bien un TControl et non un TComponent)
    * C'est quoi le but ? avoir un explorateur via clic-droit, tu ne veux quand même pas faire la liste des fichiers/dossiers comme TMenuItem ?

    Tu peux ajouter utiliser OnContextPopup



    Faudrait mieux expliquer le besoin
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

Discussions similaires

  1. Réponses: 13
    Dernier message: 21/03/2017, 21h09
  2. Réponses: 22
    Dernier message: 21/01/2016, 12h02
  3. Réponses: 8
    Dernier message: 17/04/2012, 17h05
  4. Réponses: 1
    Dernier message: 06/02/2011, 22h03
  5. utiliser le menu contextuel de IE (Export to excell)
    Par cortex024 dans le forum ASP.NET
    Réponses: 1
    Dernier message: 16/05/2007, 16h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo