Udostępnij za pośrednictwem


Implementowanie podstawowych interfejsów obiektów folderów

Procedura implementowania rozszerzenia przestrzeni nazw jest podobna do procedury dla dowolnego innego obiektu modelu obiektów składników procesu (COM). Wszystkie rozszerzenia muszą obsługiwać trzy podstawowe interfejsy, które zapewniają Eksploratorowi Windows podstawowe informacje potrzebne do wyświetlania folderów rozszerzenia w widoku drzewa. Jednak aby w pełni korzystać z funkcji Eksploratora Windows, rozszerzenie musi również uwidocznić jeden lub więcej opcjonalnych interfejsów, które obsługują bardziej zaawansowane funkcje, takie jak menu skrótów lub przeciąganie i upuszczanie, i udostępnia widok folderu.

W tym dokumencie omówiono sposób implementowania podstawowych i opcjonalnych interfejsów wywoływanych przez Eksploratora Windows w celu uzyskania informacji o zawartości rozszerzenia. Aby zapoznać się z omówieniem sposobu implementowania widoku folderu i dostosowywania Eksploratora Windows, zobacz Implementowanie widoku folderu.

Podstawowa implementacja i rejestracja

Jako serwer COM w procesie, twoja biblioteka DLL musi uwidocznić kilka standardowych funkcji i interfejsów:

Te funkcje i interfejsy są implementowane w taki sam sposób, jak w przypadku większości innych obiektów COM. Aby uzyskać szczegółowe informacje, zobacz dokumentację COM.

Rejestrowanie rozszerzenia

Podobnie jak we wszystkich obiektach COM, musisz utworzyć identyfikator klasy GUID (CLSID) dla tego rozszerzenia. Zarejestruj obiekt, tworząc podklucz HKEY_CLASSES_ROOT\CLSID, którego nazwa to CLSID twojego rozszerzenia. Biblioteka DLL powinna być zarejestrowana jako serwer przetwarzania i powinna określać model wątkowania apartamentów. Zachowanie folderu głównego rozszerzenia można dostosować, dodając różne podklucze i wartości do klucza CLSID rozszerzenia.

Kilka z tych wartości dotyczy tylko rozszerzeń z wirtualnymi punktami skrzyżowań. Te wartości nie mają zastosowania do rozszerzeń, których punkty połączenia są folderami systemu plików. Aby dowiedzieć się więcej, zobacz Określanie lokalizacji rozszerzenia przestrzeni nazw. Aby zmodyfikować zachowanie rozszerzenia za pomocą wirtualnego punktu skrzyżowania, dodaj co najmniej jedną z następujących wartości do klucza CLSID rozszerzenia:

  • ChceFORPARSING. Nazwa analizowania rozszerzenia z wirtualnym punktem połączenia zwykle ma postać ::{GUID}. Rozszerzenia tego typu zwykle zawierają elementy wirtualne. Jednak niektóre rozszerzenia, takie jak Moje dokumenty, faktycznie odpowiadają folderom systemu plików, mimo że mają wirtualne punkty połączenia. Jeśli rozszerzenie reprezentuje obiekty systemu plików w ten sposób, możesz ustawić wartość WantsFORPARSING. Eksplorator Windows zażąda nazwy parsowania folderu głównego, wywołując metodę IShellFolder::GetDisplayNameOf obiektu folderu z uFlags ustawionym na SHGDN_FORPARSING i pidl ustawionym na pojedynczy pusty wskaźnik na listę identyfikatorów elementów (PIDL). Pusta PIDL zawiera tylko terminator. Metoda powinna następnie zwrócić nazwę parsowania folderu głównego ::{identyfikator GUID}.
  • UkryjFolderVerbs. Czasowniki zarejestrowane w folderze HKEY_CLASSES_ROOT\ zwykle są skojarzone ze wszystkimi rozszerzeniami. Są one wyświetlane w menu skrótów rozszerzenia i mogą być wywoływane przez ShellExecute. Aby zapobiec skojarzeniu dowolnego z tych czasowników z rozszerzeniem, ustaw wartość HideFolderVerbs.
  • HideAsDelete. Jeśli użytkownik spróbuje usunąć rozszerzenie, Eksplorator Windows zamiast tego ukryje rozszerzenie.
  • HideAsDeletePerUser. Ta wartość ma taki sam efekt jak HideAsDelete, ale dla poszczególnych użytkowników. Rozszerzenie jest ukryte tylko dla tych użytkowników, którzy próbowali go usunąć. Rozszerzenie jest widoczne dla wszystkich innych użytkowników.
  • QueryForOverlay. Ustaw tę wartość, aby wskazać, że ikona folderu głównego może mieć nakładkę ikony. Obiekt folderu musi obsługiwać interfejs IShellIconOverlay. Zanim Eksplorator Windows wyświetli ikonę folderu głównego, zażąda ikony nakładki, wywołując jedną z dwóch metod IShellIconOverlay z pidlItem ustawionym jako pusty PIDL.

Pozostałe wartości i podklucze mają zastosowanie do wszystkich rozszerzeń:

  • Aby określić nazwę wyświetlaną folderu punktu połączenia rozszerzenia, ustaw domyślną wartość podklucza CLSID rozszerzenia na odpowiedni ciąg.
  • Gdy kursor najeżdża na folder, zwykle wyświetlana jest podpowiedź opisująca zawartość folderu. Aby podać etykietkę informacji dla folderu głównego rozszerzenia, utwórz wartość REG_SZ etykietki informacji dla klucza CLSID rozszerzenia i ustaw go na odpowiedni ciąg.
  • Aby określić niestandardową ikonę folderu głównego rozszerzenia, utwórz podklucz w podkluczu CLSID tego rozszerzenia, który będzie nosił nazwę DefaultIcon. Ustaw wartość domyślną DefaultIcon na wartość REG_SZ zawierającą nazwę pliku zawierającego ikonę, a następnie przecinek, a następnie znak minus, a następnie indeks ikony w tym pliku.
  • Domyślnie menu skrótów folderu głównego rozszerzenia będzie zawierać elementy zdefiniowane w obszarze HKEY_CLASSES_ROOT\Folder. Dodano elementy Usuń, Zmień nazwęi Właściwości, jeśli ustawiono odpowiednie flagi SFGAO_XXX. Możesz dodać inne elementy do menu skrótów folderu głównego lub zastąpić istniejące elementy, podobnie jak w przypadku typu pliku . Utwórz podklucz powłoki pod kluczem CLSID rozszerzenia i zdefiniuj polecenia zgodnie z opisem w "Rozszerzanie menu skrótów".
  • Jeśli potrzebujesz bardziej elastycznego sposobu obsługi menu skrótów folderu głównego, możesz zaimplementować program obsługi menu skrótów . Aby zarejestrować procedurę obsługi menu skrótów, utwórz klucz ShellEx w kluczu CLSID rozszerzenia. Zarejestruj identyfikator CLSID programu obsługującego, tak jak w przypadku konwencjonalnego tworzenia programów obsługi rozszerzeń powłoki.
  • Aby dodać stronę do arkusza właściwości folderu głównego, nadaj folderowi atrybut SFGAO_HASPROPSHEET i zaimplementuj program obsługi arkusza właściwości . Aby zarejestrować procedurę obsługi arkusza właściwości, utwórz klucz ShellEx w kluczu CLSID rozszerzenia. Zarejestruj identyfikator CLSID programu obsługi, tak jak w przypadku konwencjonalnych Tworzenie programów obsługi rozszerzeń powłoki.
  • Aby określić atrybuty folderu głównego, dodaj podklucz ShellFolder do podklucza CLSID rozszerzenia. Utwórz wartość atrybutów i ustaw ją na odpowiednią kombinację flag SFGAO_XXX.

W poniższej tabeli wymieniono niektóre często używane atrybuty folderów głównych.

Flaga Wartość Opis
SFGAO_FOLDER 0x20000000 Folder główny rozszerzenia zawiera co najmniej jeden element.
SFGAO_HASSUBFOLDER 0x80000000 Folder główny rozszerzenia zawiera co najmniej jeden podfolder. Eksplorator Windows umieści znak plus ( + ) obok ikony folderu.
SFGAO_CANDELETE 0x00000020 Folder główny rozszerzenia można usunąć przez użytkownika. Menu skrótów folderu będzie miało element Usuń. Tę flagę należy ustawić dla punktów skrzyżowań umieszczonych w jednym z folderów wirtualnych .
SFGAO_CANRENAME 0x00000010 Nazwa folderu głównego rozszerzenia może zostać zmieniona przez użytkownika. Menu skrótów folderu będzie miało pozycję Zmień nazwę.
SFGAO_HASPROPSHEET 0x00000040 Folder główny rozszerzenia ma Właściwości arkusz właściwości. Menu skrótów folderu będzie miało element właściwości . Aby udostępnić arkusz właściwości, należy zaimplementować program obsługi arkusza właściwości . Zarejestruj procedurę obsługi w kluczu CLSID rozszerzenia, zgodnie z wcześniejszym opisem.

 

W poniższym przykładzie pokazano wpis rejestru CLSID dla rozszerzenia o nazwie wyświetlanej "MyExtension". Rozszerzenie ma niestandardową ikonę zawartą w pliku DLL rozszerzenia z indeksem 1. Atrybuty SFGAO_FOLDER, SFGAO_HASSUBFOLDERi SFGAO_CANDELETE są ustawione.

HKEY_CLASSES_ROOT
   CLSID
      {Extension CLSID}
         (Default) = MyExtension
         InfoTip = Some appropriate text
      DefaultIcon
         (Default) = c:\MyDir\MyExtension.dll,-1
      InProcServer32
         (Default) = c:\MyDir\MyExtension.dll
         ThreadingModel = Apartment
      ShellFolder
         Attributes = 0xA00000020

Obsługa PIDLs

Każdy element w przestrzeni nazw powłoki musi mieć unikatowy kod PIDL. Eksplorator Windows przypisuje PIDL do folderu głównego i przekazuje tę wartość do rozszerzenia podczas inicjalizacji. Rozszerzenie jest następnie odpowiedzialne za przypisanie odpowiednio skonstruowanego identyfikatora PIDL do każdego ze swoich obiektów i dostarczenie tych identyfikatorów PIDLs do Eksploratora Windows na żądanie. Gdy powłoka używa kodu PIDL do identyfikowania jednego z obiektów rozszerzenia, rozszerzenie musi mieć możliwość interpretowania kodu PIDL i identyfikowania określonego obiektu. Rozszerzenie musi również przypisać nazwę wyświetlaną ,,i oraz nazwę analizowaną i do każdego obiektu. Ponieważ PIDL są używane przez praktycznie każdy interfejs folderu, rozszerzenia często implementują jednego menedżera PIDL w celu obsługi wszystkich tych zadań.

Termin PIDL jest skrótem od struktury ITEMIDLIST lub wskaźnika do takiej struktury, w zależności od kontekstu. Jak zadeklarowano, struktura ITEMIDLIST ma pojedynczy element członkowski, strukturę SHITEMID. Struktura ITEMIDLIST obiektu jest w rzeczywistości pakowaną tablicą dwóch lub więcej struktur SHITEMID. Kolejność tych struktur definiuje ścieżkę przez przestrzeń nazw w taki sam sposób, jak c:\MyDirectory\MyFile definiuje ścieżkę przez system plików. Zazwyczaj PIDL obiektu składa się z szeregu struktur SHITEMID, które odpowiadają folderom definiującym ścieżkę przestrzeni nazw, następnie struktura SHITEMID obiektu i terminator.

Terminator jest strukturą SHITEMID, z członkiem cb ustawionym na NULL. Terminator jest niezbędny, ponieważ liczba struktur SHITEMID w PIDL obiektu zależy od lokalizacji obiektu w przestrzeni nazw powłoki oraz punktu początkowego ścieżki. Ponadto rozmiar różnych SHITEMID struktur może się różnić. Po otrzymaniu identyfikatora PIDL nie masz prostego sposobu na określenie jego rozmiaru ani nawet całkowitej liczby struktur SHITEMID. Zamiast musisz "przechodzić przez" pakowaną tablicę, strukturę po strukturze, aż dotrzesz do terminatora.

Aby utworzyć PIDL, twoja aplikacja musi:

  1. Utwórz strukturę SHITEMID dla każdego z jego obiektów.
  2. Złóż odpowiednie struktury SHITEMID w PIDL.

Tworzenie struktury SHITEMID

Struktura obiektu SHITEMID jednoznacznie identyfikuje obiekt w jego folderze. W rzeczywistości typ PIDL używany przez wiele metod IShellFolder składa się tylko ze struktury SHITEMID obiektu , a następnie terminatora. Definicja struktury SHITEMID jest następująca:

typedef struct _SHITEMID { 
    USHORT cb; 
    BYTE   abID[1]; 
} SHITEMID, * LPSHITEMID;

abID członek jest identyfikatorem obiektu. Ponieważ długość abID nie jest zdefiniowana i może się różnić, element cb jest ustawiony na rozmiar SHITEMID struktury w bajtach.

Ponieważ ani długość, ani zawartość abID nie jest ustandaryzowana, możesz użyć dowolnego schematu do przypisania wartości abID swoim obiektom. Jedynym wymaganiem jest to, że nie można mieć dwóch obiektów w tym samym folderze o identycznych wartościach. Jednak ze względu na wydajność strukturaSHITEMIDpowinna być DWORD -aligned. Innymi słowy, skonstruuj wartości abID takie, że cb jest całkowitą wielokrotnością 4.

Zazwyczaj abID wskazuje strukturę zdefiniowaną przez rozszerzenie. Oprócz identyfikatora obiektu ta struktura jest często używana do przechowywania różnych powiązanych informacji, takich jak typ lub atrybuty obiektu. Obiekty folderów rozszerzenia mogą następnie szybko wyodrębnić informacje z kodu PIDL zamiast wykonywać względem niego zapytania.

Notatka

Jednym z najważniejszych aspektów projektowania struktury danych dla PIDL jest zapewnienie, żeby struktura była trwała i przenośna. W kontekście PIDL, znaczenie tych terminów jest następujące:

  • Trwałość. System często umieszcza PIDLs w różnych typach długoterminowego przechowywania, takich jak pliki skrótów. Następnie można odzyskać te PIDL-e z magazynu później, na przykład po ponownym uruchomieniu systemu. Plik PIDL, który został odzyskany z magazynu, musi być nadal prawidłowy i zrozumiały dla Twojego rozszerzenia. To wymaganie oznacza na przykład, że nie należy używać wskaźników ani uchwytów w strukturze PIDL. PIDL-e zawierające ten typ danych będą zwykle bez znaczenia, gdy system w przyszłości odzyska je z pamięci.
  • Przenośne. PIDL musi zachować swoje znaczenie podczas przenoszenia z jednego komputera na drugi. Na przykład kod PIDL można zapisać do pliku skrótów, skopiować na dyskietkę i przetransportować do innego komputera. Ten plik PIDL powinien nadal mieć znaczenie dla rozszerzenia uruchomionego na drugim komputerze. Aby na przykład upewnić się, że PIDL-e są transportowalne, należy jawnie użyć znaków ANSI lub Unicode. Unikaj typów danych, takich jak TCHAR lub LPTSTR. Jeśli używasz tych typów danych, kod PIDL utworzony na komputerze z wersją Unicode rozszerzenia nie będzie czytelny przez wersję ANSI tego rozszerzenia uruchomionego na innym komputerze.

 

Poniższa deklaracja przedstawia prosty przykład struktury danych.

typedef struct tagMYPIDLDATA {
  USHORT cb;
  DWORD dwType;
  WCHAR wszDisplayName[40];
} MYPIDLDATA, *LPMYPIDLDATA;

Element członkowski cb jest ustawiony na rozmiar struktury MYPIDLDATA. Ten członek stanowi prawidłową strukturę SHITEMID dla MYPIDLDATA samą w sobie. Pozostałe elementy członkowskie są równoważne członkowi abID struktury SHITEMID i przechowują dane prywatne. Element członkowski dwType jest wartością zdefiniowaną przez rozszerzenie, która wskazuje typ obiektu. W tym przykładzie dwType jest ustawiony na TRUE dla folderów i FALSE w przeciwnym razie. Ten element członkowski umożliwia na przykład szybkie określenie, czy obiekt jest folderem, czy nie. Element wszDisplayName zawiera nazwę wyświetlaną obiektu. Ponieważ nie przypiszesz tej samej nazwy wyświetlanej do dwóch różnych obiektów w tym samym folderze, nazwa wyświetlana również służy jako identyfikator obiektu. W tym przykładzie wszDisplayName jest ustawiona na 40 znaków, aby zagwarantować, że struktura SHITEMID będzie DWORD-aligned. Aby ograniczyć rozmiar PIDLs, możesz zamiast tego użyć tablicy znaków o zmiennej długości i odpowiednio dostosować wartość cb. Dopełnij ciąg znaków wystarczającą ilością znaków "\0", aby zachować wyrównanie struktury DWORD. Inne elementy członkowskie, które mogą być przydatne do umieszczenia w strukturze, obejmują rozmiar, atrybuty lub nazwę parsowania obiektu.

Konstruowanie PIDL

Po zdefiniowaniu SHITEMID struktur dla obiektów, można ich użyć do utworzenia pliku PIDL. PIDLs można tworzyć w różnych celach, ale większość zadań używa jednego z dwóch typów PIDL. Najprostszy, jednopoziomowy kod PIDL, identyfikuje obiekt względem jego folderu nadrzędnego. Ten typ PIDL jest używany przez wiele metod IShellFolder. Jednopoziomowy kod PIDL zawiera strukturę SHITEMID obiektu, a następnie terminator. W pełni kwalifikowany identyfikator PIDL definiuje ścieżkę przez hierarchię przestrzeni nazw od pulpitu do obiektu. Ten typ PIDL rozpoczyna się na pulpicie i zawiera jedną strukturę SHITEMID dla każdego folderu w ścieżce, a następnie obiekt i terminator. W pełni kwalifikowany PIDL jednoznacznie identyfikuje obiekt w całej przestrzeni nazw powłoki systemu.

Najprostszym sposobem konstruowania pliku PIDL jest praca bezpośrednio ze strukturą ITEMIDLIST. Utwórz strukturę ITEMIDLIST, ale przydziel wystarczającą ilość pamięci do przechowywania wszystkich struktur SHITEMID. Adres tej struktury będzie wskazywać początkową strukturę SHITEMID. Zdefiniuj wartości dla członków tej początkowej struktury, a następnie dołącz tyle dodatkowych struktur SHITEMID, ile potrzeba, w odpowiedniej kolejności. Poniższa procedura przedstawia sposób tworzenia jednopoziomowego PIDL. Zawiera ona dwie struktury SHITEMID — struktury MYPIDLDATA, po której następuje terminator:

  1. Użyj funkcji CoTaskMemAlloc, aby przydzielić pamięć dla PIDL. Przydziel wystarczającą ilość pamięci dla danych prywatnych oraz USHORT (dwa bajty) dla terminatora. Rzutuj wynik na LPMYPIDLDATA.
  2. Ustaw element członkowski cb pierwszej struktury MYPIDLDATA na rozmiar tej struktury. W tym przykładzie można ustawić cb na sizeof(MYPIDLDATA). Jeśli chcesz użyć struktury o zmiennej długości, musisz obliczyć wartość cb.
  3. Przypisz odpowiednie wartości do prywatnych członków danych.
  4. Oblicz adres następnej struktury SHITEMID. Przekształć adres bieżącej struktury MYPIDLDATA na LPBYTE i dodaj tę wartość do liczby cb określoną w kroku 3.
  5. W tym przypadku terminatorem jest kolejna struktura SHITEMID. Ustaw członka struktury cb na zero.

Dla dłuższych PIDL przydziel wystarczającą ilość pamięci i powtórz kroki od 3 do 5 dla każdej dodatkowej struktury SHITEMID.

Poniższa przykładowa funkcja przyjmuje typ obiektu i nazwę wyświetlaną oraz zwraca jednopoziomowy kod PIDL obiektu. Funkcja zakłada, że nazwa wyświetlana, w tym jej zakończenie znaku null, nie przekracza liczby znaków zadeklarowanych dla struktury MYPIDLDATA. Jeśli to założenie okaże się błędne, funkcja StringCbCopyW spowoduje obcięcie nazwy wyświetlanej. Zmienna g_pMalloc jest wskaźnikiem IMalloc utworzonym gdzie indziej i przechowywanym w zmiennej globalnej.

LPITEMIDLIST CreatePIDL(DWORD dwType, LPCWSTR pwszDisplayName)
{
    LPMYPIDLDATA   pidlOut;
    USHORT         uSize;

    pidlOut = NULL;

    //Calculate the size of the MYPIDLDATA structure.
    uSize = sizeof(MYPIDLDATA);

    // Allocate enough memory for the PIDL to hold a MYPIDLDATA structure 
    // plus the terminator
    pidlOut = (LPMYPIDLDATA)m_pMalloc->Alloc(uSize + sizeof(USHORT));

    if(pidlOut)
    {
       //Assign values to the members of the MYPIDLDATA structure
       //that is the PIDL's first SHITEMID structure
       pidlOut->cb = uSize;
       pidlOut->dwType = dwType;
       hr = StringCbCopyW(pidlOut->wszDisplayName, 
                          sizeof(pidlOut->wszDisplayName), pwszDisplayName);
       
       // TODO: Add error handling here to verify the HRESULT returned 
       // by StringCbCopyW.

       //Advance the pointer to the start of the next SHITEMID structure.
       pidlOut = (LPMYPIDLDATA)((LPBYTE)pidlOut + pidlOut->cb);

       //Create the terminating null character by setting cb to 0.
       pidlOut->cb = 0;
    }

    return pidlOut;

W pełni kwalifikowana ścieżka PIDL musi mieć struktury SHITEMID dla każdego obiektu od pulpitu do twojego obiektu. Rozszerzenie odbiera w pełni kwalifikowany kod PIDL dla folderu głównego, gdy powłoka wywołuje IPersistFolder::Initialize. Aby skonstruować w pełni kwalifikowany kod PIDL dla obiektu, weź kod PIDL przypisany przez powłokę do folderu głównego, i dołącz struktury SHITEMID, które są potrzebne, aby przejść od folderu głównego do obiektu.

Interpretowanie PIDL

Gdy powłoka lub aplikacja wywołuje jeden z interfejsów rozszerzenia w celu żądania informacji o obiekcie, zwykle zidentyfikuje obiekt przez PIDL. Niektóre metody, takie jak IShellFolder::GetUIObjectOf, używają PIDL-i względnych do folderu nadrzędnego i są łatwe do zrozumienia. Jednak twoje rozszerzenie prawdopodobnie również otrzyma w pełni kwalifikowane PIDL. Menedżer PIDL musi następnie określić, do których obiektów odwołuje się PIDL.

Zadanie kojarzenia obiektu z w pełni kwalifikowaną nazwą PIDL jest skomplikowane, ponieważ jedna lub więcej z początkowych struktur SHITEMID w PIDL może należeć do obiektów znajdujących się poza twoim rozszerzeniem w przestrzeni nazw powłoki. Nie masz możliwości interpretacji znaczenia elementu abID tych struktur. To, co musi zrobić rozszerzenie, to przeglądać listę struktur SHITEMID, dopóki nie osiągniesz struktury odpowiadającej folderowi głównemu. Od tego czasu będziesz wiedział, jak interpretować informacje w strukturach SHITEMID.

Aby przejść PIDL, weź pierwszą cb wartość i dodaj ją do adresu PIDL, aby przesunąć wskaźnik do początku następnej struktury SHITEMID. Następnie będzie wskazywać na cb elementu członkowskiego, którego można użyć, aby przejść wskaźnik na początek następnej SHITEMID struktury itd. Za każdym razem, gdy przesuwasz wskaźnik, sprawdź strukturę SHITEMID, aby określić, czy osiągnąłeś korzeń przestrzeni nazw swojego rozszerzenia.

Implementowanie interfejsów podstawowych

Podobnie jak w przypadku wszystkich obiektów COM implementacja rozszerzenia jest w dużej mierze kwestią implementacji kolekcji interfejsów. W tej sekcji omówiono trzy podstawowe interfejsy, które muszą być implementowane przez wszystkie rozszerzenia. Są one używane do inicjowania i udostępniania Eksploratorowi Windows podstawowe informacje o zawartości rozszerzenia. Te interfejsy oraz widok folderu są wymagane dla rozszerzenia funkcjonalnego. Jednak aby w pełni wykorzystać funkcje Eksploratora Windows, większość rozszerzeń implementuje również jeden lub więcej opcjonalnych interfejsów.

Interfejs IPersistFolder

Interfejs IPersistFolder jest wywoływany w celu zainicjowania nowego obiektu folderu. Metoda IPersistFolder::Initialize przypisuje w pełni kwalifikowany PIDL do nowego obiektu. Zapisz ten plik PIDL do późniejszego użycia. Na przykład obiekt folderu musi używać tego identyfikatora PIDL do konstruowania w pełni kwalifikowanych list PIDL dla elementów podrzędnych obiektu. Twórca obiektu folderu może również wywołać IPersist::GetClassID, aby zażądać identyfikatora CLSID obiektu.

Zazwyczaj obiekt folderu jest tworzony i inicjowany przez IShellFolder::BindToObject metody folderu nadrzędnego. Jednak gdy użytkownik przechodzi do rozszerzenia, Eksplorator Windows tworzy i inicjuje obiekt folderu głównego rozszerzenia. Kod PIDL, który obiekt folderu głównego odbiera za pośrednictwem IPersistFolder::Initialize, zawiera ścieżkę z pulpitu do folderu głównego, która jest potrzebna do skonstruowania w pełni kwalifikowanych list PIDL dla rozszerzenia.

IShellFolder interfejs

Powłoka traktuje rozszerzenie jako hierarchicznie uporządkowaną kolekcję obiektów folderu. Interfejs IShellFolder jest rdzeniem dowolnej implementacji rozszerzenia. Reprezentuje obiekt folderu i udostępnia Eksploratorowi Windows wiele informacji potrzebnych do wyświetlenia zawartości folderu.

IShellFolder jest zazwyczaj jedynym interfejsem folderu innym niż IPersistFolder, który jest bezpośrednio udostępniany przez obiekt folderu. Podczas gdy Eksplorator Windows używa różnych wymaganych i opcjonalnych interfejsów do uzyskiwania informacji o zawartości folderu, uzyskuje wskaźniki do tych interfejsów za pośrednictwem IShellFolder.

Eksplorator Windows uzyskuje identyfikator CLSID folderu głównego rozszerzenia na różne sposoby. Aby uzyskać szczegółowe informacje, zobacz Określanie lokalizacji rozszerzenia przestrzeni nazw lub Wyświetlanie widoku Self-Contained rozszerzenia przestrzeni nazw. Eksplorator Windows następnie używa tego identyfikatora CLSID do utworzenia i zainicjowania wystąpienia folderu głównego i wykonywania zapytań o interfejs IShellFolder. Rozszerzenie tworzy obiekt folderu, który reprezentuje folder główny, i zwraca interfejs IShellFolder tego obiektu. Większość pozostałej części interakcji między rozszerzeniem a Eksploratorem Windows odbywa się za pośrednictwem IShellFolder. Eksplorator Windows wywołuje IShellFolder:

  • Zażądaj obiektu, który może wyliczyć zawartość folderu głównego.
  • Uzyskaj różne typy informacji o zawartości folderu głównego.
  • Zażądaj obiektu, który uwidacznia jeden z opcjonalnych interfejsów. Te interfejsy można następnie przeszukiwać o dodatkowe informacje, takie jak ikony lub menu skrótów.
  • Zażądaj obiektu folderu reprezentującego podfolder folderu głównego.

Gdy użytkownik otworzy podfolder folderu głównego, Eksplorator Windows wywołuje IShellFolder::BindToObject. Rozszerzenie tworzy i inicjuje nowy obiekt folderu reprezentujący podfolder i zwraca jego interfejs IShellFolder. Eksplorator Windows wywołuje ten interfejs dla różnych typów informacji, dopóki użytkownik nie zdecyduje się przejść gdzie indziej w przestrzeni nazw powłoki lub zamknąć Eksploratora Windows.

W pozostałej części tej sekcji krótko omówiono ważniejsze metody IShellFolder oraz sposób ich implementowania.

EnumObjects

Przed wyświetleniem zawartości folderu w widoku drzewa Eksplorator Windows musi najpierw określić, który folder zawiera, wywołując metodę IShellFolder::EnumObjects. Ta metoda tworzy standardowy obiekt wyliczenia OLE, który uwidacznia interfejs IEnumIDList i zwraca wskaźnik tego interfejsu. Interfejs IEnumIDList umożliwia Eksploratorowi Windows uzyskanie PIDL wszystkich obiektów zawartych przez folder. Te listy PIDLs są następnie używane do uzyskiwania informacji o obiektach zawartych w folderze. Aby uzyskać więcej informacji, zobacz interfejs IEnumIDList .

Notatka

Metoda IEnumIDList::Next powinna zwracać tylko PIDLe, które są względne do folderu nadrzędnego. PIDL powinien zawierać tylko strukturę SHITEMID obiektu, a następnie terminator.

 

CreateViewObject

Przed wyświetleniem zawartości folderu Eksplorator Windows wywołuje tę metodę, aby zażądać wskaźnika do interfejsu IShellView. Ten interfejs jest używany przez Eksploratora Windows do zarządzania widokiem folderu. Utwórz obiekt widoku folderu i zwróć jego interfejs IShellView.

Metoda IShellFolder::CreateViewObject jest również wywoływana w celu zażądania jednego z opcjonalnych interfejsów, takich jak IContextMenu, dla samego folderu. Implementacja tej metody powinna utworzyć obiekt, który uwidacznia żądany interfejs i zwraca wskaźnik interfejsu. Jeśli Eksplorator Windows potrzebuje opcjonalnego interfejsu dla jednego z obiektów zawartych w folderze, wywoła IShellFolder::GetUIObjectOf.

GetUIObjectOf

Chociaż podstawowe informacje o zawartości folderu są dostępne za pośrednictwem metod IShellFolder, rozszerzenie może również udostępnić Eksploratorowi Windows różnego rodzaju dodatkowe informacje. Można na przykład określić ikony zawartości folderu lub menu skrótów obiektu. Eksplorator Windows wywołuje metodę IShellFolder::GetUIObjectOf, aby spróbować pobrać dodatkowe informacje o obiekcie, który znajduje się w folderze. Eksplorator Windows określa, dla którego obiektu chce uzyskać informacje, oraz identyfikator IID odpowiedniego interfejsu. Następnie obiekt folderu tworzy obiekt, który uwidacznia żądany interfejs i zwraca wskaźnik interfejsu.

Jeśli rozszerzenie umożliwia użytkownikom przenoszenie obiektów za pomocą przeciągania i upuszczania lub schowka, Eksplorator Windows wywoła funkcję IShellFolder::GetUIObjectOf, aby zażądać interfejsu IDataObject lub IDropTarget. Aby uzyskać szczegółowe informacje, zobacz transferowanie obiektów powłoki za pomocą przeciągania i upuszczania oraz schowka.

Eksplorator Windows wywołuje IShellFolder::CreateViewObject, gdy chce uzyskać takie same informacje o samym folderze.

BindToObject

Eksplorator Windows wywołuje metodę IShellFolder::BindToObject, gdy użytkownik próbuje otworzyć jeden z podfolderów rozszerzenia. Jeśli riid jest ustawiony na IID_IShellFolder, należy utworzyć i zainicjować obiekt folderu reprezentujący podfolder i zwrócić interfejs IShellFolder obiektu.

Notatka

Obecnie Eksplorator Windows wywołuje tę metodę tylko w celu zażądania interfejsu IShellFolder. Nie zakładaj jednak, że zawsze tak będzie. Przed kontynuowaniem należy zawsze sprawdzać wartość riid.

 

GetDisplayNameOf

Eksplorator Windows wywołuje metodę IShellFolder::GetDisplayNameOf, aby przekonwertować kod PIDL jednego z obiektów folderu na nazwę. Ten PIDL musi być względny do folderu nadrzędnego obiektu. Innymi słowy, musi zawierać pojedynczą strukturęSHITEMID, która nie jest NULL,. Ponieważ istnieje więcej niż jeden możliwy sposób na nadania nazw obiektom, Eksplorator Windows określa typ nazwy, ustawiając co najmniej jedną flagę SHGDNF w parametrze uFlags. Jedna z dwóch wartości, SHGDN_NORMAL lub SHGDN_INFOLDER, zostanie ustawiona tak, aby określić, czy nazwa powinna być względna względem folderu, czy względem pulpitu. Jedną z pozostałych trzech wartości, SHGDN_FOREDITING, SHGDN_FORADDRESSBARlub SHGDN_FORPARSING, można ustawić, aby określić, do czego będzie używana nazwa.

Należy zwrócić nazwę w postaci struktury STRRET. Jeśli SHGDN_FOREDITING, SHGDN_FORADDRESSBARi SHGDN_FORPARSING nie są ustawione, zwróć nazwę wyświetlaną obiektu. Jeśli flaga SHGDN_FORPARSING jest ustawiona, Eksplorator Windows żąda nazwy do analizy składniowej. Analizowanie nazw jest przekazywane do IShellFolder::P arseDisplayName w celu uzyskania kodu PIDL obiektu, mimo że może znajdować się co najmniej jeden poziom poniżej bieżącego folderu w hierarchii przestrzeni nazw. Na przykład nazwa analizowania obiektu systemu plików to jego ścieżka. Można przekazać w pełni kwalifikowaną ścieżkę dowolnego obiektu w systemie plików do IShellFolder::ParseDisplayName metody i zwróci w pełni kwalifikowany PIDL obiektu.

Podczas analizowania nazwy są traktowane jako ciągi tekstowe, ale nie muszą one zawierać nazwy wyświetlanej. Należy przypisać nazwy analizowania w oparciu o to, co będzie działać najbardziej wydajnie, gdy wywoływana jest metoda IShellFolder::ParseDisplayName. Na przykład, wiele wirtualnych folderów powłoki Shell nie jest częścią systemu plików i nie posiada w pełni kwalifikowanej ścieżki. Zamiast tego każdy folder ma przypisany identyfikator GUID, a nazwa analizowania ma postać ::{GUID}. Niezależnie od tego, jakiego schematu używasz, powinien być w stanie niezawodnie działać w "obie strony". Na przykład, jeśli obiekt wywołujący przekazuje nazwę do analizy składniowej do IShellFolder::ParseDisplayName w celu pobrania PIDL obiektu, a następnie przekazuje ten PIDL do IShellFolder::GetDisplayNameOf z ustawioną flagą SHGDN_FORPARSING, obiekt wywołujący powinien odzyskać oryginalną nazwę do analizy składniowej.

GetAttributesOf

Eksplorator Windows wywołuje metodę IShellFolder::GetAttributesOf w celu określenia atrybutów co najmniej jednego elementu zawartego w obiekcie folderu. Wartość cidl podaje liczbę elementów w zapytaniu, a aPidl wskazuje na listę ich pidlów.

Ponieważ testowanie niektórych atrybutów może być czasochłonne, Eksplorator Windows zwykle ogranicza zapytanie do podzestawu dostępnych flag, ustawiając ich wartości w rfgInOut. Metoda powinna testować tylko te atrybuty, których flagi są ustawione w rfgInOut. Pozostaw ustawione prawidłowe flagi i wyczyść resztę. Jeśli w zapytaniu znajduje się więcej niż jeden element, ustaw tylko te flagi, które mają zastosowanie do wszystkich elementów.

Notatka

Atrybuty muszą być poprawnie ustawione, aby element był poprawnie wyświetlany. Jeśli na przykład element jest folderem zawierającym podfoldery, należy ustawić flagę SFGAO_HASSUBFOLDER. W przeciwnym razie Eksplorator Windows nie wyświetli ikony + obok ikony elementu w widoku drzewa.

 

ParseDisplayName

Metoda IShellFolder::ParseDisplayName jest w pewnym sensie lustrzanym obrazem IShellFolder::GetDisplayNameOf. Najczęstszym zastosowaniem tej metody jest przekonwertowanie nazwy analizy obiektu na skojarzona nazwa PIDL. Nazwa analizowania może odwoływać się do dowolnego obiektu znajdującego się poniżej folderu w hierarchii przestrzeni nazw. Zwrócony kod PIDL jest względny względem obiektu folderu, który uwidacznia metodę i zwykle nie jest w pełni kwalifikowany. Innymi słowy, mimo że PIDL może zawierać kilka struktur SHITEMID, pierwszy będzie albo samego obiektu, albo pierwszego podfolderu w ścieżce od folderu do obiektu. Obiekt wywołujący będzie musiał dołączyć ten identyfikator PIDL do w pełni kwalifikowanego identyfikatora PIDL folderu, aby uzyskać w pełni kwalifikowany identyfikator PIDL dla obiektu.

IShellFolder::ParseDisplayName można również wywołać, aby zażądać atrybutów obiektu. Ponieważ określenie wszystkich odpowiednich atrybutów może być czasochłonne, obiekt wywołujący ustawi tylko te flagi SFGAO_XXX reprezentujące informacje interesujące obiekt wywołujący. Należy określić, które z tych atrybutów są prawdziwe dla obiektu, i wyczyścić pozostałe flagi.

Interfejs IEnumIDList

Gdy Eksplorator Windows musi wyliczyć obiekty zawarte w folderze, wywołuje IShellFolder::EnumObjects. Obiekt folderu musi utworzyć obiekt wyliczenia, który uwidacznia interfejs IEnumIDList i zwraca ten wskaźnik interfejsu. Eksplorator Windows zazwyczaj używa IEnumIDList w celu wyliczenia PIDLs wszystkich obiektów zawartych w folderze.

IEnumIDList jest standardowym interfejsem wyliczania OLE i jest implementowany w zwykły sposób. Pamiętaj jednak, że zwracane listy PIDLs muszą być relatywne względem folderu i zawierać jedynie strukturę SHITEMID obiektu oraz terminator.

Implementowanie opcjonalnych interfejsów

Istnieje wiele opcjonalnych interfejsów powłoki, które mogą obsługiwać obiekty folderów rozszerzenia. Wiele z nich, takich jak IExtractIcon, umożliwia dostosowanie różnych aspektów sposobu, w jaki użytkownik wyświetla rozszerzenie. Inne, takie jak IDataObject, umożliwiają rozszerzenie obsługi funkcji takich jak przeciąganie i upuszczanie.

Żaden z opcjonalnych interfejsów nie jest uwidaczniony bezpośrednio przez obiekt folderu. Zamiast tego Eksplorator Windows wywołuje jedną z dwóch metod IShellFolder, aby zażądać interfejsu:

Aby podać informacje, obiekt folderu tworzy obiekt, który uwidacznia żądany interfejs i zwraca wskaźnik interfejsu. Eksplorator Windows wywołuje ten interfejs, aby pobrać potrzebne informacje. W tej sekcji omówiono najczęściej używane interfejsy opcjonalne.

IExtractIcon

Eksplorator Windows żąda interfejsu IExtractIcon przed wyświetleniem zawartości folderu. Interfejs umożliwia rozszerzeniu określanie niestandardowych ikon dla obiektów, które znajdują się w folderze. W przeciwnym razie zostaną użyte standardowe ikony plików i folderów. Aby udostępnić ikonę niestandardową, utwórz obiekt wyodrębniania ikon, który uwidacznia IExtractIcon i zwraca wskaźnik do tego interfejsu. Aby uzyskać więcej informacji, zobacz dokumentację referencyjną IExtractIcon lub Tworzenie obsługi ikon.

IContextMenu

Gdy użytkownik kliknie obiekt prawym przyciskiem myszy, Eksplorator Windows zażąda interfejsu IContextMenu. Aby udostępnić menu skrótów dla obiektów, utwórz obiekt obsługi menu i zwróć jego interfejs IContextMenu.

Procedury tworzenia obiektu programu obsługi menu są bardzo podobne do procedur używanych do tworzenia rozszerzenia powłoki programu obsługi menu. Aby uzyskać szczegółowe informacje, zobacz Tworzenie programów obsługi menu kontekstowego lub IContextMenu, IContextMenu2, lub IContextMenu3.

IQueryInfo

Eksplorator Windows wywołuje interfejs IQueryInfo w celu pobrania ciągu tekstowego etykietki informacji.

IDataObject i IDropTarget

Gdy obiekty są wyświetlane przez Eksploratora Windows, obiekt folderu nie ma bezpośredniego sposobu, aby wiedzieć, kiedy użytkownik próbuje wycinać, kopiować lub przeciągać obiekt. Zamiast tego Eksplorator Windows żąda interfejsuIDataObject. Aby zezwolić na przesyłanie obiektu, utwórz obiekt danych i zwróć wskaźnik do interfejsu IDataObject.

Podobnie użytkownik może próbować usunąć obiekt danych w Eksploratorze Windows reprezentujący jeden z obiektów, takich jak ikona lub ścieżka paska adresu. Eksplorator Windows żąda interfejsu IDropTarget. Aby zezwolić na porzucenie obiektu danych, utwórz obiekt, który uwidacznia interfejs IDropTarget i zwraca wskaźnik interfejsu.

Obsługa transferu danych jest jednym z bardziej skomplikowanych aspektów pisania rozszerzeń przestrzeni nazw. Aby zapoznać się ze szczegółową dyskusją, zobacz Przenoszenie obiektów powłoki za pomocą przeciągania i upuszczania oraz schowka.

Praca z domyślną implementacją widoku folderu powłoki

Źródła danych korzystające z domyślnego obiektu widoku folderu powłoki (DefView) muszą implementować następujące interfejsy:

Opcjonalnie mogą również implementować IPersistFolder3.