Categorias
Tirando o ícone associado de uma extensão de arquivo
Este artigo apresenta uma função que você pode usar para obter o ícone associado a um arquivo ou documento baseado em sua extensão de arquivo (ou seja, não importa se o arquivo ou documento já exista no disco ou não).
ExtractAssociatedIcon
Para obter o ícone de um aplicativo ou documento, pode utilizar essa função API (relatada na unidade ShellAPI):
function ExtractAssociatedIcon(hInst: HINST; lpIconPath: PChar;
var lpiIcon: Word): HICON; stdcall;
hInst: A alavanca do aplicativo. Este valor está contido na variável pre-definida HInstance.
lpIconPath: um indicador para um caractere em buffer que deverá conter uma corda terminada nula com o nome completo do caminho do aplicativo, biblioteca (DLL) ou documento. Se for um documento, a função vai colocar lá o caminho completo do aplicativo associado ao ícone de onde foi extraído, de modo que devemos alocar um buffer grande o suficiente.
lpiIcon: O index do ícone (o primeiro ícone do arquivo tem um index de 0). Se lpIconPath especifica um documento, então lpiIcon está definido através da função (é por isso que ele é passado por referência) para o a posição index do atual ícone retirado do associado executável (definido no arquivo de associação).
Valor de retorno: Se a função falhar, ela retorna a 0. Se for bem sucedida, ela volta como um ícone handle, que é um valor inteiro que o Windows usa para identificar os recursos alocados. Não é necessário chamar a API DestroyIcon para liberar o ícone, uma vez que vai ser desalocado automaticamente quando o aplicativo terminar, embora você possa fazê-lo se quiser.
AMOSTRA
Agora, o que fazemos com o ícone handle? Normalmente o que nós queremos é um ícone, com nome e instância da classe TIcon. Tudo o que temos que fazer é criar um objeto TIcon e atribuir à sua propriedade Handle. Se mais tarde vamos atribuir outro valor para a propriedade Handle, o ícone anterior será automaticamente liberado. O mesmo acontece se o objeto TIcon é liberado.
Aqui está um exemplo de que as alterações no ícone do formulário:
usa SysUtils, Windows, ShellAPI;
procedimento TForm1.Button1Click(Sender: TObject);
var
IconIndex: word;
Buffer: array[0..2048] of char;
IconHandle: HIcon;
começo
StrCopy(@Buffer, 'C:\Windows\Help\Windows.hlp');
IconIndex := 0;
IconHandle := ExtractAssociatedIcon(HInstance, Buffer, IconIndex);
if IconHandle <> 0 then
Icon.Handle := IconHandle;
fim;
GETASSOCIATEDICON
Infelizmente, ExtractAssociatedIcon falha se o arquivo não existir no disco, portanto, nós definimos um procedimento que pega o ícone de um arquivo, este existindo ou não, e também poderá pegar o ícone pequeno (ideal para um TListView que pode ser exibido em estilos de exibição vsIcon ou vsReport). O procedimento recebe três parâmetros: o nome do arquivo e dois indicadores para variáveis hicon (inteiro): uma para o ícone grande (32x32) e outra para o ícone pequeno (16x16). Qualquer um deles pode ser nulo se você não precisar de um desses ícones. Os ícones "devolvidos", pelo procedimento terão que ser liberados com o API DestroyIcon. Isso será feito automaticamente se você atribuir o ícone handle (hicon) à propriedade Handle de um objeto TIcon (o ícone será disponível quando esse objeto se libertar ou um novo valor for atribuído a ele).
usa SysUtils, Registry, Windows, ShellAPI;
tipo
PHICON = ^HICON;
procedimento GetAssociatedIcon(FileName: TFilename;
PLargeIcon, PSmallIcon: PHICON);
// Pegar os ícones de um dado arquivo
var
IconIndex: word; // Posicionar o ícone no arquivo
FileExt, FileType: string;
Reg: TRegistry;
p: integer;
p1, p2: pchar;
label
noassoc;
começo
IconIndex := 0;
// Pegar a extensão do arquivo
FileExt := UpperCase(ExtractFileExt(FileName));
se ((FileExt <> '.EXE') and (FileExt <> '.ICO')) ou
not FileExists(FileName) então comece
// Se o arquivo é um EXE ou ICO e existe, então
// nós vamos extraír o ícone deste arquivo. Senão
// aqui nós vamos tentar achar o ícone associado em
// Windows Registry...
Reg := nil;
tente
Reg := TRegistry.Create(KEY_QUERY_VALUE);
Reg.RootKey := HKEY_CLASSES_ROOT;
se FileExt = '.EXE' then FileExt := '.COM';
se Reg.OpenKeyReadOnly(FileExt) então
tente
FileType := Reg.ReadString('');
finalmente
Reg.CloseKey;
fim;
se (FileType <> '') and Reg.OpenKeyReadOnly(
FileType + '\DefaultIcon') então
tente
FileName := Reg.ReadString('');
finalmente
Reg.CloseKey;
fim;
finalmente
Reg.Free;
fim;
// Se nós não conseguirmos achar a associação, nós vamos
// tentar pegar os ícones padrão
se FileName = '' then goto noassoc;
// Pegue o nome do arquivo e o índice de ícones da
// associação (do formulário '"filaname",index')
p1 := PChar(FileName);
p2 := StrRScan(p1, ',');
se p2 <> nulo então comece
p := p2 - p1 + 1; // Posição do comma
IconIndex := StrToInt(Copy(FileName, p + 1,
Length(FileName) - p));
SetLength(FileName, p - 1);
fim;
fim;
// Tentativa de pegar o ícone
if ExtractIconEx(pchar(FileName), IconIndex,
PLargeIcon^, PSmallIcon^, 1) <> 1 então
comece
noassoc:
// A operação falhou ou o arquivo não estava associado
// ícone. Tente pegar os ícones padrão em SHELL32.DLL
tente // para pegar a localização de SHELL32.DLL
FileName := IncludeTrailingBackslash(GetSystemDir)
+ 'SHELL32.DLL';
exceto
FileName := 'C:\WINDOWS\SYSTEM\SHELL32.DLL';
fim;
// Determinar o ícone padrão para a extensão do arquivo
se (FileExt = '.DOC') então IconIndex := 1
também se (FileExt = '.EXE')
ou (FileExt = '.COM') então IconIndex := 2
também se (FileExt = '.HLP') então IconIndex := 23
também se (FileExt = '.INI')
ou (FileExt = '.INF') então IconIndex := 63
também se (FileExt = '.TXT') então IconIndex := 64
também se (FileExt = '.BAT') então IconIndex := 65
também se (FileExt = '.DLL')
ou (FileExt = '.SYS')
ou (FileExt = '.VBX')
ou (FileExt = '.OCX')
ou (FileExt = '.VXD') então IconIndex := 66
também se (FileExt = '.FON') então IconIndex := 67
também se (FileExt = '.TTF') então IconIndex := 68
também se (FileExt = '.FOT') then IconIndex := 69
também IconIndex := 0;
// Tentativa de pegar o ícone.
se ExtractIconEx(pchar(FileName), IconIndex,
PLargeIcon^, PSmallIcon^, 1) <> 1 então
comece
// Falha em pegar o ícone. Simplesmente "returne" zeros.
se PLargeIcon <> nil then PLargeIcon^ := 0;
se PSmallIcon <> nil then PSmallIcon^ := 0;
fim;
fim;
fim;
AMOSTRA
Esse exemplo vai mudar o ícone no seu formulário:
procedimento TForm1.Button1Click(Sender: TObject);
var
SmallIcon: HICON;
comece
GetAssociatedIcon('file.doc', nil, @SmallIcon);
se SmallIcon <> 0 então
Icon.Handle := SmallIcon;
fim;