Click here to Skip to main content
Click here to Skip to main content

Icon Extractor Shell Extension

, 27 Aug 2001 Ms-PL
Rate this:
Please Sign up or sign in to vote.
A context menu handler shell extension for extracting icons from .exe and .dll files

Introduction

Sometimes you can see some applications with very interesting icons and maybe you would like to use the same or similar icons in your applications. In this article I will show how you can easily do this. This article is not a tutorial about how to develop shell extensions and particularly context menu handlers. For understanding all the needed details I recommend the excellent series of articles by Michael Dunn published here at CodeProject: "The Complete Idiot's Guide to Writing Shell Extensions" and particularly Part I. My fully functional project IconExtract.zip is developed using ATL and COM and is structured similarly to the project described in the above mentioned article so that all the explanations given there are applicable. This shell extension will add two menu items to the context menu when you right click on an .exe or .dll file in Windows Explorer, one menu item is for extracting the large icon and the other one is for extracting the small icon. By clicking on these menu items you copy the corresponding icon information (large or small) in the clipboard in the BITMAP format. Later you can paste this information in a graphical editor, for example in the one used by the Visual C++ environment and you can modify it as you want and use similar icons in your own applications.

I will present just the specific details about how to extract icon information from files and how to copy this information in the clipboard in order to be later saved.

How to extract icon information from files

All the specific actions are implemented in the QueryContextMenu() and InvokeCommand() functions of the IContextMenu interface. For getting the handles to the icons I used the function:

UINT ExtractIconEx(LPCTSTR lpszFile, int nIconIndex, HICON FAR *phiconLarge, HICON FAR *phiconSmall, UINT nIcons)

which can extract icons from executable files, dynamic-link libraries (DLL), or icon files. The function ExtractIcon() could also be used, but it extracts only the large icons. First we need to see if there are any icons in the file. For this purpose, in the function QueryContextMenu() I called ExtractIconEx() with the nIconIndex parameter set to -1 and the phiconLarge and phiconSmall parameters set both to NULL:

int nIcons = (int)ExtractIconEx(m_szFile, -1, NULL, NULL, 0);

If the returned number is greater than 0 then I insert in the contxet menu the menu items for large and small icon extraction. In this way the shell extension is applicable to all the files, but the Menu Items will be inserted only for the files which contain icons. Later in the InvokeCommand() function I get the handles to both icons with the call:

HICON hIconLarge, hIconSmall;
ExtractIconEx(m_szFile, 0, &hIconLarge, &hIconSmall, 1);

The icon information can be extracted in an ICONINFO structure using the function GetIconInfo() as in the call:

ICONINFO oIconInfo;
GetIconInfo(hIconLarge, &oIconInfo);

The ICONINFO structure has the field hbmColor of type HBITMAP which is a handle to a BITMAP structure. Using this handle we can copy the bitmap information in the clipboard:

BOOL bOpen = ::OpenClipboard(NULL);
if(TRUE==bOpen)
{
  ::EmptyClipboard();
  ::SetClipboardData(CF_BITMAP, oIconInfo.hbmColor);
  ::CloseClipboard();
}

Finally after we finish using the icon handles we must destroy the icons by calling the DestroyIcon() function:

DestroyIcon(hIconLarge);
DestroyIcon(hIconSmall);

Here I present the full code for QueryContextMenu() and InvokeCommand() functions:

// 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;
  //The number of icons in the file
  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)
{
  // If lpVerb really points to a string, ignore this function call and bail out
  if(0 != HIWORD( pCmdInfo->lpVerb))
    return E_INVALIDARG;
  //Extract first icon
  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;
}

Thanks to Michael Dunn for the improvement suggestions I implemented in this update to the article. I hope that you will find the presented information useful!

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)

Share

About the Author

George Anescu
Web Developer
Romania Romania
No Biography provided

Comments and Discussions

 
QuestionRegistration is successful but does not display? Pinmemberforcj92823-Jun-14 22:19 
QuestionYes but... What about getting a 24x24 icon version of this icon?? PinmemberEricF2-Jul-11 20:14 
Generalsome icons have one problem Pinmembernenfa15-Dec-09 22:11 
GeneralInstall and unInstall is succefull! Pinmemberthanhthuyvn_vtajkhskjakjd17-Jan-07 17:50 
GeneralLegal Issues PinsussAnonymous22-Dec-03 9:21 
QuestionHow to remove it? PinmemberSprudling6-Feb-02 13:50 
AnswerRe: How to remove it? PinmemberTim Smith6-Feb-02 15:19 
QuestionResource leak? Pinmemberjeffb5-Nov-01 9:01 
Questionhow can I find which icon in the icon list I extracted is the one lay beside the exe file in windows explorer? Pinmemberflyingcat29-Aug-01 17:41 
AnswerRe: how can I find which icon in the icon list I extracted is the one lay beside the exe file in windows explorer? PinmemberPaolo Messina31-Aug-01 14:35 
GeneralOne little improvment PinmemberMichael Dunn24-May-01 16:56 
GeneralRe: One little improvment PinmemberGeorge Anescu25-May-01 3:16 
GeneralIcon Copyrights PinmemberGeorge Chastain24-May-01 5:11 
GeneralRe: Icon Copyrights PinmemberGeorge Anescu25-May-01 3:17 
GeneralRe: Icon Copyrights PinmemberMario M.27-May-01 11:56 
GeneralRe: Icon Copyrights PinmemberMal Ross28-May-01 21:26 
GeneralRe: Icon Copyrights PinsussAnonymous2-Sep-03 5:31 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 28 Aug 2001
Article Copyright 2001 by George Anescu
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid