此代码在运行32位时运行正常。但是当我切换到64位时,GetObject
方法不起作用,BITMAP
struct为空。
IntPtr hBmp = ObtainValidBitmapHandleFromSystem();
BITMAP bmpData = new BITMAP();
/* BITMAP consists of four 32bit ints,
* two 16 bit uints and one IntPtr */
* 4 + sizeof(UInt16) * 2 + IntPtr.Size;
int cbBuffer = sizeof(Int32) * 4 + sizeof(UInt16) * 2 + IntPtr.Size;
NativeMethods.GetObject(hBmp, cbBuffer, out bmpData);
Bitmap bmp = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppPArgb);
本机方法实现:
private static class NativeMethods
{
[DllImport("gdi32", CharSet = CharSet.Auto)]
internal extern static int GetObject(
IntPtr hgdiobj, // handle to graphics object
int cbBuffer, // size of buffer for object information
out BITMAP lpvObject // Should be IntPtr, but we know we will use it only for BITMAP.
);
}
BITMAP结构实现(删除文档以保持代码紧凑):
[StructLayoutAttribute(LayoutKind.Sequential)]
private struct BITMAP
{
public Int32 Type;
public Int32 Width;
public Int32 Height;
public Int32 WidthBytes;
public UInt16 Planes;
public UInt16 BitsPixel;
public IntPtr Bits;
}
此代码背后的想法在此question中有详细描述。
起初我认为问题是由IntPtr
的不同大小造成的,导致cbBuffer
的大小不同,但似乎并非如此,因为更改cbBuffer
大小没有帮助。
在64位系统上使用GDI的GetObject
方法的正确方法是什么?
答案 0 :(得分:3)
问题在于这一行:
cbBuffer = sizeof(Int32) * 4 + sizeof(UInt16) * 2 + IntPtr.Size;
这适用于32位版本,因为struct的对齐没有填充。但在64位版本上,指针前有4个字节的填充。所以cbBuffer
短4个字节。
这就是问题所在。解决方案是停止自己计算大小并使用专为此目的而设计的Marshal.SizeOf()
。