|
| БЕСПЛАТНАЯ ежедневная online лотерея! Выигрывай каждый день БЕСПЛАТНО! |
|
|
Using PIDLs and Display Names
This section presents an example illustrating how to retrieve the location of a special folder, walk an item identifier list, and use the IShellFolder interface to retrieve display names. The example is a console application that prints the display names of the folders a user would have to open to get to the Programs folder. To display them, the application would carry out these steps:
1. Retrieve the PIDL (obtain a pointer to an item identifier list) for the Programs folder by using the SHGetSpecialFolderLocation function. 2. Bind to the desktop folder (retrieve the folder's IShellFolder interface) by using the SHGetDesktopFolder function. 3. Walk the item identifier list and process elements as follows: print the subfolder's display name, bind to the subfolder, and release the parent folder's IShellFolder interface.
Before carrying out any of the preceding steps, the application uses the SHGetMalloc function to retrieve a pointer to the shell's IMalloc interface, which it saves in the following global variable.
// Global pointer to the shell's IMalloc interface. LPMALLOC g_pMalloc;
The following example shows the application's main function. This function carries out all of the steps described previously, although it calls the application-defined GetNextItemID and CopyItemID functions to walk the item identifier list and the application-defined PrintStrRet function to print the display names. Code for these application-defined functions is shown following the code for the main function.
// main - the application's entrypoint function int __cdecl main() { LPITEMIDLIST pidlPrograms; LPSHELLFOLDER pFolder; // Get the shell's allocator. if (!SUCCEEDED(SHGetMalloc(&g_pMalloc))) return 1; // Get the PIDL for the Programs folder. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidlPrograms))) { // Start with the desktop folder. if (SUCCEEDED(SHGetDesktopFolder(&pFolder))) {
LPITEMIDLIST pidl; // Process each item identifier in the list. for (pidl = pidlPrograms; pidl != NULL; pidl = GetNextItemID(pidl)) { STRRET sName; LPSHELLFOLDER pSubFolder; LPITEMIDLIST pidlCopy; // Copy the item identifier to a list by itself. if ((pidlCopy = CopyItemID(pidl)) == NULL) break;
// Display the name of the subfolder. if (SUCCEEDED(pFolder->lpVtbl->GetDisplayNameOf( pFolder, pidlCopy, SHGDN_INFOLDER, &sName))) PrintStrRet(pidlCopy, &sName); // Bind to the subfolder. if (!SUCCEEDED(pFolder->lpVtbl->BindToObject( pFolder, pidlCopy, NULL, &IID_IShellFolder, &pSubFolder))) {
g_pMalloc->lpVtbl->Free(g_pMalloc, pidlCopy); break; } // Free the copy of the item identifier. g_pMalloc->lpVtbl->Free(g_pMalloc, pidlCopy); // Release the parent folder and point to the // subfolder. pFolder->lpVtbl->Release(pFolder); pFolder = pSubFolder; } // Release the last folder that was bound to.
if (pFolder != NULL) pFolder->lpVtbl->Release(pFolder); } // Free the PIDL for the Programs folder. g_pMalloc->lpVtbl->Free(g_pMalloc, pidlPrograms); } // Release the shell's allocator. g_pMalloc->lpVtbl->Release(g_pMalloc); return 0; }
Following is the GetNextItemID function. Given a pointer to an element in an item identifier list, the function returns a pointer to the next element (or NULL if there are no more elements). The main function calls this function to walk the item identifier list for the Programs folder.
// GetNextItemID - points to the next element in an item identifier // list. // Returns a PIDL if successful or NULL if at the end of the list. // pdil - previous element LPITEMIDLIST GetNextItemID(LPITEMIDLIST pidl) { // Get the size of the specified item identifier. int cb = pidl->mkid.cb; // If the size is zero, it is the end of the list. if (cb == 0) return NULL; // Add cb to pidl (casting to increment by bytes).
pidl = (LPITEMIDLIST) (((LPBYTE) pidl) + cb); // Return NULL if it is null-terminating or a pidl otherwise. return (pidl->mkid.cb == 0) ? NULL : pidl; }
Following is the CopyItemID function. Given a pointer to an element in an item identifier list, the function allocates a new list containing only the specified element followed by a terminating zero. The main function uses this function to create single-element PIDLs, which it passes to IShellFolder member functions.
// CopyItemID - creates an item identifier list containing the first // item identifier in the specified list. // Returns a PIDL if successful or NULL if out of memory. LPITEMIDLIST CopyItemID(LPITEMIDLIST pidl) { // Get the size of the specified item identifier. int cb = pidl->mkid.cb; // Allocate a new item identifier list. LPITEMIDLIST pidlNew = (LPITEMIDLIST) g_pMalloc->lpVtbl->Alloc(g_pMalloc, cb + sizeof(USHORT));
if (pidlNew == NULL) return NULL; // Copy the specified item identifier. CopyMemory(pidlNew, pidl, cb); // Append a terminating zero. *((USHORT *) (((LPBYTE) pidlNew) + cb)) = 0; return pidlNew; }
The IShellFolder::GetDisplayNameOf member function returns a display name in a STRRET structure. The display name may be returned in one of three ways, which is specified by the uType member of the STRRET structure. The main function calls the following PrintStrRet function to print the display name.
// PrintStrRet - prints the contents of a STRRET structure. // pidl - PIDL containing the display name if STRRET_OFFSET // lpStr - address of the STRRET structure void PrintStrRet(LPITEMIDLIST pidl, LPSTRRET lpStr) { LPSTR lpsz; int cch; switch (lpStr->uType) { case STRRET_WSTR: cch = WideCharToMultiByte(CP_OEMCP, WC_DEFAULTCHAR, lpStr->pOleStr, -1, NULL, 0, NULL, NULL); lpsz = (LPSTR) g_pMalloc->lpVtbl->Alloc(g_pMalloc, cch);
if (lpsz != NULL) { WideCharToMultiByte(CP_OEMCP, WC_DEFAULTCHAR, lpStr->pOleStr, -1, lpsz, cch, NULL, NULL); printf("%s\n", lpsz); g_pMalloc->lpVtbl->Free(g_pMalloc, lpsz); } break; case STRRET_OFFSET: printf("%s\n", ((char *) pidl) + lpStr->uOffset); break; case STRRET_CSTR: printf("%s\n", lpStr->cStr);
break; } }
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
| Пригласи друзей и счет твоего мобильника всегда будет положительным! |
Использование PIDLs и Дисплейные Имена
Эта секция представляет пример, иллюстрирующий как, чтобы извлекать позицию специальной папки, проходить список идентификатора пункта и использовать интерфейс IShellFolder, чтобы извлекать дисплейные имена. Пример является консольным приложением, которое печатает дисплейные имена папок, которые потребитель должен бы открывать, чтобы доходить до папки Программ. Чтобы отображать их, приложение должно выполнить эти шаги:
1. Извлеките PIDL (получите указатель в список идентификатора пункта) для папки Программ используя функцию SHGetSpecialFolderLocation. 2. Свяжитесь в настольную папку (извлеките интерфейс папки IShellFolder) используя функцию SHGetDesktopFolder. 3. Пройдите список идентификатора пункта и обрабатывайте элементы следующим образом: напечатайте дисплейное имя subfolder's, связывайтесь на subfolder и выпускайте родительский интерфейс папки IShellFolder.
Перед выполнять любой из предыдущих шагов, приложение использует функцию SHGetMalloc, чтобы извлекать указатель на интерфейс оболочки IMalloc, какое это сохраняется в следующей глобальной переменной.
// Глобальный указатель на интерфейс оболочки IMalloc. LPMALLOC g_pMalloc;
Следующий пример показывает прикладную основную функцию. Эта функция выполняет все шаги описанные прежде, хотя она называет определенное приложение GetNextItemID и функции CopyItemID, чтобы проходить список идентификатора пункта и определенная прикладная функция PrintStrRet, чтобы печатать дисплейные имена. Код для этих определившее прикладные функции показан следуя за кодом для основной функции.
// основа - приложение entrypoint функция int __cdecl основа() { LPITEMIDLIST pidlPrograms; LPSHELLFOLDER pFolder; // Получите распределитель оболочки. если (!ПОЛУЧЕННОЕ возврат(SHGetMalloc(&g_pMalloc))) 1; // Получите PIDL для папки Программ. если (ПОЛУЧЕННОЕ(SHGetSpecialFolderLocation(НЕДЕЙСТВИТЕЛЬНЫЙ, CSIDL_PROGRAMS, &pidlPrograms))) { // Начните с настольной папки. если (ПОЛУЧЕННОЕ(SHGetDesktopFolder(&pFolder))) {
LPITEMIDLIST pidl; // Обработайте каждый идентификатор пункта в списке. для (pidl = pidlPrograms; pidl != НЕДЕЙСТВИТЕЛЬНЫЙ; pidl = GetNextItemID(pidl)) { STRRET sName; LPSHELLFOLDER pSubFolder; LPITEMIDLIST pidlCopy; // Скопируйте идентификатор пункта в список самостоятельно. если прерывание ((pidlCopy = CopyItemID(pidl)) == НЕДЕЙСТВИТЕЛЬНЫЙ);
// Отобразите имя subfolder. если (ПОЛУЧЕННОЕ(pFolder->lpVtbl->GetDisplayNameOf( pFolder, pidlCopy, SHGDN_INFOLDER, &sName))) PrintStrRet(pidlCopy, &sName); // Свяжитесь в subfolder. если (!ПОЛУЧЕННОЕ(pFolder->lpVtbl->BindToObject( pFolder, pidlCopy, НЕДЕЙСТВИТЕЛЬНЫЙ, &IID_IShellFolder, &pSubFolder))) {
g_pMalloc->lpVtbl->Free(g_pMalloc, pidlCopy); прерывание; } // Свободный копия идентификатора пункта. g_pMalloc->lpVtbl->Free(g_pMalloc, pidlCopy); // Выпустите родительскую папку и указывайте на // subfolder. pFolder->lpVtbl->Release(pFolder); pFolder = pSubFolder; } // Выпуск последняя папка, которая была обязанной.
если (pFolder != НЕДЕЙСТВИТЕЛЬНЫЙ) pFolder->lpVtbl->Release(pFolder); } // Освободите PIDL для папки Программ. g_pMalloc->lpVtbl->Free(g_pMalloc, pidlPrograms); } // Выпуск распределитель оболочки. g_pMalloc->lpVtbl->Release(g_pMalloc); возврат 0; }
Следующее является функцией GetNextItemID. Данный указатель в элемент в списке идентификатора пункта, функция возвращает указатель в следующий элемент (или НЕДЕЙСТВИТЕЛЬНЫЙ если нет больше элементов). Основная функция называет эту функцию, чтобы проходить список идентификатора пункта для папки Программ.
// GetNextItemID - ТОЧКИ на следующий элемент в идентификаторе / пункте/ списке. // Возвращает PIDL если успешный или НЕДЕЙСТВИТЕЛЬНЫЙ если в конце списка. // pdil - предшествующий элемент LPITEMIDLIST GetNextItemID(LPITEMIDLIST pidl) { // Получите размер определенного идентификатора пункта. pidl->mkid.cb int cb =; // Если размер является нулем, он - конец списка. если (cb == 0) обратный НЕДЕЙСТВИТЕЛЬНЫЙ; // Добавьте cb, чтобы pidl (подсчитывать, чтобы увеличиваться байтами).
pidl = (LPITEMIDLIST) (((LPBYTE) pidl) + cb); // Обратный НЕДЕЙСТВИТЕЛЬНЫЙ если это - недействительное-завершение или pidl в противном случае. возврат (pidl->mkid.cb == 0)? НЕДЕЙСТВИТЕЛЬНЫЙ : pidl; }
Следующее является функцией CopyItemID. Данный указатель в элемент в списке идентификатора пункта, функция распределяет новый список, содержащий только определенный элемент сопровождался завершающим нулем. Основная функция использует эту функцию, чтобы создавать единственный-элемент PIDLs, какое это проходит в функции члена IShellFolder.
// CopyItemID - СОЗДАЕТ список идентификатора пункта, содержащий первый // идентификатор пункта в определенном списке. // Возвращает PIDL если успешный или НЕДЕЙСТВИТЕЛЬНЫЙ если из памяти. LPITEMIDLIST CopyItemID(LPITEMIDLIST pidl) { // Получите размер определенного идентификатора пункта. pidl->mkid.cb int cb =; // Распределите список идентификатора нового пункта. LPITEMIDLIST pidlNew = (LPITEMIDLIST) g_pMalloc->lpVtbl->Alloc(g_pMalloc, cb + sizeof(USHORT));
если (pidlNew == НЕДЕЙСТВИТЕЛЬНЫЙ) обратный НЕДЕЙСТВИТЕЛЬНЫЙ; // Копия определенный идентификатор пункта. CopyMemory(pidlNew, pidl, cb); // Добавление завершающий нуль. *((USHORT *) (((LPBYTE) pidlNew) + cb)) = 0; возвращайте pidlNew; }
IShellFolder::Функция члена GetDisplayNameOf возвращает дисплейное имя в структуру STRRET. Дисплейное имя может возвращаться одним из трех способов, который определен членом uType структуры STRRET. Основная функция называет следующее функции PrintStrRet, чтобы печатать дисплейное имя.
// PrintStrRet - ПЕЧАТАЕТ содержание структуры STRRET. // pidl - PIDL, содержащий дисплейное имя если STRRET_OFFSET // lpStr - адрес структурной пустоты STRRET PrintStrRet(LPITEMIDLIST pidl, LPSTRRET lpStr) { LPSTR lpsz; int cch; ключ (lpStr->uType) { случай STRRET_WSTR: cch = WideCharToMultiByte(CP_OEMCP, WC_DEFAULTCHAR, lpStr->pOleStr, -1, НЕДЕЙСТВИТЕЛЬНОЕ, 0, НЕДЕЙСТВИТЕЛЬНОЕ, НЕДЕЙСТВИТЕЛЬНОЕ); lpsz = (LPSTR) g_pMalloc->lpVtbl->Alloc(g_pMalloc, cch);
если (lpsz != НЕДЕЙСТВИТЕЛЬНЫЙ) { WideCharToMultiByte(CP_OEMCP, WC_DEFAULTCHAR, lpStr->pOleStr, -1, lpsz, cch, НЕДЕЙСТВИТЕЛЬНЫЙ, НЕДЕЙСТВИТЕЛЬНЫЙ); printf("%s\n", lpsz); g_pMalloc->lpVtbl->Free(g_pMalloc, lpsz); } прерывание; случай STRRET_OFFSET: printf("%s\n", ((символ *) pidl) + lpStr->uOffset); прерывание; случай STRRET_CSTR: printf("%s\n", lpStr->cStr);
прерывание; } }
|
|
|
|
| |