2012-03-21 9 views
6

誰かがマルチフレームアイコンを読むことができるクラスについて知っていますか?インターネットを検索しても情報は得られていません。MultiFrameアイコンをロード

アイコンをリストに正しくロードするAlan Peter StotzがIconTools 2.0を使用しようとしましたが、8ビットと4ビットアイコンのビット深度が0に戻りました。32ビットと24ビットのアイコンフレームのビット深度しかし、正しく返されます。

表示されるアイコン自体は正しく表示されます...言及されたビットのビット深度が間違っています。ここTLamaによってコメントにBaised

EDIT#2 は、いくつかの未テストコードです:

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を返していますか?

EDIT#3 ヘルプファイルによると、「ファイルが.icoファイルであれば、ExtractIconの戻り値は1です。」どのような方法を使ってicoファイルのアイコン数を取得できますか?ここで

+0

あなたは、さらにそれらを編集することを計画しているか、あなただけのプログラムでそれらを使用するために欠けていますか?後者の場合は、リソースとしてリンクし、リソースAPIを使用してアイコンの正しいバージョンを取得する方が簡単です。 –

+0

@David ...ビットマップを読み込むImageEditorでそれらを使用しようとしているので、アイコンを取得したらビットマップに変換し、幅と高さ、ビット深度を取得する必要があります。私はExtractIconを使用してTLamasのコメントでこれを行うよう試みています。私は、未テストのコードを編集として追加しました。 – Bill

+0

@Bill、ImageEditorはDelphiに同梱されていますか?もしそうなら、それを忘れてください。私は良い経験を持っています。あなたがアイコンをいくつかのフォーマット(* .bmpを含む)にエクスポートすることを可能にするIcoFX(それの移植可能なバージョンもあります)。しかし、リソースファイルでビットマップだけを使用する必要はありません。任意のファイルタイプを使用できます。リソースファイルを自分でコンパイルするだけで済みます。 – TLama

答えて

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

+2

@Bill、BTW KIconは上記と同じ方法、すなわち 'TKIcon.LoadFromStream'->' FIconCount:= IH.idCount; 'を使います。 – kobik

+1

興味深いことに、上記のケースでExctractIconを実行することが可能であることはまったく分かりませんでした。 – OnTheFly

関連する問題