Pregunta

Básicamente tengo un TcxGrid que enumerará varios nombres de archivos y me gustaría dar más detalles en función de la extensión del archivo, específicamente su descripción (por ejemplo, para .PDF es '' Documento de Adobe Acrobat '') y su icono relacionado .

Noto que hay un muy similar pregunta ya pero está relacionada con C # y me gustaría algo basado en Delphi.

Las sugerencias sobre dónde buscar este tipo de información serían buenas y si hay una clase similar a la mencionada en la publicación C # anterior (obviamente en Delphi) sería genial.

¿Fue útil?

Solución

Gracias a Rob Kennedy por señalarme en dirección a ShGetFileInfo. Luego busqué en Google y encontré estos dos ejemplos: Delphi 3000 , Torry's . A partir de eso, escribí la siguiente clase para hacer lo que necesitaba.

Además, justo cuando estaba terminando, la respuesta de Bill Miller me dio la última ayuda que necesitaba. Originalmente, estaba pasando los nombres completos de los archivos a ShGetFileInfo, que idealmente no era lo que quería. El ajuste sugirió pasar '' *. EXT '' fue genial.

La clase podría hacer más trabajo pero hace lo que necesito. Parece manejar extensiones de archivo que tampoco tienen detalles asociados.

Finalmente, en lo que estoy usando, lo cambié a usar una TcxImageList en lugar de una TImageList, ya que tenía problemas con los bordes negros que aparecían en los iconos, porque era una solución rápida.

unit FileAssociationDetails;

{
  Created       : 2009-05-07
  Description   : Class to get file type description and icons.
                  * Extensions and Descriptions are held in a TStringLists.
                  * Icons are stored in a TImageList.

                  Assumption is all lists are in same order.
}

interface

uses Classes, Controls;

type
  TFileAssociationDetails = class(TObject)
  private
    FImages : TImageList;
    FExtensions : TStringList;
    FDescriptions : TStringList;
  public
    constructor Create;
    destructor Destroy; override;

    procedure AddFile(FileName : string);
    procedure AddExtension(Extension : string);    
    procedure Clear;    
    procedure GetFileIconsAndDescriptions;

    property Images : TImageList read FImages;
    property Extensions : TStringList read FExtensions;
    property Descriptions : TStringList read FDescriptions;
  end;

implementation

uses SysUtils, ShellAPI, Graphics, Windows;

{ TFileAssociationDetails }

constructor TFileAssociationDetails.Create;
begin
  try
    inherited;

    FExtensions := TStringList.Create;
    FExtensions.Sorted := true;
    FDescriptions := TStringList.Create;
    FImages := TImageList.Create(nil);
  except
  end;
end;

destructor TFileAssociationDetails.Destroy;
begin
  try
    FExtensions.Free;
    FDescriptions.Free;
    FImages.Free;
  finally
    inherited;
  end;
end;

procedure TFileAssociationDetails.AddFile(FileName: string);
begin
  AddExtension(ExtractFileExt(FileName));
end;

procedure TFileAssociationDetails.AddExtension(Extension : string);
begin
  Extension := UpperCase(Extension);
  if (Trim(Extension) <> '') and
     (FExtensions.IndexOf(Extension) = -1) then
    FExtensions.Add(Extension);
end;

procedure TFileAssociationDetails.Clear;
begin
  FExtensions.Clear;
end;

procedure TFileAssociationDetails.GetFileIconsAndDescriptions;
var
  Icon: TIcon;
  iCount : integer;
  Extension : string;
  FileInfo : SHFILEINFO; 
begin
  FImages.Clear;
  FDescriptions.Clear;

  Icon := TIcon.Create;
  try
    // Loop through all stored extensions and retrieve relevant info
    for iCount := 0 to FExtensions.Count - 1 do
    begin
      Extension := '*' + FExtensions.Strings[iCount];

      // Get description type
      SHGetFileInfo(PChar(Extension),
                    FILE_ATTRIBUTE_NORMAL,
                    FileInfo,
                    SizeOf(FileInfo),
                    SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES
                    );
      FDescriptions.Add(FileInfo.szTypeName);

      // Get icon and copy into ImageList
      SHGetFileInfo(PChar(Extension),
                    FILE_ATTRIBUTE_NORMAL,
                    FileInfo,
                    SizeOf(FileInfo),
                    SHGFI_ICON or SHGFI_SMALLICON or
                    SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES
                    );
      Icon.Handle := FileInfo.hIcon;
      FImages.AddIcon(Icon);
    end;
  finally
    Icon.Free;
  end;
end;

end.

También aquí hay una aplicación de prueba de ejemplo que lo usa, es muy simple, solo un formulario con un TPageControl. Mi uso real no era para esto, sino para un Developer Express TcxImageComboxBox en un TcxGrid.

unit Main;

{
  Created       : 2009-05-07
  Description   : Test app for TFileAssociationDetails.
}

interface

uses
  Windows, Forms, FileAssociationDetails, Classes, Controls, ComCtrls;

type
  TfmTest = class(TForm)
    PageControl1: TPageControl;
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    FFileDetails : TFileAssociationDetails;
  public
    { Public declarations }
  end;

var
  fmTest: TfmTest;

implementation

{$R *.dfm}

procedure TfmTest.FormShow(Sender: TObject);
var
  iCount : integer;
  NewTab : TTabSheet;
begin
  FFileDetails := TFileAssociationDetails.Create;
  FFileDetails.AddFile('C:\Documents and Settings\...\Test.XLS');
  FFileDetails.AddExtension('.zip');
  FFileDetails.AddExtension('.pdf');
  FFileDetails.AddExtension('.pas');
  FFileDetails.AddExtension('.XML');
  FFileDetails.AddExtension('.poo');

  FFileDetails.GetFileIconsAndDescriptions;
  PageControl1.Images := FFileDetails.Images;

  for iCount := 0 to FFileDetails.Descriptions.Count - 1 do
  begin
    NewTab := TTabSheet.Create(PageControl1);
    NewTab.PageControl := PageControl1;
    NewTab.Caption := FFileDetails.Descriptions.Strings[iCount];
    NewTab.ImageIndex := iCount;
  end;
end;

procedure TfmTest.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  PageControl1.Images := nil;
  FFileDetails.Free;
end;

end.

¡Gracias a todos por sus respuestas!

Otros consejos

function GetGenericFileType( AExtension: string ): string;
{ Get file type for an extension }
var
  AInfo: TSHFileInfo;
begin
  SHGetFileInfo( PChar( AExtension ), FILE_ATTRIBUTE_NORMAL, AInfo, SizeOf( AInfo ),
    SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES );
  Result := AInfo.szTypeName;
end;

function GetGenericIconIndex( AExtension: string ): integer;
{ Get icon index for an extension type }
var
  AInfo: TSHFileInfo;
begin
  if SHGetFileInfo( PChar( AExtension ), FILE_ATTRIBUTE_NORMAL, AInfo, SizeOf( AInfo ),
    SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES ) <> 0 then
  Result := AInfo.iIcon
  else
    Result := -1;
end;

function GetGenericFileIcon( AExtension: string ): TIcon;
{ Get icon for an extension }
var
  AInfo: TSHFileInfo;
  AIcon: TIcon;
begin
  if SHGetFileInfo( PChar( AExtension ), FILE_ATTRIBUTE_NORMAL, AInfo, SizeOf( AInfo ),
    SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES ) <> 0 then
  begin
    AIcon := TIcon.Create;
    try
      AIcon.Handle := AInfo.hIcon;
      Result := AIcon;
    except
      AIcon.Free;
      raise;
    end;
  end
  else
    Result := nil;
end;

Llame a ShGetFileInfo . Puede indicarle la descripción (el "tipo de nombre" en el vocabulario de esa función), y puede darle un identificador de icono o un identificador de la lista de imágenes del sistema, donde reside el icono o la ruta al módulo que contiene el recurso de imagen. Esa función puede hacer muchas cosas diferentes, así que asegúrese de leer la documentación cuidadosamente.

MSDN dice ShGetFileInfo " puede ser lento " y llama al IExtractIcon interfaz a "más flexible y eficiente" alternativa. Pero la secuencia que recomienda es usar un IShellFolder , luego llame a GetUIObjectOf para obtener la interfaz IExtractIcon del archivo y luego llame a GetIconLocation y Extracto para recuperar el identificador del icono.

Por lo que sé, eso es exactamente lo que ShGetFileInfo hace de todos modos, pero es mucho más engorroso, y después de haber hecho todo eso, aún no tendría la descripción del tipo de archivo. Siga con ShGetFileInfo hasta que la velocidad y la eficiencia se conviertan en un problema notable.

uses ShellAPI;

var
AExtension: string;
AFileType: string;    
AListItem: TListItem;
AFileInfo: TSHFileInfo;
begin
// get the extensions file icon
AExtension := ExtractFileExt( FileName );
if SHGetFileInfo( PChar( '*' + AExtension ), FILE_ATTRIBUTE_NORMAL, AFileInfo, SizeOf
  ( AFileInfo ), SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES ) <> 0 then
  AIndex := AFileInfo.iIcon
else
  AIndex := -1;
AListItem.ImageIndex := AIndex;
// get extensions file info
if SHGetFileInfo( PChar( '*' + AExtension ), FILE_ATTRIBUTE_NORMAL, Info, SizeOf( Info ),
  SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES ) then
    AFileType := AFileInfo.szTypeName;
end;

No para sonar simplista, pero Google es tu amigo. Estos son algunos de los primeros resultados para " icono asociado de delphi " ;:

http://www.delphi3000.com/articles/article_453.asp? SK =

http://www.jpgriffiths.com/tutorial/Snippets%5Cgetassociatedicon.html

El otro método es buscar la extensión en el registro bajo HKEY_CLASSES_ROOT, luego seguir la clave en el valor predeterminado (si está disponible) y su valor predeterminado es la descripción. Este segundo nivel también es donde puede abrir los comandos de shell o imprimir el tipo de archivo, así como la ruta al icono predeterminado.

Aquí hay un par de buenos ejemplos del uso de ShGetFileInfo de bitwisemag.com:

http://www.bitwisemag.com/copy/delphi/lpad1.html

http://www.bitwisemag.com/copy/delphi/prog_groups2.html

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top