{"id":698,"date":"2014-09-21T19:51:34","date_gmt":"2014-09-21T11:51:34","guid":{"rendered":"http:\/\/blog.qdac.cc\/?p=698"},"modified":"2014-09-21T19:51:34","modified_gmt":"2014-09-21T11:51:34","slug":"%e3%80%90delphi%e3%80%91icon%e5%9b%be%e6%a0%87%e6%96%87%e4%bb%b6%e8%a7%a3%e6%9e%90","status":"publish","type":"post","link":"https:\/\/blog.qdac.cc\/?p=698","title":{"rendered":"\u3010Delphi\u3011ICON\u56fe\u6807\u6587\u4ef6\u89e3\u6790"},"content":{"rendered":"<p>icon\u662f\u4e00\u79cd\u56fe\u6807\u683c\u5f0f\uff0c\u7528\u4e8e\u7cfb\u7edf\u56fe\u6807\u3001<a href=\"http:\/\/baike.baidu.com\/view\/37.htm\" target=\"_blank\">\u8f6f\u4ef6<\/a>\u56fe\u6807\u7b49\uff0c\u8fd9\u79cd\u56fe\u6807\u6269\u5c55\u540d\u4e3a*.icon\u3001*.ico\u3002\u5e38\u89c1\u7684\u8f6f\u4ef6\u6216windows\u684c\u9762\u4e0a\u7684\u90a3\u4e9b\u56fe\u6807\u4e00\u822c\u90fd\u662fICON\u683c\u5f0f\u7684\u3002<\/p>\n<p>ICON\u6587\u4ef6\u683c\u5f0f\u6bd4\u8f83\u7b80\u5355\uff0c\u5305\u542b\u6587\u4ef6\u5934\u6bb5\u3001\u56fe\u50cf\u6570\u636e\u5934\u6bb5\u3001\u56fe\u50cf\u6570\u636e\u6bb5\u3002<\/p>\n<p>\u6587\u4ef6\u5934\uff1a<br \/>\n\u6587\u4ef6\u5934\u4e3a6\u4e2a\u5b57\u8282\uff0c\u5b9a\u4e49\u5982\u4e0b\uff1a<\/p>\n<pre class=\"lang:delphi decode:true \">type\r\n  ICONDIR = packed record\r\n    idReserved: SmallInt; \/\/ Reserved\r\n    idType: SmallInt; \/\/ Resource type\r\n    idCount: SmallInt; \/\/ Image Count\r\n  end; \/\/ 6 bytes<\/pre>\n<p>&nbsp;<\/p>\n<p>idCount\u6807\u8bb0\u4e86\u6587\u4ef6\u4e2d\u5305\u542b\u7684\u56fe\u50cf\u6570\u91cf\u3002<\/p>\n<p>\u56fe\u50cf\u6570\u636e\u5934\u6bb5\uff1a<\/p>\n<p>\u7d27\u63a5\u7740\u6587\u4ef6\u5934\u7684\u5c31\u662f\u56fe\u50cf\u6570\u636e\u5934\u6bb5\u4e86\uff0c\u5b83\u5b58\u653e\u7740\u6587\u4ef6\u4e2d\u6bcf\u4e2a\u56fe\u50cf\u5bbd\u5ea6\u3001\u9ad8\u5ea6\u3001\u989c\u8272\u6570\u91cf\u3001\u6570\u636e\u6bb5\u7684\u504f\u79fb\u7b49\u4fe1\u606f\uff0c\u5927\u5c0f\u4e3a16 * idCount\u3002\u5b83\u662f\u4e00\u4e2a\u6570\u7ec4\uff0c\u6bcf\u9879\u6570\u636e16\u5b57\u8282\uff0c\u5b9a\u4e49\u5982\u4e0b\uff1a<\/p>\n<pre class=\"lang:delphi decode:true \">type\r\n  ICONDIRENTRY = packed record\r\n    bWidth: Byte; \/\/ Width of the image\r\n    bHeight: Byte; \/\/ Height of the image (2 * Height)\r\n    bColorCount: Byte; \/\/ Number of colors in image (0 when &gt;= 8 bpp)\r\n    bReserved: Byte; \/\/ Reserved\r\n    wPlanes: SmallInt; \/\/ Color Planes   (-&gt; xHotspot [Cursor])\r\n    wBitCount: SmallInt; \/\/ Bits per pixel (-&gt; yHotspot [Cursor])\r\n    dwBytesInRes: Integer; \/\/ How many bytes in this resource?\r\n    dwImageOffset: Integer; \/\/ Where in the file is this image?\r\n  end; \/\/ 16 bytes<\/pre>\n<p>&nbsp;<\/p>\n<p>\u8bfb\u53d6\u5b8c\u56fe\u50cf\u6570\u636e\u5934\u6bb5\u540e\uff0c\u5c31\u53ef\u4ee5\u77e5\u9053\u6587\u4ef6\u4e2d\u6bcf\u4e2a\u56fe\u6807\u7684\u5927\u5c0f\uff0c\u989c\u8272\u4f4d\u6570\u4e86\uff0c\u540c\u65f6\u76f4\u63a5\u6839\u636e\u6570\u636e\u6bb5\u7684\u504f\u79fb\uff0c\u8bfb\u53d6\u56fe\u50cf\u6570\u636e\u6bb5\u3002\u56fe\u50cf\u6570\u636e\u7684\u504f\u79fb\u662f\u4ece\u6587\u4ef6\u6700\u5f00\u59cb\u7b97\u8d77\u7684\u3002<\/p>\n<p>&nbsp;<\/p>\n<p>\u56fe\u50cf\u6570\u636e\u6bb5\uff1a<\/p>\n<p>\u56fe\u50cf\u6570\u636e\u4e3a\u591a\u4e2a\u56fe\u50cf\u7684DIB\u6570\u636e\uff0c\u6839\u636e\u6570\u636e\u5934\u6bb5\u7684\u504f\u79fb\u6765\u5b9a\u4f4d\u3002\u5b9a\u4f4d\u540e\uff0c\u8bfb\u53d6BIH\u4fe1\u606f\u3002\u4eceBIH\u4fe1\u606f\u4e2d\uff0c\u5224\u65ad\u989c\u8272\u4f4d\u6570\u5927\u4e8e8\u4f4d\u7684\uff0c\u8bb0\u53d6XOR\u8c03\u8272\u76d8 \u6570\u636e\uff08\u5c0f\u4e8e8\u4f4d\u7684\u4e0d\u5b58\u5728XOR\u8c03\u8272\u76d8\uff0c\u53ea\u5305\u542b\u6709\u4e00\u4e2aMASK\u8c03\u8272\u76d8\uff09\u3002\u8bfb\u53d6\u5b8cXOR\u8c03\u8272\u76d8\u540e\uff0c\u521d\u59cb\u5316\u56fe\u50cfDIB\u5934\uff0c\u7136\u540e\u5728\u6587\u4ef6\u4e2d\u8bfb\u53d6DIB\u6570\u636e\u3002<\/p>\n<p>\u4e0b\u9762\u6765\u770b\u770b\u5b9e\u73b0\u7684\u52a0\u8f7d\u4ee3\u7801\uff1a\uff08\u6ce8\u610f\uff1a\u672c\u793a\u4f8b\u4ee3\u7801\uff0c\u53ea\u52a0\u8f7dICO\u6587\u4ef6\u4e2d\u989c\u8272\u4f4d\u6570\u6700\u9ad8\uff0c\u6700\u5927\u7684\u4e00\u4e2a\uff09<\/p>\n<p>\u76f8\u5173\u5b9a\u4e49\uff1a<\/p>\n<pre class=\"lang:delphi decode:true \">type\r\n  dibBPPCts = (bpp_01 = 1, bpp_04 = 4, bpp_08 = 8, bpp_16 = 16, bpp_24 = 24,\r\n    bpp_32 = 32);\r\n\r\n  DIBItem = packed record\r\n  private\r\n    function GetBPP: dibBPPCts;\r\n    function GetBytesPerScanline: Integer;\r\n    function GetHeight: Integer;\r\n    function GetWidth: Integer;\r\n    function GetSize: Integer;\r\n  public\r\n    m_uBIH: BITMAPINFOHEADER;\r\n    m_hDC: Integer;\r\n    m_hDIB: Integer;\r\n    m_hOldDIB: Integer;\r\n    m_lpBits: Pointer;\r\n    m_lpBitsSize: Integer;\r\n\r\n    function Create(NewWidth, NewHeight: Integer; NewBPP: dibBPPCts): Boolean;\r\n    procedure Free();\r\n    procedure Clone(var toDIB: DIBItem);\r\n\r\n    procedure GetPalette(var Palette: TBytes);\r\n    procedure SetPalette(Palette: TBytes);\r\n\r\n    function Stretch(dc: HDC; x, y, w, h, xSrc, ySrc, wSrc, hSrc: Integer;\r\n      rop: Cardinal): Integer;\r\n    function Stretch32(dc: HDC; BufferBits: Pointer; BytesPerRow, x, y, w, h, xSrc, ySrc, wSrc, hSrc: Integer): Integer;\r\n\r\n    property Width: Integer read GetWidth;\r\n    property Height: Integer read GetHeight;\r\n    property BPP: dibBPPCts read GetBPP;\r\n    property BytesPerScanline: Integer read GetBytesPerScanline;\r\n    property Size: Integer read GetSize;\r\n  end;\r\n\r\n  DIBDATA = packed record\r\n    XORDIB: DIBItem; \/\/ XOR DIB section\r\n    ANDDIB: DIBItem; \/\/ AND DIB section\r\n  end;\r\n\r\ntype\r\n  BITMAPINFO_001 = packed record\r\n    bmiHeader: BITMAPINFOHEADER;\r\n    bmiColors: array [0 .. 7] of Byte;\r\n  end;\r\n\r\n  BITMAPINFO_004 = packed record\r\n    bmiHeader: BITMAPINFOHEADER;\r\n    bmiColors: array [0 .. 63] of Byte;\r\n  end;\r\n\r\n  BITMAPINFO_008 = packed record\r\n    bmiHeader: BITMAPINFOHEADER;\r\n    bmiColors: array [0 .. 1023] of Byte;\r\n  end;\r\n\r\n  BITMAPINFO_RGB = packed record\r\n    bmiHeader: BITMAPINFOHEADER;\r\n  end;\r\n\r\ntype\r\n  icoBPPCts = (Colors_002 = 1, Colors_016 = 4, Colors_256 = 8, Color_True = 24,\r\n    Color_ARGB = 32);<\/pre>\n<p>\u52a0\u8f7d\u4ee3\u7801\uff1a<\/p>\n<pre class=\"lang:delphi decode:true \">procedure TYxdIcon.LoadFromStream(Stream: TStream);\r\nvar\r\n  nImg: Integer;\r\nbegin\r\n  \/\/ Get icon header\r\n  Fillchar(m_uDir, sizeof(m_uDir), 0);\r\n  Stream.Read(m_uDir, sizeof(m_uDir));\r\n\r\n  \/\/ Get icon entries\r\n  SetLength(m_uDirEntry, m_uDir.idCount);\r\n  Stream.Read(m_uDirEntry[0], sizeof(ICONDIRENTRY) * m_uDir.idCount);\r\n\r\n  \/\/ Initialize arrays and monochrome palette\r\n  \/\/SetLength(m_OrderKey, m_uDir.idCount);\r\n  \/\/SetLength(m_uDIBData,  m_uDir.idCount);\r\n  \/\/SetLength(m_DIBData, m_uDir.idCount);\r\n  SetLength(aPalAND, 8);\r\n  FillChar(aPalAND[0], SizeOf(aPalAND), 0);\r\n  aPalAND[4] := $FF;\r\n  aPalAND[5] := $FF;\r\n  aPalAND[6] := $FF;\r\n\r\n  \/\/ Get images\r\n  nMaxIndex := -1;\r\n  nMaxW := 0;\r\n  for nImg := 0 to m_uDir.idCount - 1 do begin\r\n    if (m_uDirEntry[nImg].bWidth &gt; nMaxW) or\r\n      ((m_uDirEntry[nImg].bWidth = nMaxW) and (m_uDirEntry[nImg].bColorCount = 0)) then begin\r\n      nMaxW := m_uDirEntry[nImg].bWidth;\r\n      nMaxIndex := nImg;\r\n    end;\r\n  end;\r\n\r\n  if nMaxIndex &gt; -1 then begin\r\n    \/\/ Move to begin of image data\r\n    Stream.Position := m_uDirEntry[nMaxIndex].dwImageOffset;\r\n    \/\/ Load BITMAPINFOHEADER\r\n    Stream.Read(uBIH, SizeOf(uBIH));\r\n    \/\/ Load XOR palette [?] (&lt;= 8 bpp)\r\n    if uBIH.biBitCount &lt;= 8 then begin\r\n      SetLength(aPalXOR, 4 * Trunc(Power(2, uBIH.biBitCount)));\r\n      Stream.Read(aPalXOR[0], Length(aPalXOR));\r\n    end;\r\n\r\n    \/\/ Inititalize XOR DIB\r\n    FillChar(m_uDIBData, SizeOf(m_uDIBData), 0);\r\n    m_uDIBData.XORDIB.Create(uBIH.biWidth, uBIH.biHeight div 2, dibBPPCts(ubih.biBitCount));\r\n    if uBIH.biBitCount &lt;= 8 then\r\n      m_uDIBData.XORDIB.SetPalette(aPalXOR);\r\n\r\n    \/\/ Inititalize AND DIB\r\n    m_uDIBData.ANDDIB.Create(uBIH.biWidth, uBIH.biHeight div 2, bpp_01);\r\n    m_uDIBData.ANDDIB.SetPalette(aPalAND);\r\n\r\n    \/\/ Read DIB bits\r\n    m_uDIBData.XORDIB.m_lpBits := GetMemory(m_uDIBData.XORDIB.Size);\r\n    m_uDIBData.ANDDIB.m_lpBits := GetMemory(m_uDIBData.ANDDIB.Size);\r\n    Stream.Read(m_uDIBData.XORDIB.m_lpBits^, m_uDIBData.XORDIB.Size);\r\n    Stream.Read(m_uDIBData.ANDDIB.m_lpBits^, m_uDIBData.ANDDIB.Size);\r\n\r\n    m_OrderKey := IntToHex(uBIH.biWidth, 3) + IntToHex(uBIH.biHeight div 2, 3) +\r\n      IntToHex(uBIH.biBitCount, 2);\r\n  end;\r\n  Changed(Self);\r\nend;<\/pre>\n<p>DIBItem \u5c31\u662fICON\u6587\u4ef6\u4e2d\u4e00\u4e2a\u56fe\u6807\u7684\u56fe\u50cf\u6570\u636e\uff0c\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n<pre class=\"lang:delphi decode:true \">{ DIBItem }\r\n\r\nprocedure DIBItem.Clone(var toDIB: DIBItem);\r\nvar\r\n  aPal: TBytes;\r\nbegin\r\n  if m_hDIB &lt;&gt; 0 then begin\r\n    toDIB.Create(m_uBIH.biWidth, m_uBIH.biHeight, dibBPPCts(m_uBIH.biBitCount));\r\n    if m_lpBits &lt;&gt; nil then begin\r\n      toDIB.m_lpBits := GetMemory(Size);\r\n      CopyMemory(toDIB.m_lpBits, m_lpBits, Size);\r\n    end else\r\n      toDIB.m_lpBits := nil;\r\n    if (m_uBIH.biBitCount &lt;= 8) then begin\r\n        SetLength(aPal, 4 * Trunc(Power(2, m_uBIH.biBitCount)) - 1);\r\n        GetPalette(aPal);\r\n        toDIB.SetPalette(aPal);\r\n    end;\r\n  end;\r\nend;\r\n\r\nfunction DIBItem.Create(NewWidth, NewHeight: Integer;\r\n  NewBPP: dibBPPCts): Boolean;\r\nvar\r\n  BI_001: BITMAPINFO_001;\r\n  BI_004: BITMAPINFO_004;\r\n  BI_008: BITMAPINFO_008;\r\n  BI_RGB: BITMAPINFO_RGB;\r\nbegin\r\n  Free();\r\n\r\n  \/\/ Define DIB header\r\n  m_uBIH.biSize := SizeOf(m_uBIH);\r\n  m_uBIH.biPlanes := 1;\r\n  m_uBIH.biBitCount := Integer(NewBPP);\r\n  m_uBIH.biWidth := NewWidth;\r\n  m_uBIH.biHeight := NewHeight;\r\n  m_uBIH.biSizeImage := 4 * ((m_uBIH.biWidth * m_uBIH.biBitCount + 31) div 32) * m_uBIH.biHeight;\r\n  case NewBPP of\r\n    bpp_01: BI_001.bmiHeader := m_uBIH;\r\n    bpp_04: BI_004.bmiHeader := m_uBIH;\r\n    bpp_08: BI_008.bmiHeader := m_uBIH;\r\n  else\r\n    BI_RGB.bmiHeader := m_uBIH\r\n  end;\r\n\r\n  \/\/ Create DIB and select into a DC\r\n  m_hDC := CreateCompatibleDC(0);\r\n  if m_hDC &lt;&gt; 0 then begin\r\n    case NewBPP of\r\n      bpp_01: m_hDIB := CreateDIBSection(m_hDC, pBitmapInfo(@BI_001)^, DIB_RGB_COLORS, m_lpBits, 0, 0);\r\n      bpp_04: m_hDIB := CreateDIBSection(m_hDC, pBitmapInfo(@BI_004)^, DIB_RGB_COLORS, m_lpBits, 0, 0);\r\n      bpp_08: m_hDIB := CreateDIBSection(m_hDC, pBitmapInfo(@BI_008)^, DIB_RGB_COLORS, m_lpBits, 0, 0);\r\n    else\r\n      m_hDIB := CreateDIBSection(m_hDC, pBitmapInfo(@BI_RGB)^, DIB_RGB_COLORS, m_lpBits, 0, 0);\r\n    end;\r\n    if m_hDIB &lt;&gt; 0 then\r\n      m_hOldDIB := SelectObject(m_hDC, m_hDIB)\r\n    else\r\n      Free;\r\n  end;\r\n  Result := m_hDIB &lt;&gt; 0;\r\nend;\r\n\r\nprocedure DIBItem.Free;\r\nbegin\r\n  if m_hDC &lt;&gt; 0 then begin\r\n    if m_hDIB &lt;&gt; 0 then begin\r\n      SelectObject(m_hDC, m_hOldDIB);\r\n      DeleteObject(m_hDIB);\r\n    end;\r\n    DeleteDC(m_hDC);\r\n  end;\r\n  if m_lpBits &lt;&gt; nil then begin\r\n    FreeMemory(m_lpBits);\r\n    m_lpBits := nil;\r\n  end;\r\n  FillChar(m_uBIH, SizeOf(m_uBIH), 0);\r\n  m_hDC := 0;\r\n  m_hDIB := 0;\r\n  m_hOldDIB := 0;\r\nend;\r\n\r\nfunction DIBItem.GetBPP: dibBPPCts;\r\nbegin\r\n  Result := dibBPPCts(m_uBIH.biBitCount);\r\nend;\r\n\r\nfunction DIBItem.GetBytesPerScanline: Integer;\r\nbegin\r\n  Result := ((m_uBIH.biWidth * m_uBIH.biBitCount + 31) div 32) * 4;\r\nend;\r\n\r\nfunction DIBItem.GetHeight: Integer;\r\nbegin\r\n  Result := m_uBIH.biHeight;\r\nend;\r\n\r\nprocedure DIBItem.GetPalette(var Palette: TBytes);\r\nbegin\r\n  if m_hDIB &lt;&gt; 0 then\r\n    GetDIBColorTable(m_hDC, 0, Trunc(Power(2, m_uBIH.biBitCount)), Palette[Low(Palette)]);\r\nend;\r\n\r\nfunction DIBItem.GetSize: Integer;\r\nbegin\r\n  Result := m_uBIH.biSizeImage;\r\nend;\r\n\r\nfunction DIBItem.GetWidth: Integer;\r\nbegin\r\n  Result := m_uBIH.biWidth;\r\nend;\r\n\r\nprocedure DIBItem.SetPalette(Palette: TBytes);\r\nbegin\r\n  SetDIBColorTable(m_hDC, 0, (High(Palette) - Low(Palette) + 1) div 4, Palette[Low(Palette)])\r\nend;\r\n\r\nfunction DIBItem.Stretch(dc: HDC; x, y, w, h, xSrc, ySrc, wSrc, hSrc: Integer;\r\n  rop: Cardinal): Integer;\r\nvar\r\n  b001: BITMAPINFO_001;\r\n  b004: BITMAPINFO_004;\r\n  b008: BITMAPINFO_008;\r\n  brgb: BITMAPINFO_RGB;\r\n  iLen: Integer;\r\n  lOldMode: Integer;\r\nbegin\r\n  Result := 0;\r\n  if m_hDIB = 0 then Exit;\r\n  lOldMode := SetStretchBltMode(dc, COLORONCOLOR);\r\n  iLen := Trunc(Power(2, m_uBIH.biBitCount));\r\n  case dibBPPCts(m_uBIH.biBitCount) of\r\n    bpp_01:\r\n      begin\r\n        b001.bmiHeader := m_uBIH;\r\n        GetDIBColorTable(m_hDC, 0, iLen, b001.bmiColors[0]);\r\n        StretchDIBits(dc, x, y, w, h, xSrc, ySrc, wsrc, hsrc, m_lpBits,\r\n          pBitmapinfo(@b001)^, DIB_RGB_COLORS, rop);\r\n      end;\r\n    bpp_04:\r\n      begin\r\n        b004.bmiHeader := m_uBIH;\r\n        GetDIBColorTable(m_hDC, 0, iLen, b004.bmiColors[0]);\r\n        StretchDIBits(dc, x, y, w, h, xSrc, ySrc, wsrc, hsrc, m_lpBits,\r\n          pBitmapinfo(@b004)^, DIB_RGB_COLORS, rop);\r\n      end;\r\n    bpp_08:\r\n      begin\r\n        b008.bmiHeader := m_uBIH;\r\n        GetDIBColorTable(m_hDC, 0, iLen, b008.bmiColors[0]);\r\n        StretchDIBits(dc, x, y, w, h, xSrc, ySrc, wsrc, hsrc, m_lpBits,\r\n          pBitmapinfo(@b008)^, DIB_RGB_COLORS, rop);\r\n      end;\r\n    else begin\r\n      brgb.bmiHeader := m_uBIH;\r\n      StretchDIBits(dc, x, y, w, h, xSrc, ySrc, wsrc, hsrc, m_lpBits,\r\n        pBitmapinfo(@brgb)^, DIB_RGB_COLORS, rop);\r\n    end;\r\n  end;\r\n  SetStretchBltMode(dc, lOldMode);\r\n  Result := 1;\r\nend;\r\n\r\nfunction DIBItem.Stretch32(dc: HDC; BufferBits: Pointer; BytesPerRow, x, y, w, h, xSrc, ySrc, wSrc, hSrc: Integer): Integer;\r\nvar\r\n  i, i2, j, j2: Integer;\r\n  Stretch: Boolean;\r\n  FactorX, FactorY: Double;\r\n  ABytesPerScanline: Integer;\r\n  AlphaSource, ImageData: pPixelLine;\r\nbegin\r\n  Result := 0;\r\n  if (m_hDIB = 0) or (m_lpBits = nil) then Exit;\r\n\r\n  Stretch := (W &lt;&gt; wSrc) or (H &lt;&gt; hSrc);\r\n  if Stretch then FactorX := W \/ wSrc else FactorX := 1;\r\n  if Stretch then FactorY := H \/ hSrc else FactorY := 1;\r\n\r\n  AlphaSource := m_lpBits;\r\n  ABytesPerScanline := BytesPerScanline;\r\n  PByte(ImageData) := PByte(Integer(BufferBits) + BytesPerRow * (H - 1));\r\n  BufferBits := ImageData;\r\n\r\n  if m_uBIH.biBitCount = 32 then begin\r\n\r\n    FOR j := 1 TO H DO begin\r\n      FOR i := 0 TO W - 1 DO begin\r\n        if Stretch then i2 := trunc(i \/ FactorX) else i2 := i;\r\n        if (AlphaSource[i2].rgbReserved &lt;&gt; 0) then begin\r\n          if (AlphaSource[i2].rgbReserved = 255) then begin\r\n            ImageData[i] := AlphaSource[i2];\r\n          end else\r\n            with ImageData[i] do begin\r\n              rgbRed := ($7F + AlphaSource[i2].rgbRed * AlphaSource[i2].rgbReserved + rgbRed *\r\n                (not AlphaSource[i2].rgbReserved)) div $FF;\r\n              rgbGreen := ($7F + AlphaSource[i2].rgbGreen * AlphaSource[i2].rgbReserved +\r\n                rgbGreen * (not AlphaSource[i2].rgbReserved)) div $FF;\r\n              rgbBlue := ($7F + AlphaSource[i2].rgbBlue * AlphaSource[i2].rgbReserved + rgbBlue *\r\n               (not AlphaSource[i2].rgbReserved)) div $FF;\r\n              rgbReserved := not (($7F + (not rgbReserved) * (not AlphaSource[i2].rgbReserved)) div $FF);\r\n            end;\r\n        end;\r\n      end;\r\n\r\n      {Move pointers}\r\n      PByte(ImageData) := PByte(Integer(BufferBits) - BytesPerRow * j);\r\n      if Stretch then j2 := trunc(j \/ FactorY) else j2 := j;\r\n      PByte(AlphaSource) := PByte(m_lpBits) + ABytesPerScanline * j2;\r\n    end\r\n  end;\r\n  Result := 1;\r\nend;<\/pre>\n<p>&nbsp;<\/p>\n<p>ICON\u7684\u663e\u793a\uff1a<\/p>\n<p>\u672c\u793a\u4f8b\u4e2d\u7684TYxdIcon\u7ee7\u627f\u81eaTIcon\uff0c\u672c\u8eab\u5c31\u662f\u4e00\u4e2aGraphic\u4e86\uff0c\u6240\u4ee5\u53ef\u4ee5\u76f4\u63a5\u91cd\u8f7dDraw\u5b9e\u73b0\u663e\u793a\u3002<\/p>\n<pre class=\"lang:delphi decode:true \">type\r\n  TYxdIcon = class(TIcon)\r\n  private\r\n    m_uDir: ICONDIR; \/\/ Icon file header\r\n    m_uDirEntry: array of ICONDIRENTRY; \/\/ Icon image headers\r\n    m_OrderKey: string; \/\/ Image format key\r\n    aPalXOR: TBytes;\r\n    aPalAND: TBytes;\r\n    nMaxW: Byte;\r\n    nMaxIndex: Integer;\r\n    uBIH: BITMAPINFOHEADER;\r\n\r\n    BufferDC: HDC;\r\n    OldBufferBitmap, BufferBitmap: HBitmap;\r\n    LastW, LastH: Integer;\r\n    FUseBuffer: Boolean;\r\n  protected\r\n    m_uDIBData: DIBDATA; \/\/ Icon data (DIBs)\r\n    function GetEmpty: Boolean; override;\r\n    function GetHeight: Integer; override;\r\n    function GetWidth: Integer; override;\r\n    procedure Draw(ACanvas: TCanvas; const Rect: TRect); override;\r\n    function GetSupportsPartialTransparency: Boolean; override;\r\n  public\r\n    constructor Create; override;\r\n    destructor Destroy; override;\r\n    procedure Assign(Source: TPersistent); override;\r\n    procedure LoadFromStream(Stream: TStream); override;\r\n    procedure SaveToStream(Stream: TStream); override;\r\n    property UseBuffer: Boolean read FUseBuffer write FUseBuffer;\r\n  end;<\/pre>\n<p>Draw:<\/p>\n<pre class=\"lang:delphi decode:true \">procedure TYxdIcon.Draw(ACanvas: TCanvas; const Rect: TRect);\r\nvar\r\n  BitmapInfo: TBitmapInfo;\r\n  BufferBits, Buf: Pointer;\r\n  AlphaSource, ImageData: pPixelLine;\r\n  W, H: Integer;\r\n  BytesPerRow: Integer;\r\n  I, J: Integer;\r\nbegin\r\n  W := Rect.Right - Rect.Left;\r\n  H := Rect.Bottom - Rect.Top;\r\n\r\n  BitmapInfo := GetBitmapInfoHeader(W, H);\r\n  BufferDC := CreateCompatibleDC(0);\r\n  if (BufferDC = 0) then Exit;\r\n\r\n  BytesPerRow := (((BitmapInfo.bmiHeader.biBitCount * W) + 31) and\r\n    not 31) div 8;\r\n\r\n  BufferBitmap := CreateDIBSection(BufferDC, pBitmapInfo(@BitmapInfo)^,\r\n    DIB_RGB_COLORS, BufferBits, 0, 0);\r\n  OldBufferBitmap := SelectObject(BufferDC, BufferBitmap);\r\n  BitBlt(BufferDC, 0, 0, W, H, ACanvas.Handle, Rect.Left, Rect.Top, SRCCOPY);\r\n\r\n  if m_uDIBData.XORDIB.BPP = bpp_32 then begin\r\n    m_uDIBData.XORDIB.Stretch32(BufferDC, BufferBits, BytesPerRow, Rect.Left, Rect.Top,\r\n      W, H, 0, 0, m_uDIBData.XORDIB.Width, m_uDIBData.XORDIB.Height);\r\n  end else begin\r\n    \/\/ \u753b Mask \u5c42\r\n    m_uDIBData.ANDDIB.Stretch(BufferDC, Rect.Left, Rect.Top, W, H, 0, 0,\r\n      m_uDIBData.XORDIB.Width, m_uDIBData.XORDIB.Height, SRCCOPY);\r\n\r\n    \/\/ \u4fdd\u5b58\u900f\u660e\u533a\u57df\u4fe1\u606f\r\n    Buf := GetMemory(BytesPerRow*H);\r\n    CopyMemory(Buf, BufferBits, BytesPerRow*H);\r\n\r\n    \/\/ \u753b\u5b9e\u9645\u56fe\u50cf\r\n    m_uDIBData.XORDIB.Stretch(BufferDC, Rect.Left, Rect.Top, W, H, 0, 0,\r\n      m_uDIBData.XORDIB.Width, m_uDIBData.XORDIB.Height, SRCCOPY);\r\n\r\n    \/\/ \u5e94\u7528 Mask\r\n    PByte(ImageData) := PByte(BufferBits);\r\n    AlphaSource := Buf;\r\n    FOR j := 1 TO H DO begin\r\n      FOR i := 0 TO W - 1 DO begin\r\n        if (AlphaSource[i].rgbBlue = 0) and (AlphaSource[i].rgbGreen = 0) and (AlphaSource[i].rgbRed = 0) then begin\r\n          ImageData[i].rgbReserved := $ff;\r\n        end else\r\n          ImageData[i].rgbReserved := 0;\r\n      end;\r\n      {Move pointers}\r\n      inc(PByte(AlphaSource), BytesPerRow);\r\n      inc(PByte(ImageData), BytesPerRow);\r\n    end;\r\n    FreeMemory(Buf);\r\n  end;\r\n\r\n  TYxdCanvas(ACanvas).RequiredState([csHandleValid]);\r\n  BitBlt(ACanvas.Handle, Rect.Left, Rect.Top, W, H, BufferDC, 0, 0, SRCCOPY);\r\n\r\n  SelectObject(BufferDC, OldBufferBitmap);\r\n  DeleteObject(BufferBitmap);\r\n  DeleteDC(BufferDC);\r\n  BufferBitmap := 0;\r\nend;<\/pre>\n<p>\u663e\u793a\u4e2d\u4e3b\u8981\u7279\u522b\u5904\u7406\u7684\u5730\u65b9\u5c31\u662f\u533a\u5206\u662f\u5426\u4e3a32\u4f4d\u7684\u5e26\u900f\u660e\u901a\u9053\u56fe\u6807\u3002\u4e0d\u5e26\u900f\u660e\u901a\u9053\u7684\uff0c\u4f7f\u7528MASK\u5c42\u8fdb\u884c\u900f\u660e\u5904\u7406\u3002<\/p>\n<p>(END)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>icon\u662f\u4e00\u79cd\u56fe\u6807\u683c\u5f0f\uff0c\u7528\u4e8e\u7cfb\u7edf\u56fe\u6807\u3001\u8f6f [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[8],"tags":[75],"class_list":["post-698","post","type-post","status-publish","format-standard","hentry","category-delphi","tag-icon"],"views":4816,"_links":{"self":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/698","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=698"}],"version-history":[{"count":1,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/698\/revisions"}],"predecessor-version":[{"id":699,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=\/wp\/v2\/posts\/698\/revisions\/699"}],"wp:attachment":[{"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.qdac.cc\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}