Распаковщик иконок
Автор: George Anescu
Описание
Наверное Вы иногда замечали, что в некоторых
приложения сидят красивые иконки. И, наверное,
Вам тоже хотелось поместить эти иконки в свою
программу. Давайте посмотрим - как просто можно
это сделать.
Проект представляет собой 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;
}
|