7
votes

Comment obtenir le PIDL d'un ishellfolder

Si j'ai un ishellfolder Pointeur d'interface. Comment puis-je obtenir son PIDL?

Je peux voir comment énumérer ses enfants, et je peux voir comment l'utiliser pour comparer deux enfants. Mais comment puis-je obtenir son propre PIDL?

Je demande parce que j'aimerais savoir:

est-ce ishellfolder == un autre iShellfolder

Je peux utiliser ishellfolder :: comp réserve () , mais je dois avoir les identifiants des deux dossiers.


0 commentaires

5 Réponses :


6
votes

J'ai constaté que vous pouvez interroger un Ishellfolder pour son iPersistColder2, qui a GetCurfolder (), qui renvoie son PIDL absolu. Je pourrais alors simplement utiliser l'IShellfolder pour le bureau pour les comparerids () pour déterminer s'ils sont égaux. J'ai trouvé les contours de ceci en regardant shgetidlistfromObject . Je ne pouvais pas simplement utiliser cette fonction, parce que sa Vista, et j'ai besoin de la compatibilité XP.

Voici un croquis de la façon dont il fonctionne (en supposant que vous avez un ifolder_desktop, et ifolder_other, qui sont des pointeurs IShellfolder. PIDL est un simple assistant qui Assure que les idologistes sont traitées correctement): p> xxx pré>

au cas où n'importe qui est intéressé par ma classe PIDL simple: P>

class Pidl
{
public:
    // create empty
    Pidl() : m_pidl(NULL) { }

    // create one of specified size
    explicit Pidl(size_t size) : m_pidl(Pidl_Create(size)) {}

    // create a copy of a given PIDL
    explicit Pidl(const ITEMIDLIST * pidl) : m_pidl(Pidl_Copy(pidl)) {}

    // create an absolute PIDL from a parent + child
    Pidl(const ITEMIDLIST_ABSOLUTE * pParent, const ITEMIDLIST_RELATIVE * pChild) : m_pidl(Pidl_Concatenate(pParent, pChild)) { }

    // return our PIDL for general use (but retain ownership of it)
    operator const ITEMIDLIST * () { return m_pidl; }

    // return a pointer to our pointer, for use in functions that assign to a PIDL
    operator ITEMIDLIST ** () 
    {
        free();
        return &m_pidl; 
    }

    // release ownership of our PIDL
    ITEMIDLIST * release() 
    { 
        ITEMIDLIST * pidl = m_pidl;
        m_pidl = NULL;
        return pidl;
    }

    void free()
    {
        if (m_pidl)
            //Pidl_Free(m_pidl);
            ILFree(m_pidl);
    }

    // automatically free our pidl (if we have one)
    ~Pidl()
    {
        free();
    }

private:
    ITEMIDLIST * m_pidl;
};


0 commentaires

1
votes

La réponse de Mordachai pourrait être correcte, mais pour moi, cette requête n'a aucun sens sur deux fronts:

  1. Je ne crois pas qu'il existe un document publié indiquant qu'un IShellfolder ne peut avoir qu'un seul parent. Il pourrait y avoir plusieurs façons de tout dossier shell. Le panneau de commande est accessible via mon ordinateur, via le menu Démarrer et n'importe où dans le système de fichiers que vous créez un Junction le point. Il semble que l'intention orgénale des équipes de shell était, étant donné une instance Ishellfolder, il ne devrait pas importer d'utilisateurs externes ce que son emplacement arbitraire est arrivé.

  2. plus, toute application qui instancie un ishellfolder sûrement a fait de sorte d'avoir une connaissance d'une PIDL. Si votre application se souciait de la voie à un iShellfolder, cela avait déjà cette information. Comment l'avez-vous perdu? (Et pourquoi l'équipe Shell devrait-elle ajouter une méthode pour aider les applications à garder une trace de leurs propres données?)


2 commentaires

1. Vrai, mais le système de fichiers est la vérité sous-jacente pour la plupart des objets de l'espace Shell. Et bien qu'il soit possible d'avoir plusieurs liens, jonctions, etc. à un dossier donné, il ne peut y avoir qu'un seul dossier parent. C'est vrai par définition du système de fichiers. Cela a toujours été ainsi, et il y a SHBindtoparent de corroborer cette vérité. 2. Pas ça. On peut instancer un Ishellfolder directement de Shgetdesktopfolder. En tout cas, il s'agit souvent de systèmes conçus qui ne peuvent aller que d'une manière qui échoue finalement. La capacité de convertir de l'un à l'autre est plus flexible et robuste.


1. Donc, si certains systèmes de fichiers ont des limites.L'apace de noms de shell a été conçu pour exprimer l'affaire plus générale. 2. Merci d'avoir souligné le cas spécial. Très intelligent.



8
votes

Qu'est-ce que Chris ou Mordechai écrit sur le n ° 1 est de toute façon pas au point. La question ne concerne pas les objets de l'espace de noms shell, mais sur des objets ayant une interface ishellfolder . Possession d'un IShellfolder L'interface ne signifie pas elle-même une présence dans l'espace de noms de shell. La question initiale est mal formée, dans la mesure où elle suppose qu'un objet avec une interface iShellfolder doit avoir "sa propre PIDL" .

Le meilleur que vous puissiez faire, je pense, est que Mordechai suggère:

  • Voir si l'objet dispose également d'un IPERSISTFolder2 interface

    Le but de cette interface est de corriger l'objet dans l'espace de noms de shell, ce qui fait tourner le dossier persistable. Plutôt que d'en déduire de toute absence de documentation publiée, examinez ce que Microsoft dit en réalité le iPersistFolder et IPERSISTFolder2 interfaces et la initialisée et GetCurFolder Méthodes. Plus particulièrement:

    Vous devez implémenter cette interface pour que l'élément d'objet de l'objet de dossier Shell puisse être récupéré.

    sur # 2, j'ai peur que Chris n'est certainement pas correct. Un ishellfolder peut certainement être obtenu sans PIDL. Le panneau de commande, que Chris introduit pour le n ° 1, fournit un contre-exemple prêt au n ° 2. Il suffit de nourrir clsid_controlpanel et iid_ishellfolder à coCreateInstance . Vous obtenez une instanciation parfaitement utilisable du panneau de commande sans jamais "avoir la connaissance d'un PIDL" .

    Il y a une poignée d'autres dossiers coquillés créateurs implémentés dans Shell32 et toute DLL peut configurer un nombre de personnes.


0 commentaires


0
votes

Comme indiqué avant qu'il puisse y avoir beaucoup de problèmes avec des dossiers spéciaux tels que Panneau de contrôle (je ne comprends toujours pas complètement) mais voici une solution simple pour les dossiers "normaux":

HRESULT get_pidl(IShellFolder * sf, LPITEMIDLIST * pidl)
{
    if (!sf || !pidl) return E_FAIL;

    wchar_t FolderName[MAX_PATH] = {0};
    STRRET strDispName; 

    sf->GetDisplayNameOf(NULL, SHGDN_FORPARSING, &strDispName); 
    StrRetToBuf(&strDispName, NULL, FolderName, (UINT)MAX_PATH);

    IShellFolder * desktop = nullptr;
    SHGetDesktopFolder(&desktop);

    ULONG cbEaten, atrib = 0;
    HRESULT hr = desktop->ParseDisplayName(NULL, nullptr, FolderName, &cbEaten, pidl, &atrib);
    desktop->Release();

    return hr;
}


0 commentaires