如何在 win32 中获取鼠标光标的 RGB 字节数组?

How to get RGB byte array for the mouse cursor in win32?

我使用以下代码获取鼠标光标位图:

HCURSOR hCursor = (HCURSOR)LoadImage(NULL, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE);

ICONINFO info = { 0 };
BOOL ret = GetIconInfo(hCursor, &info);

当我将 info.hbmMask 位图保存到文件时,它看起来像这样:

我想用这个游标作为Direct3d9 纹理来绘图。我不知道如何将此单色位图转换为可用于创建纹理的 RGB 字节缓冲区。

或者是否有任何其他方法来获取标准 Windows 游标的 RGB 字节数组?

一个图标由两个位图组成,如ICONINFO documentation:

中所述

hbmMask
Type: HBITMAP

The icon bitmask bitmap. If this structure defines a black and white icon, this bitmask is formatted so that the upper half is the icon AND bitmask and the lower half is the icon XOR bitmask. Under this condition, the height should be an even multiple of two. If this structure defines a color icon, this mask only defines the AND bitmask of the icon.

hbmColor
Type: HBITMAP

A handle to the icon color bitmap. This member can be optional if this structure defines a black and white icon. The AND bitmask of hbmMask is applied with the SRCAND flag to the destination; subsequently, the color bitmap is applied (using XOR) to the destination by using the SRCINVERT flag.

在您的例子中,您有一个单色图标,因此 hbmColor 为 NULL,而 hbmMask 包含蒙版和颜色。上半部分与目标 AND 结合以清除像素并为图标创建一个空的 space,然后下半部分与目标 XOR 结合以填充 space 由掩码创建。

对于非单色图标,hbmMask 将按目标原样 AND 编辑,然后 hbmColorXOR 编辑为-与目标一致。

正如 Raymond Chen 在他的评论中所说,您可以“使用 GetDIBits() 从位图中提取位 ”。所以你必须从适当的 HBITMAP 中提取像素位,并根据你是否使用单色图标来处理它们。

下面介绍如何使用GetDIBits()获取游标数据的字节数组。为此,请调用 GetDIBits() 两次,一次获取光标图像的实际细节,另一次获取像素。

您可以将此代码应用于颜色和蒙版,请注意它仅 returns 32x32px 光标,即使大小已配置为其他内容。

之后,您可以同时兼顾两者。

var windowDeviceContext = User32.GetWindowDC(IntPtr.Zero);

//Initialize the bitmap header and calculate its size.
var maskHeader = new BitmapInfoHeader();
maskHeader.Size = (uint) Marshal.SizeOf(maskHeader);

//Gets the image details.
Gdi32.GetDIBits(windowDeviceContext, iconInfo.Mask, 0, 0, null, ref maskHeader, DibColorModes.RgbColors);

//If there's any data, get it.
if (maskHeader.Height != 0)
{
    //To prevent the cursor image from being inverted.
    maskHeader.Height *= -1;

    var maskBuffer = new byte[maskHeader.SizeImage];

    Gdi32.GetDIBits(windowDeviceContext, iconInfo.Mask, 0, (uint) maskHeader.Height, maskBuffer, ref maskHeader, DibColorModes.RgbColors);
}

它是 C#,但很容易转换为您选择的语言。