Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОСиСП - методички / OS&SP_Lab_2.6(shell).doc
Скачиваний:
95
Добавлен:
18.05.2015
Размер:
1.12 Mб
Скачать

Извлечение методом 1

Первый вызываемый метод IExtractIcon - GetIconLocation(). Эта функция просматривает файл (чье имя было сохранено в IPersistFile::Load()) и возвращает пару имя файла/индекс, как это обсуждалось выше. Вот прототип GetIconLocation():

HRESULT IExtractIcon::GetIconLocation (

UINT uFlags,

LPTSTR szIconFile,

UINT cchMax,

int* piIndex,

UINT* pwFlags );

Параметры:

  • uFlags Некоторые флаги, которые могут изменить поведение расширения. GIL_ASYNC передается, чтобы запросить, не займет ли процесс извлечения много времени. Если так, расширение может запросить извлечение в фоновом потоке, чтобы не задерживать интерфейс Проводника. Другие флаги, GIL_FORSHELL и GIL_OPENICON, кажется имеют значение только для расширений пространства имен. Нам не стоит беспокоиться насчет флагов, поскольку наш код не требует больших затрат времени на выполнение.

  • szIconFile, cchMax szIconFile - буфер, предоставленный оболочкой, в который помещается имя файла, содержащего иконку для использования проводником. cchMax - размер буфера в символах.

  • piIndex Указатель на int, в котором мы сохраним индекс иконки в файле (чье имя мы внесли в szIconFile)

  • pwFlags Указатель на UINT, в котором мы можем передать флаги, изменяющие поведение Проводника. Эти флаги описаны ниже.

GetIconLocation() заполняет параметры szIconFile и piIndex и возвращает S_OK. Можно также вернуть S_FALSE, если мы все-же решим, что не хотим обеспечивать указанную иконку. В этом случае Проводник установит иконку "неизвестный файл":

В параметре pwFlags Проводнику могут быть переданы следующие флаги:

  • GIL_DONTCACHE Сообщает Проводнику, что не надо проверять кэш иконок. В результате всегда будет вызываться IExtractIcon::Extract(). Я расскажу об этом флаге подробнее позже, когда буду описывать извлечение методом 2.

  • GIL_NOTFILENAME Согласно MSDN, этот флаг требует от Проводника проигнорировать пару szIconFile/piIndex, возвращаемую GetIconLocation(). Очевидно, таким образом расширения должны заставить Проводник всегда вызывать IExtractIcon::Extract(), однако этот флаг никак не влияет на то, что происходит после возврата из GetIconLocation().

  • GIL_SIMULATEDOC Этот флаг заставляет Проводник взять исконку, переданную расширением, вставить ее внутрь иконки в виде чистого листочка и использовать то что получилось как иконку для файла. Я продемонстрирую работу этого флага позже.

В методе 1 GetIconLocation() получает размер файла и основываясь на нем возвращает индекс от 0 до 3 включительно. У этого метода есть один недостаток - нам нужно отслеживать ID ресурсов и быть уверенным, что они в правильном порядке. Наше расширение имеет только 4 иконки, так что эта бухгалтерия не сложна, но если иконок будет больше, или вы будете удалять и добавлять иконки в вашем проекте, вы должны будете внимательно следить за идентификаторами ваших ресурсов.

Вот реализация нашей функции GetIconLocation(). Сначала мы открываем файл и получаем его размер. Если при этом произойдет ошибка, мы вернем S_FALSE и Проводник будет использовать иконку по умолчанию.

STDMETHODIMP CTxtIconShlExt::GetIconLocation (

UINT uFlags,

LPTSTR szIconFile,

UINT cchMax,

int* piIndex,

UINT* pwFlags )

{

DWORD dwFileSizeLo, dwFileSizeHi;

DWORDLONG ldwSize;

HANDLE hFile;

hFile = CreateFile ( m_szFilename, GENERIC_READ, FILE_SHARE_READ, NULL,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

if ( INVALID_HANDLE_VALUE == hFile )

return S_FALSE; // Сообщаем оболочке, что нужно использовать иконку по умолчанию

dwFileSizeLo = GetFileSize ( hFile, &dwFileSizeHi );

CloseHandle ( hFile );

if ( (DWORD) -1 == dwFileSizeLo && GetLastError() != NO_ERROR )

return S_FALSE; // Сообщаем оболочке, что нужно использовать иконку по умолчанию

ldwSize = ((DWORDLONG) dwFileSizeHi)<<32 | dwFileSizeLo;

Далее мы получаем путь к нашей DLL, поскольку иконки находятся в ней и копируем его в буффер szIconFile.

TCHAR szModulePath[MAX_PATH];

GetModuleFileName ( _Module.GetModuleInstance(), szModulePath, MAX_PATH );

lstrcpyn ( szIconFile, szModulePath, cchMax );

На следующем шаге мы проверяем размер файла и записываем в piIndex индекс иконки, соответствующей этому размеру.

if ( 0 == ldwSize )

*piIndex = 0;

else if ( ldwSize < 4096 )

*piIndex = 1;

else if ( ldwSize < 8192 )

*piIndex = 2;

else

*piIndex = 3;

В конце мы устанавливаем pwFlags в 0, чтобы получить от Проводника поведение по умолчанию. Это означает, что он проверит кэш иконок, чтобы определить, есть ли иконка szIconFile/piIndex в кэше, и, если да, то IExtractIcon::Extract() вызываться не будет. Мы возвращаем S_OK чтобы показать, что GetIconLocation() завершилась успешно.

*pwFlags = 0;

return S_OK;

}

Поскольку мы сообщили Проводнику, где найти иконку, наша реализация Extract() возвращает S_FALSE, чтобы он самостоятельно извлек иконку. Параметры Extract() я буду обсуждать в следующем разделе.

STDMETHODIMP CTxtIconShlExt::Extract (

LPCTSTR pszFile,

UINT nIconIndex,

HICON* phiconLarge,

HICON* phiconSmall,

UINT nIconSize )

{

return S_FALSE; // Сообщаем оболочке что извлечение ей нужно сделать самостоятельно

}

И вот как выглядят наши иконки в действии:

Если изменить GetIconLocation() так чтобы pwFlags был установлен в GIL_SIMULATEDOC, иконки будут выглядеть так:

Заметьте, что в режиме больших иконок использована маленькая версия нашей иконки (16х16). При просмотре в режиме мелких значков Проводник дополнительно уменьшает нашу маленькую иконку, что выглядит не очень красиво.

Соседние файлы в папке ОСиСП - методички