2012-03-21 13 views
6

Czy ktoś wie o klasie, która potrafi czytać ikony wieloramkowe? Wyszukiwanie w Internecie nie wygenerowało żadnych informacji.Załaduj ikony MultiFrame

Próbowałem używać IconTools 2.0 przez Alana Petera Stotza, który ładuje ikony do listy poprawnie, ale głębia bitowa dla ikon 8-bitowych i 4-bitowych jest zwracana jako 0. Bitduszetka dla ramek ikon o wielkości 32 i 24-bitowej jest jednak zwracany poprawnie.

Ikona pojawia się poprawnie podczas przeglądania ... tylko bitdepth jest błędny dla wymienionych bitów.

EDIT # 2 baised na komentarzem TLama Oto niektóre niesprawdzone kod:

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; 

Jestem na dobrej drodze? W moich testach mam teraz 1 ikonę, ale funkcja NumberOfIcons wraca 1?

EDIT # 3 Według pliku pomocy „Jeśli jest to plik .ico, wartość zwracana ExtractIcon to 1.” Jakiej metody można użyć, aby uzyskać liczbę ikon w pliku ico?

+0

Planujesz edytować je dalej czy tylko chce je wykorzystać w programie? Jeśli to drugie, łatwiej jest połączyć je jako zasoby i użyć interfejsów API zasobów, aby uzyskać odpowiednią wersję ikony. –

+0

@ David ... Próbuję użyć ich w ImageEditor, który ładuje bitmapy, więc gdy otrzymam ikonę potrzebuję przekonwertować go do bitmapy, a następnie uzyskać jego szerokość i wysokość i bitdepth. Próbuję użyć ExtractIcon do zrobienia tego baised na komentarz TLamas. Dodałem nietestowany kod jako edycję. – Bill

+0

@Bill, ImageEditor dostarczany z Delphi? Jeśli tak, spróbuj zapomnieć o tym. Mam dobre doświadczenie, np. z IcoFX (jest też wersja przenośna), która pozwala eksportować ikony do kilku formatów (* .bmp włącznie). Ale nie musisz używać tylko map bitowych w plikach zasobów, możesz użyć dowolnego typu pliku, musisz tylko skompilować pliki zasobów. – TLama

Odpowiedz

5

Oto mały przykład kodu:

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 ... dziękuję ...Wydaje mi się, że udało mi się również osiągnąć sukces dzięki http://www.tkweb.eu/en/delphicomp/kicon.html. – Bill

+2

@Bill, BTW KIcon używa tej samej metody powyżej, tj. 'TKIcon.LoadFromStream'->' FIconCount: = IH.idCount; '. – kobik

+1

Heh, ciekawe, nigdy nie wiedziałem, co jest możliwe, aby kontynuować ExctractIcon w opisanym przypadku. – OnTheFly