Описание Наверное Вы иногда замечали, что в некоторых приложения сидят красивые иконки. И, наверное, Вам тоже хотелось поместить эти иконки в свою программу. Давайте посмотрим - как просто можно это сделать. Проект представляет собой shell расширение, которое добавляет два пункта во всплывающее меню при нажатии правой кнопкой на .exe или .dll файл в Windows Explorer. Первый пункт меню для распаковки больших иконок, а второй - для маленьких иконок. При нажатии на эти менюшки, информация о иконке (большая или маленькая) сопируется в clipboard, используя формат BITMAP. Далее можно скопировать содержимое буфера обмена в графический редактор. Как получить из файла информацию об иконке Все необходимые действия включены в функции QueryContextMenu() и InvokeCommand() интерфейса IContextMenu. Для получения обработчиков иконок используем следующую функцию: UINT ExtractIconEx(LPCTSTR lpszFile, int nIconIndex, HICON FAR *phiconLarge, HICON FAR *phiconSmall, UINT nIcons)
которая позволяет распакавать иконки из исполняемых файлов, динамических библиотек (DLL), или файлов-иконок. Так же можно использовать функцию ExtractIcon() , но она может распаковывать только большие иконки. Итак для начала нам необходимо определить - присутствуют ли иконки в файле. Для этого в функции QueryContextMenu() вызываем ExtractIconEx() с параметром nIconIndex равным -1 и параметрами phiconLarge и phiconSmall установленными в NULL: int nIcons = (int)ExtractIconEx(m_szFile, -1, NULL, NULL, 0);
Если возвращённое значение больше чем 0 то тогда вставляем во всплывающее меню пункты для больших и маленьких иконок. Таким образом наша shell примочка оперирует со всеми файлами, но пункты меню будут добавлены только для файлов, содержащих иконки. И наконец в функции InvokeCommand() получаем обработчики на оба типа иконок следующим образом: HICON hIconLarge, hIconSmall; ExtractIconEx(m_szFile, 0, &hIconLarge, &hIconSmall, 1);
Информацию об иконке распаковывается в структуру ICONINFO используя функцию GetIconInfo() следующим образом: ICONINFO oIconInfo; GetIconInfo(hIconLarge, &oIconInfo);
Структура ICONINFO имеет поле hbmColor типа HBITMAP которое и указывает на BITMAP структуру. Используя этот указатель мы можем скопировать информацию о битмапе в clipboard: BOOL bOpen = ::OpenClipboard(NULL); if(TRUE==bOpen) { ::EmptyClipboard(); ::SetClipboardData(CF_BITMAP, oIconInfo.hbmColor); ::CloseClipboard(); }
В заключение, после того как мы прекращаем использовать указатели на иконки, необходимо уничтожить их вызовом функции DestroyIcon(): DestroyIcon(hIconLarge); DestroyIcon(hIconSmall);
А теперь давайте посмотрим на полный код функций QueryContextMenu() и InvokeCommand(): // IContextMenu HRESULT CIconExtractObj::QueryContextMenu(HMENU hmenu, UINT uMenuIndex, UINT uCmdID, UINT uidLastCmd, UINT uFlags) { //If the flags include CMF_DEFAULTONLY then we shouldn't do anything if(uFlags & CMF_DEFAULTONLY) return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); int nMenus = 0; //Количество иконок в файле int nIcons = (int)ExtractIconEx(m_szFile, -1, NULL, NULL, 0); if(nIcons > 0) { InsertMenu(hmenu, uMenuIndex, MF_STRING | MF_BYPOSITION, uCmdID++, _T("Extract &Large Icon")); if(NULL != m_hExtractBmpL) SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, m_hExtractBmpL, NULL); uMenuIndex++; InsertMenu(hmenu, uMenuIndex, MF_STRING | MF_BYPOSITION, uCmdID++, _T("Extract &Small Icon")); if(NULL != m_hExtractBmpS) SetMenuItemBitmaps(hmenu, uMenuIndex, MF_BYPOSITION, m_hExtractBmpS, NULL); uMenuIndex++; nMenus = 2; } return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, nMenus); }
HRESULT CIconExtractObj::InvokeCommand(LPCMINVOKECOMMANDINFO pCmdInfo) { // Если lpVerb реальный указатель на строку, // то пропускаем данную функцию и выходим if(0 != HIWORD( pCmdInfo->lpVerb)) return E_INVALIDARG; //Распаковываем первую иконку HICON hIconLarge, hIconSmall; ExtractIconEx(m_szFile, 0, &hIconLarge, &hIconSmall, 1); ICONINFO oIconInfo; switch(LOWORD(pCmdInfo->lpVerb)) { case 0: GetIconInfo(hIconLarge, &oIconInfo); break;
case 1: GetIconInfo(hIconSmall, &oIconInfo); break;
default: return E_INVALIDARG; } BOOL bOpen = ::OpenClipboard(NULL); if(TRUE==bOpen) { ::EmptyClipboard(); ::SetClipboardData(CF_BITMAP, oIconInfo.hbmColor); ::CloseClipboard(); } //Destroy the icons DestroyIcon(hIconLarge); DestroyIcon(hIconSmall); return S_OK; }
|