2012-03-21 42 views
6

有谁知道可以读取多帧图标的类?搜索互联网并没有产生任何信息。加载多帧图标

我试着用Alan Peter Stotz的IconTools 2.0,它将图标正确加载到列表中,但8位和4位图标的位深度返回为0. 32位和24位图标帧的位深度返回正确,但是。

查看时,图标本身显示正确...只是所述位的位深度错误。

编辑#2 由TLama评论Baised这里是一些未经测试的代码:

function NumberOfIcons (AFileName: string): integer; 
var 
    iNumberOfIcons: Integer; 
begin 

    iNumberOfIcons := ExtractIcon (hInstance, PChar (AFilename), UINT (-1)); 
    Result := iNumberOfIcons; 

end; 

function ExtractAnIcon (AFilename: string; AIndex: integer): TBitmap; 
var 
    icoHandle: HIcon; 
    iBitmap: TBitmap; 
    iIcon: TIcon; 
    iNumberOfIcons, i: Integer; 
begin 

    Result := nil; 

    iBitmap := TBitMap.Create; 

    iIcon := TIcon.Create; 
    try 

    // Get the number of Icons 
    iNumberOfIcons := ExtractIcon (hInstance, PChar (AFilename), UINT (-1)); 

    // Extract the icon frame 
    icoHandle := ExtractIcon (hInstance, PChar (AFileName), AIndex); 
    iIcon.Handle := icoHandle; 
    iBitmap.Width := iIcon.Width; 
    iBitmap.Height := iIcon.Height; 
    // Draw the icon on your bitmap 
    DrawIcon (iBitmap.Canvas.Handle, 0, 0, iIcon.Handle);  
    Result := iBitmap; 

    finally 
    iIcon.Free; 
    end; 

end; 

function PixelFormatToBitDepth (APixelFormat: TPixelFormat): integer; 
// Convert TPixelFormat to integer 
begin 

    Result := -1; 
    case APixelFormat of 
    pf32Bit: 
     Result := 32; 
    pf24bit: 
     Result := 24; 
    pf8bit: 
     Result := 8; 
    pf4Bit: 
     Result := 4; 
    pf1bit: 
     Result := 1; 
    end; 

end; 

我在正确的轨道上?在我的测试中,我现在得到1个图标,但NumberOfIcons函数返回1?

编辑#3 根据帮助文件“如果文件是一个.ico文件,ExtractIcon的返回值是1。”那么可以使用什么方法来获取ico文件中的图标数量?

+0

你打算做进一步的编辑或者你只是想在程序中使用它们?如果后者更容易将它们作为资源链接并使用资源API来获取正确版本的图标。 – 2012-03-21 13:58:06

+0

@David ...我想在加载位图的ImageEditor中使用它们,所以一旦我得到图标,我需要将它转换为位图,然后获取它的宽度和高度以及位深度。我正在尝试使用ExtractIcon来完成TLamas评论。我添加了未经测试的代码作为编辑。 – Bill 2012-03-21 14:07:21

+0

@Bill,Delphi附带的ImageEditor?如果是这样,那就试着忘记它。我有一个很好的经验,例如与IcoFX(也有它的便携式版本),它允许您将图标导出为多种格式(* .bmp包括)。但是你不需要在资源文件中只使用位图,你可以使用任何文件类型,你只需要自己编译资源文件。 – TLama 2012-03-21 14:33:18

回答

5

这里是一个小的代码示例:

uses ShellApi; 

type 
    TICONDIRENTRY = packed record 
    bWidth: Byte;   // Width, in pixels, of the image 
    bHeight: Byte;   // Height, in pixels, of the image 
    bColorCount: Byte;  // Number of colors in image (0 if >=8bpp) 
    bReserved: Byte;  // Reserved (must be 0) 
    wPlanes: Word;   // Color Planes 
    wBitCount: Word;  // Bits per pixel 
    dwBytesInRes: DWORD; // How many bytes in this resource? 
    dwImageOffset: DWORD; // Where in the file is this image? 
    end; 

    TICONDIR = packed record 
    idReserved: Word; // Reserved (must be 0) 
    idType: Word;  // Resource Type (1 for icons) 
    idCount: Word; // How many images? 
    idEntries: array [0..255] of TICONDIRENTRY; 
    end; 
    PICONDIR=^TICONDIR; 

function GetIconsCount(const FileName: string): Word; 
var 
    Stream: TMemoryStream; 
    IconDir: PICONDIR; 
begin 
    Result := 0; 
    if ExtractIcon(hInstance, PChar(FileName), UINT(-1)) <> 0 then 
    try 
    Stream := TMemoryStream.Create; 
    try 
     Stream.LoadFromFile(FileName); 
     IconDir := Stream.Memory; 
     if IconDir.idType = 1 then 
     Result := IconDir.idCount; 
    finally 
     Stream.Free; 
    end; 
    except 
    // do not raise exceptions 
    end; 
end; 

function ExtractIcons(const FileName: string; IconList: TList): Boolean; 
var 
    Stream: TMemoryStream; 
    NewIconStream: TMemoryStream; 
    IconDir: PICONDIR; 
    NewIconDir: PICONDIR; 
    Icon: TIcon; 
    I: Integer; 
begin 
    Result := False; 
    if ExtractIcon(hInstance, PChar(FileName), UINT(-1)) <> 0 then 
    try 
    Stream := TMemoryStream.Create; 
    try 
     Stream.LoadFromFile(FileName); 
     IconDir := Stream.Memory; 
     for I := 0 to IconDir.idCount-1 do 
     begin 
     NewIconStream := TMemoryStream.Create; 
     try 
      NewIconStream.Size := SizeOf(Word) * 3 + SizeOf(TICONDIRENTRY); 
      NewIconStream.Position:= SizeOf(Word) * 3 + SizeOf(TICONDIRENTRY); 

      NewIconDir := NewIconStream.memory; 
      NewIconDir.idCount := 1; 
      NewIconDir.idType := IconDir.idType; 
      NewIconDir.idReserved := IconDir.idReserved; 
      NewIconDir.idEntries[0] := IconDir.idEntries[I]; 
      NewIconDir.idEntries[0].dwImageOffset := NewIconStream.Size; 

      Stream.Position := IconDir.idEntries[I].dwImageOffset; 
      NewIconStream.CopyFrom(Stream, IconDir.idEntries[I].dwBytesInRes); 
      NewIconStream.Position := 0; 
      Icon := TIcon.Create; 
      Icon.LoadFromStream(NewIconStream); 
      IconList.Add(Icon); 
     finally 
      NewIconStream.Free; 
     end; 
     IconList.Add(Icon); 
     end; 
     Result := True; 
    finally 
     Stream.Free; 
    end; 
    except 
    // do not raise exceptions 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    FileName: string; 
    Icon: TIcon; 
    List: TList; 
    I: Integer; 
begin 
    FileName := 'c:\myicon.ico'; 
    List := TList.Create; 
    try 
    if ExtractIcons(FileName, List) then 
    for I := 0 to List.Count - 1 do 
    begin 
     Icon := TIcon(List.Items[I]); 
     DrawIcon(Form1.Canvas.Handle, 10, I * 40, Icon.Handle); 
     Icon.Free; 
    end; 
    finally 
    List.Free; 
    end; 
end; 
+2

@Kobik ...谢谢你...我似乎也与http://www.tkweb.eu/en/delphicomp/kicon.html有一些成功。 – Bill 2012-03-21 17:04:51

+2

@Bill,BTW KIcon使用与上述相同的方法,即“TKIcon.LoadFromStream” - >“FIconCount:= IH.idCount;”。 – kobik 2012-03-21 17:38:58

+1

嘿,有趣的是,从来不知道在所描述的情况下继续使用ExctractIcon有什么可能。 – OnTheFly 2012-03-21 18:23:30