我用这段代码从exe文件中读取其ICON
var
  myIcon: TIcon;
begin
  myIcon := TIcon.Create;
  try
    myIcon.ReleaseHandle;
    myIcon.Handle := ExtractIcon(hInstance, PChar('c:\aaa.exe'), 0);
    myIcon.Palette := HALFTONE;   //1处
    Image1.Canvas.Draw(0, 0, myIcon);
    if SaveDlg.Execute then
      myIcon.SaveToFile(OpenDlg.FileName);
  finally
    myIcon.Free;
  end;
end;
但是发现,画在Image1画布上的图像为真彩,而保存的.ico文件却只有16色?
查询Delphi Help,其中有这样一句话:
If your application supports 256 colors, you should use the Windows halftone palette, as the shell does. It helps system performance, because the system does not need to load a new palette every time the execution focus switches between the shell and your application.
因此我在1处增加
myIcon.Palette := HALFTONE;
但是程序运行结果并未有改变?
请问如何实现8bit以上颜色的ICON?

解决方案 »

  1.   

    关注,我也为这事烦,看就别人的ICO颜色很艳
      

  2.   

    http://community.csdn.net/Expert/topic/4814/4814219.xml?temp=.5663874
      

  3.   

    翻看了一下源代码,比较了一下D7和BDS2006的
    以下是D7的。
    procedure WriteIcon(Stream: TStream; Icon: HICON; WriteLength: Boolean);
    var
      IconInfo: TIconInfo;
      MonoInfoSize, ColorInfoSize: DWORD;
      MonoBitsSize, ColorBitsSize: DWORD;
      MonoInfo, MonoBits, ColorInfo, ColorBits: Pointer;
      CI: TCursorOrIcon;
      List: TIconRec;
      Length: Longint;
    begin
      FillChar(CI, SizeOf(CI), 0);
      FillChar(List, SizeOf(List), 0);
      CheckBool(GetIconInfo(Icon, IconInfo));
      try
        InternalGetDIBSizes(IconInfo.hbmMask, MonoInfoSize, MonoBitsSize, 2);
        InternalGetDIBSizes(IconInfo.hbmColor, ColorInfoSize, ColorBitsSize, 16);
        MonoInfo := nil;
        MonoBits := nil;
        ColorInfo := nil;
        ColorBits := nil;
        try
          MonoInfo := AllocMem(MonoInfoSize);
          MonoBits := AllocMem(MonoBitsSize);
          ColorInfo := AllocMem(ColorInfoSize);
          ColorBits := AllocMem(ColorBitsSize);
          InternalGetDIB(IconInfo.hbmMask, 0, MonoInfo^, MonoBits^, 2);
          InternalGetDIB(IconInfo.hbmColor, 0, ColorInfo^, ColorBits^, 16);
          if WriteLength then
          begin
            Length := SizeOf(CI) + SizeOf(List) + ColorInfoSize +
              ColorBitsSize + MonoBitsSize;
            Stream.Write(Length, SizeOf(Length));
          end;
          with CI do
          begin
            CI.wType := RC3_ICON;
            CI.Count := 1;
          end;
          Stream.Write(CI, SizeOf(CI));
          with List, PBitmapInfoHeader(ColorInfo)^ do
          begin
            Width := biWidth;
            Height := biHeight;
            Colors := biPlanes * biBitCount;
            DIBSize := ColorInfoSize + ColorBitsSize + MonoBitsSize;
            DIBOffset := SizeOf(CI) + SizeOf(List);
          end;
          Stream.Write(List, SizeOf(List));
          with PBitmapInfoHeader(ColorInfo)^ do
            Inc(biHeight, biHeight); { color height includes mono bits }
          Stream.Write(ColorInfo^, ColorInfoSize);
          Stream.Write(ColorBits^, ColorBitsSize);
          Stream.Write(MonoBits^, MonoBitsSize);
        finally
          FreeMem(ColorInfo, ColorInfoSize);
          FreeMem(ColorBits, ColorBitsSize);
          FreeMem(MonoInfo, MonoInfoSize);
          FreeMem(MonoBits, MonoBitsSize);
        end;
      finally
        DeleteObject(IconInfo.hbmColor);
        DeleteObject(IconInfo.hbmMask);
      end;
    end;以下是BDS2006的
    procedure WriteIcon(Stream: TStream; Icon: HICON; WriteLength: Boolean);
    var
      IconInfo: TIconInfo;
      MonoInfoSize, ColorInfoSize: DWORD;
      MonoBitsSize, ColorBitsSize: DWORD;
      MonoInfo, MonoBits, ColorInfo, ColorBits: Pointer;
      CI: TCursorOrIcon;
      List: TIconRec;
      Length: Longint;
    begin
      FillChar(CI, SizeOf(CI), 0);
      FillChar(List, SizeOf(List), 0);
      CheckBool(GetIconInfo(Icon, IconInfo));
      try
        InternalGetDIBSizes(IconInfo.hbmMask, MonoInfoSize, MonoBitsSize, 2);
        InternalGetDIBSizes(IconInfo.hbmColor, ColorInfoSize, ColorBitsSize, -1);
        MonoInfo := nil;
        MonoBits := nil;
        ColorInfo := nil;
        ColorBits := nil;
        try
          MonoInfo := AllocMem(MonoInfoSize);
          MonoBits := AllocMem(MonoBitsSize);
          ColorInfo := AllocMem(ColorInfoSize);
          ColorBits := AllocMem(ColorBitsSize);
          InternalGetDIB(IconInfo.hbmMask, 0, MonoInfo^, MonoBits^, 2);
          InternalGetDIB(IconInfo.hbmColor, 0, ColorInfo^, ColorBits^, -1);
          if WriteLength then
          begin
            Length := SizeOf(CI) + SizeOf(List) + ColorInfoSize +
              ColorBitsSize + MonoBitsSize;
            Stream.Write(Length, SizeOf(Length));
          end;
          with CI do
          begin
            CI.wType := RC3_ICON;
            CI.Count := 1;
          end;
          Stream.Write(CI, SizeOf(CI));
          with List, PBitmapInfoHeader(ColorInfo)^ do
          begin
            Width := biWidth;
            Height := biHeight;
            Colors := biPlanes * biBitCount;
            DIBSize := ColorInfoSize + ColorBitsSize + MonoBitsSize;
            DIBOffset := SizeOf(CI) + SizeOf(List);
          end;
          Stream.Write(List, SizeOf(List));
          with PBitmapInfoHeader(ColorInfo)^ do
            Inc(biHeight, biHeight); { color height includes mono bits }
          Stream.Write(ColorInfo^, ColorInfoSize);
          Stream.Write(ColorBits^, ColorBitsSize);
          Stream.Write(MonoBits^, MonoBitsSize);
        finally
          FreeMem(ColorInfo, ColorInfoSize);
          FreeMem(ColorBits, ColorBitsSize);
          FreeMem(MonoInfo, MonoInfoSize);
          FreeMem(MonoBits, MonoBitsSize);
        end;
      finally
        DeleteObject(IconInfo.hbmColor);
        DeleteObject(IconInfo.hbmMask);
      end;
    end;
    所以D7中的InternalGetDIB(IconInfo.hbmColor, 0, ColorInfo^, ColorBits^, 16);
    已经变为InternalGetDIB(IconInfo.hbmColor, 0, ColorInfo^, ColorBits^, -1);
    所以用BDS2006就没有问题了,给分