更新对此答案的评论指出了代码失败的原因.评估的顺序bitmap.Handle
和bitmap.Canvas.Handle
事项.由于参数评估顺序未定义,因此您的程序具有未定义的行为.这就解释了为什么x86和x64程序的行为不同.
因此,您可以通过以适当的顺序将位图句柄和设备上下文分配给局部变量,然后将这些作为参数传递给,来解决此问题GetDIBits
.但我仍然认为代码远远好于避免VCL TBitmap
类并直接使用GDI调用,如下面的代码所示.
我相信你的错误是传递位图句柄及其画布句柄.相反,你应该传递一个通过调用获得的设备上下文CreateCompatibleDC(0)
.或传递IconInfo.hbmColor
给GetDIBits
.但是不要传递TBitmap
它的画布和手柄的句柄.
我也看不到TBitmap
你创造的任何目的.你用它做的就是获得宽度和高度IconInfo.hbmColor
.您无需创建TBitmap
即可.
所以,如果我是你,我会删除TBitmap
,并用于CreateCompatibleDC(0)
获取设备上下文.这应该会大大简化代码.
您还需要删除调用返回的位图GetIconInfo
,但我想您已经知道这一点并且为了简单起见从问题中删除了该代码.
坦率地说,VCL对象正在阻碍这里.实际上直接调用GDI函数要简单得多.也许是这样的:
procedure Main; var res: Cardinal; Bits: PRGBALine; bitmap: Winapi.Windows.TBitmap; DC: HDC; buffer: TMyBitmapInfo; BitmapInfo: TBitmapInfo absolute buffer; BitsSize: Cardinal; IconInfo: TIconInfo; begin if not GetIconInfo(LoadIcon(0, IDI_WINLOGO), IconInfo) then begin Writeln('Error GetIconInfo: ', GetLastError); Exit; end; try if GetObject(IconInfo.hbmColor, SizeOf(bitmap), @bitmap) = 0 then begin Writeln('Error GetObject'); Exit; end; BitsSize := BytesPerScanline(bitmap.bmWidth, 32, 32) * abs(bitmap.bmHeight); Bits := AllocMem(BitsSize); try buffer := TMyBitmapInfo.Create(bitmap.bmWidth, abs(bitmap.bmHeight)); DC := CreateCompatibleDC(0); res := GetDIBits(DC, IconInfo.hbmColor, 0, abs(bitmap.bmHeight), Bits, BitmapInfo, DIB_RGB_COLORS); DeleteDC(DC); if res = 0 then begin Writeln('Error GetDIBits: ', GetLastError); Exit; end; Writeln('Succeed'); finally FreeMem(Bits); end; finally DeleteObject(IconInfo.hbmMask); DeleteObject(IconInfo.hbmColor); end; end;