Board index » cppbuilder » Get the shell icon associated to a file type

Get the shell icon associated to a file type

Hi.

How can i get the the shell icon which is associated to a file typ.
I looking for a way to get this icon by the file extension.

thanks, Jan

 

Re:Get the shell icon associated to a file type


Quote
> How can i get the the shell icon which is associated to a file typ.
> I looking for a way to get this icon by the file extension.

Use SHGetFileInfo.

http://www.bcbdev.com/faqs/faq22.htm

contains a code example.

Harold Howe [TeamB]
http://www.bcbdev.com

Re:Get the shell icon associated to a file type


Hi.

Yes this works fine but ...
... i looking for a way to get the icon _by the file extension_.
The code example seems to work only for _existing_ files !?
I have only a name of a (not existing) file.

thanks, Jan

Re:Get the shell icon associated to a file type


Quote
Jan Weing?rtner wrote:

> Yes this works fine but ...
> ... i looking for a way to get the icon _by the file extension_.
> The code example seems to work only for _existing_ files !?

Hmm. I don't know how you would do it by extension. You could use a brute force
approach that creates a temp file with the given file extension, gets the icon index,
and then deletes the temp file. There might be a better way though.

Maybe you could use the registry. Look at how .cpp files get their extension. There
is a folder in HKEY_CLASSES_ROOT that lists each register file extension. Each of
these folders has a default value that contains a friendly name (the name for .cpp
files is BCBUnit). If you open a the registry folder for the friendly name, you can
read the DefaultIcon value, which points you to the actual icon resource. You could
open the icon resource using ExtractIcon. Sounds like a lot of work. The temp file
might be an easier way.

Harold Howe [TeamB]
http://www.bcbdev.com

Re:Get the shell icon associated to a file type


"Harold Howe (TeamB)" schrieb:

Quote

> Jan Weing?rtner wrote:

> > Yes this works fine but ...
> > ... i looking for a way to get the icon _by the file extension_.
> > The code example seems to work only for _existing_ files !?

> Hmm. I don't know how you would do it by extension. You could use a brute force
> approach that creates a temp file with the given file extension, gets the icon index,
> and then deletes the temp file. There might be a better way though.

That was my first idea to. I develop a cd archive software.
So i have thousands of files ... :-(

Quote
> Maybe you could use the registry. Look at how .cpp files get their extension. There
> is a folder in HKEY_CLASSES_ROOT that lists each register file extension. Each of
> these folders has a default value that contains a friendly name (the name for .cpp
> files is BCBUnit). If you open a the registry folder for the friendly name, you can
> read the DefaultIcon value, which points you to the actual icon resource. You could
> open the icon resource using ExtractIcon. Sounds like a lot of work.

:-|

another idea and a further question:
I save the complete directory structure of a disk with all files in a
TTreeView. If i
read this (existing) data, i can get the icons and save them in an
ImageList.
If i load (later) the directory structure in the TreeView, i could load
the
ImageList before and assign the ImageList to the tree.
So my question is: How can i save/load a TImageList in/from a file?

thanks, Jan Weing?rtner
-----------------------------
www.dschensky.de

Re:Get the shell icon associated to a file type


I look in the registry to get the file type icons.  It took me a while to
work this out.  I too write archiving software.  Sorry the following code is
in Delphi 5.

Call GetFileTypeIcon to get the icon.

I hope this helps.

// Extract from a delimited string
function ExtractStr(
  Text: String;                   // Text to look in
  Delimiter: String;              // Delimiter
  ElementNo: Integer              // Element no to extract
  ): String;                      // The contents of that element
var
  cnt: Integer;
  char_pos: Integer;
  work_string: String;
begin
  Result := '';

  work_string := Text;

  for cnt := 1 to ElementNo - 1 do
  begin
    char_pos := pos(Delimiter, work_string);
    if char_pos = 0 then
      Exit
    else
      // Keep the string after the Delimiter
      work_string := Copy(work_string, char_pos + Length(Delimiter),
        Length(work_string));
  end;

  char_pos := pos(Delimiter, work_string);
  if char_pos = 0 then
    Result := work_string
  else
    Result := copy(work_string, 1, char_pos - 1);
end;

// Get default icon for a file extension
function FileExtensionDefaultIcon(
  FileExtension: String;                  // File extension
  var FileName: String;                   // File containing the icon
  var IconIndex: Integer                  // Index of the icon in the file
  ): Boolean;                             // True if success
var
  reg: TRegIniFile;
  FileType, DefaultIcon: String;
  IconIndexStr: String;
begin
  Result := False;

  FileExtension := LowerCase(LTrimStr(FileExtension, '.'));

  if FileExtension = '' then
    Exit;

  reg := TRegIniFile.Create('');
  try
    reg.CloseKey;
    reg.RootKey := HKEY_CLASSES_ROOT;

    FileType := reg.ReadString('.' + FileExtension, '', '');

    if FileType = '' then
      // Not registered
      Exit;

    DefaultIcon := reg.ReadString(FileType + '\DefaultIcon', '', '');

    if DefaultIcon = '' then
      // No icon
      Exit;

    FileName := Trim(ExtractStr(DefaultIcon, ',', 1));

    IconIndexStr := ExtractStr(DefaultIcon, ',', 2);

    if (IconIndexStr + ' ')[1] = ' ' then
      // It seems than if there is a space before the icon index the index
      // is ignored and the first icon in the file is used
      // e.g. Delphi project files have '...Delphi32.exe, 4'.  Icon no 4
      // is not the correct no to use, 0 is the correct no
      IconIndex := 0
    else
      IconIndex := StrToInt(ExtractStr(DefaultIcon, ',', 2));

    Result := True;
  finally
    reg.Free;
  end;
end;

// Get a file's associated icon
function GetFileIcon(FileName: String; Icon: TIcon): Boolean;
var
  WorkFile: array[0 .. MAX_PATH] of char;
  IconHandle: HICON;
  IconIndex: Word;
begin
  StrPLCopy(WorkFile, FileName, MAX_PATH);
  IconIndex := 0;
  IconHandle := ExtractAssociatedIcon(Application.Handle, WorkFile,
IconIndex);

  Result := IconHandle <> Null;

  if Result then
    Icon.Handle := IconHandle;
end;

// Get an for this file extension associated icon
function GetFileTypeIcon(FileExtension: String; Icon: TIcon): Boolean;
var
  IconFile: String;
  WorkFile: array[0 .. MAX_PATH] of char;
  IconHandle: HICON;
  IconIndex: Integer;
begin
  Result := False;

  if not FileExtensionDefaultIcon(FileExtension, IconFile, IconIndex) then
  begin
    // File extension does not have a default icon so get the windows
    // standard icon.  This is a kludge, pass a file name that does not
    // exist to the get file icon routine.
    Result := GetFileIcon('zzzzzz.' + FileExtension, Icon);
    Exit;
  end;

  StrPLCopy(WorkFile, IconFile, MAX_PATH);

  IconHandle := ExtractIcon(Application.Handle, WorkFile, IconIndex);

  Result := IconHandle <> Null;

  if Result then
    Icon.Handle := IconHandle;
end;

Quote
Jan Weing?rtner <weing...@rz.uni-potsdam.de> wrote in message

news:3A6E9041.7D364D72@rz.uni-potsdam.de...
Quote

> "Harold Howe (TeamB)" schrieb:

> > Jan Weing?rtner wrote:

> > > Yes this works fine but ...
> > > ... i looking for a way to get the icon _by the file extension_.
> > > The code example seems to work only for _existing_ files !?

> > Hmm. I don't know how you would do it by extension. You could use a
brute force
> > approach that creates a temp file with the given file extension, gets
the icon index,
> > and then deletes the temp file. There might be a better way though.

> That was my first idea to. I develop a cd archive software.
> So i have thousands of files ... :-(

> > Maybe you could use the registry. Look at how .cpp files get their
extension. There
> > is a folder in HKEY_CLASSES_ROOT that lists each register file
extension. Each of
> > these folders has a default value that contains a friendly name (the
name for .cpp
> > files is BCBUnit). If you open a the registry folder for the friendly
name, you can
> > read the DefaultIcon value, which points you to the actual icon
resource. You could
> > open the icon resource using ExtractIcon. Sounds like a lot of work.

> :-|

> another idea and a further question:
> I save the complete directory structure of a disk with all files in a
> TTreeView. If i
> read this (existing) data, i can get the icons and save them in an
> ImageList.
> If i load (later) the directory structure in the TreeView, i could load
> the
> ImageList before and assign the ImageList to the tree.
> So my question is: How can i save/load a TImageList in/from a file?

> thanks, Jan Weing?rtner
> -----------------------------
> www.dschensky.de

Re:Get the shell icon associated to a file type


Andrew,

thanks for your tips. It works for a lot of Extensions.

Have you test your code with extensions like ".ini" or ".txt"?
For both ".ini" _and_ ".txt" i get the value
"%SystemRoot%\system32\shell32.dll,-152".
For this values i can't get the correct icon.

Any ideas?

Jan
-----------------------------
www.dschensky.de

Re:Get the shell icon associated to a file type


Yes you are right these extensions have icon indexes of -151 and -152.

I'm not sure why icon indexes can be negative because I don't know enough
about resources etc but these values still work for me when they are passed
into the ExtractIcon function.  The icons show correctly in my archiving
software.

I've only tested my code on Win98 2nd edition so far because I'm still
developing the app.  I'll try it on other systems and let you know if it
fails.

Maybe someone else might be able to tell us more about these icon indexes ?

Quote
Jan Weing?rtner <weing...@rz.uni-potsdam.de> wrote in message

news:3A6F6BE9.996590B5@rz.uni-potsdam.de...
Quote
> Andrew,

> thanks for your tips. It works for a lot of Extensions.

> Have you test your code with extensions like ".ini" or ".txt"?
> For both ".ini" _and_ ".txt" i get the value
> "%SystemRoot%\system32\shell32.dll,-152".
> For this values i can't get the correct icon.

> Any ideas?

> Jan
> -----------------------------
> www.dschensky.de

Re:Get the shell icon associated to a file type


It works on Win95 too.  Maybe there is a difference between the ExtractIcon
function in Delphi and the one in C++Builder ?

Quote
Andrew Cutforth <andr...@stukeley.demon.co.uk> wrote in message

news:94os6c$6jv5@bornews.inprise.com...
Quote
> Yes you are right these extensions have icon indexes of -151 and -152.

> I'm not sure why icon indexes can be negative because I don't know enough
> about resources etc but these values still work for me when they are
passed
> into the ExtractIcon function.  The icons show correctly in my archiving
> software.

> I've only tested my code on Win98 2nd edition so far because I'm still
> developing the app.  I'll try it on other systems and let you know if it
> fails.

> Maybe someone else might be able to tell us more about these icon indexes
?

> Jan Weing?rtner <weing...@rz.uni-potsdam.de> wrote in message
> news:3A6F6BE9.996590B5@rz.uni-potsdam.de...
> > Andrew,

> > thanks for your tips. It works for a lot of Extensions.

> > Have you test your code with extensions like ".ini" or ".txt"?
> > For both ".ini" _and_ ".txt" i get the value
> > "%SystemRoot%\system32\shell32.dll,-152".
> > For this values i can't get the correct icon.

> > Any ideas?

> > Jan
> > -----------------------------
> > www.dschensky.de

Re:Get the shell icon associated to a file type


Hi,
I am (also) developing a CD archiving app
so far I use "BruteForce" - I create a temp file a delete it
I profiled this solution and it turned out that
calling the WinAPI function is actually slower than the creation of a
zero-length file in a temp folder. So I cache the Icons I get from Windows
and I only do the whole banga-danga once for each file type.
Works fine for me.

HTH

--/******************************************************************/
//  Kalin Zahariev - senior software engineer
//  Sirma AI Ltd. - Artificial Intelligence Labs.
//  38A, Christo Botev Blvd, 1000 Sofia, Bulgaria.
//  tel: (+ 359 2) 9810018; 9812338; fax: 9819058
//  email: kal...@sirma.bg
//  http://www.sirma.bg/kalinz
/******************************************************************/

Other Threads