当前位置:  开发笔记 > 编程语言 > 正文

为什么在Win64上调用GetDIBits会失败?

如何解决《为什么在Win64上调用GetDIBits会失败?》经验,为你挑选了1个好方法。



1> David Heffer..:

更新对此答案的评论指出了代码失败的原因.评估的顺序bitmap.Handlebitmap.Canvas.Handle事项.由于参数评估顺序未定义,因此您的程序具有未定义的行为.这就解释了为什么x86和x64程序的行为不同.

因此,您可以通过以适当的顺序将位图句柄和设备上下文分配给局部变量,然后将这些作为参数传递给,来解决此问题GetDIBits.但我仍然认为代码远远好于避免VCL TBitmap类并直接使用GDI调用,如下面的代码所示.


我相信你的错误是传递位图句柄及其画布句柄.相反,你应该传递一个通过调用获得的设备上下文CreateCompatibleDC(0).或传递IconInfo.hbmColorGetDIBits.但是不要传递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;

推荐阅读
牛尾巴2010
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有