Page 1 of 1

ExtractIconExW

PostPosted: Fri Apr 15, 2016 10:49 pm
by theLizard
What am I doing wrong!

I am using the following code ( for working out how to go about it ) to extract icons from files (exe / dll) and getting Access violation errors.

I have had success but the successes were random, by this I mean that if I opened the same file more than once it would work the first time then hang the second attempt to open with a TFileOpen dialog window.

On the second attempt, TFileOpen->Execute() did not produce a file open window.

I have searched and searched for sample code that was more than what I have but no luck.

I have no trouble using ExtractAssociatedIcon and adding to ListView.

I have tried all types of variations without luck,

Code: Select all
   UINT ico_count;
   UINT nIcons;
   UnicodeString lpszFile;
   int nIconIndex = -1;
   HICON * phiconLarge;
   HICON * phiconSmall;
   HICON icon;
   TIcon *ico;

   TListItem *item;

   lpszFile = fileName;
   ico_count = ExtractIconExW(lpszFile.w_str(), nIconIndex, phiconLarge, phiconSmall, nIcons);
   ico = new TIcon();
   ico->Height = 32;
   ico->Width = 32;

 if(phiconSmall > 0)
   {
   for(int i = 0; i < ico_count; i++)
      {
      icon = phiconSmall[i];
      ico->Handle = icon;
      ImageList->AddIcon(ico);
      item = lv->Items->Add();
      item->ImageIndex = ImageList->Count -1;
      }
   }

   for(int j = 0; j < ico_count; j++)
      DestroyIcon(phiconSmall[j]);

   delete ico;



TIA..

Re: ExtractIconExW

PostPosted: Sat Apr 16, 2016 5:47 am
by HsiaLin
This is the way i used it a while ago, im typing this from memory so it may
need tweaking:

Code: Select all
   HICON I;
   long Index = 0;
   long Limit = 0;

   if(OpenDialog1->Execute())
   {
      Limit = (long)ExtractIcon(HInstance, OpenDialog1->FileName.c_str(), -1);
      if(Limit < 1)
      {
         ShowMessage("No icons!");
         return 0;
      }

      I = ExtractIcon(HInstance, OpenDialog1->FileName.c_str(), Index);
      if((int)I > 1)
      {
         Image1->Picture->Icon->Handle = I;
      }
   }
}

Re: ExtractIconExW

PostPosted: Sat Apr 16, 2016 8:04 am
by minas
ico_count = ExtractIconExW(lpszFile.w_str(), nIconIndex, phiconLarge, phiconSmall, nIcons);


to get the number of icons call ExtractIconExW with
nIconIndex=-1
phiconLarge=NULL
phiconSmall= NULL

Code: Select all
ico_count = ExtractIconExW(lpszFile.w_str(), -1,NULL,NULL, nIcons);


then allocate memory for the icons' handles array

Code: Select all
if (ico_count>0){
      phiconSmall= new HICON[ico_count];
      // in one shot you get in phiconSmall the small Icons Handles
      // num is the number of successfully extracted
      int num = ExtractIconExW(lpszFile.w_str(),0, NULL, phiconSmall, ico_count);
      for(int i = 0; i < num; i++)
      {
          icon = phiconSmall[i];
          ico->Handle = icon;
          ImageList->AddIcon(ico);
          item = lv->Items->Add();
          item->ImageIndex =i;
         }
         
         for(int j = 0; j < num; j++)
                 DestroyIcon(phiconSmall[j]);

          if (phiconSmall!=NULL)
            delete[] phiconSmall;
      }
       delete ico;     
}

Re: ExtractIconExW

PostPosted: Sat Apr 16, 2016 5:11 pm
by theLizard
Thanks minas and HsiaLin very much appreciated.

Appears that the only thing I did not try in my earlier attempts was to allocate memory for the handles, which, of course now makes sense that it needed to be done.

Cheers.

Re: ExtractIconExW

PostPosted: Mon Apr 18, 2016 5:26 pm
by rlebeau
minas wrote:to get the number of icons call ExtractIconExW with
nIconIndex=-1
phiconLarge=NULL
phiconSmall= NULL


FWIW, this is documented behavior on MSDN:

ExtractIconEx function

nIconIndex [in]
Type: int

The zero-based index of the first icon to extract. For example, if this value is zero, the function extracts the first icon in the specified file.

If this value is –1 and phiconLarge and phiconSmall are both NULL, the function returns the total number of icons in the specified file. If the file is an executable file or DLL, the return value is the number of RT_GROUP_ICON resources. If the file is an .ico file, the return value is 1.

If this value is a negative number and either phiconLarge or phiconSmall is not NULL, the function begins by extracting the icon whose resource identifier is equal to the absolute value of nIconIndex. For example, use -3 to extract the icon whose resource identifier is 3.


When something is not working right for you, try reading the documentation :wink:

Re: ExtractIconExW

PostPosted: Tue Apr 19, 2016 4:37 pm
by theLizard
rlebeau wrote:When something is not working right for you, try reading the documentation :wink:


Prior to posting, I read the article in the link you posted and a number of others I found and only after spending some time getting random results using various approaches did I post for some assistance.

minas pointed out that memory needed to be allocated, the one thing I did not try (not seeing the forest for the trees, so to speak) once memory was allocated, I got the result I was after so, all is well now.

But while you are here, is there an easy way to get all the sizes of icons contained in a file, dll, exe etc... so that I can load any size image into a TListView

Cheers

Re: ExtractIconExW

PostPosted: Wed Apr 20, 2016 11:45 am
by rlebeau
theLizard wrote:But while you are here, is there an easy way to get all the sizes of icons contained in a file, dll, exe etc... so that I can load any size image into a TListView


There is no single Win32 API function for that particular purpose. You would have to enumerate an executable's resources to discover its available icon resources, and then manually parse the raw resource data to get the particular icon details, like size dimensions.

Find out number of icons in an icon resource using Win32 API

Re: ExtractIconExW

PostPosted: Thu Apr 21, 2016 6:08 am
by HsiaLin
This simple demo shows how to scroll thru all the icons in a dll/exe file.