如何在 C# 中渲染鼠标光标纹理?
How can I render the mouse cursor texture in c#?
这是我目前的情况:
[StructLayout(LayoutKind.Sequential)]
struct CursorInfo
{
public Int32 cbSize;
public Int32 flags
public IntPtr hCursor;
public POINT ptScreenPos;
}
[DllImport("user32.dll")]
static extern int GetSystemMetrics(SystemMetric smIndex);
public enum SystemMetric
{
SM_CXICON = 11, // 0x0B
SM_CYICON = 12, // 0x0C
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool DrawIconEx(IntPtr hdc,
int xLeft,
int yTop,
IntPtr hIcon,
int cxWidth,
int cyHeight,
int istepIfAniCur,
IntPtr hbrFlickerFreeDraw,
int diFlags);
const int DI_MASK = 0x0001;
const int DI_IMAGE = 0x0002;
const int DI_NORMAL = 0x0003;
const int DI_COMPAT = 0x0004;
const int DI_DEFAULTSIZE = 0x0008;
const int DI_NOMIRROR = 0x0010;
public struct IconInfo
{
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
Bitmap GetCursorBitmap()
{
CursorInfo ci = new CursorInfo ();
ci.cbSize = Marshal.SizeOf (typeof(CursorInfo));
if (!GetCursorInfo (ref ci)) {
throw new Exception("Failed to get cursor info");
}
IntPtr cursorPointer = ci.hCursor;
int iconWidth = GetSystemMetrics (SystemMetric.SM_CXICON);
int iconHeight = GetSystemMetrics (SystemMetric.SM_CYICON);
Bitmap bmp;
bmp = new System.Drawing.Bitmap(iconWidth, iconHeight, PixelFormat.Format32bppRgb);
bmp.MakeTransparent();
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
DrawIconEx(hdcBitmap, 0, 0, cursorPointer, iconWidth, iconHeight, 0, IntPtr.Zero, DI_NORMAL);
// DrawIcon(hdcBitmap, 0, 0, cursorPointer); has the same problem
IconInfo hotSpotInfo = new IconInfo ();
GetIconInfo(cursorPointer, ref hotSpotInfo);
Point hotSpot = new Point(hotSpotInfo.xHotspot, hotSpotInfo.yHotspot)
gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
return bmp;
}
(我在别处使用热点信息,但我省略了那部分,因为这里重要的是获取该信息)。
这工作了很长一段时间,但最终我收到一条错误消息
A null reference or invalid value was found [GDI+ status: InvalidParameter]
来自
IntPtr hdcBitmap = gfxBmp.GetHdc();
我相当确定这是由于内存泄漏造成的。我在我的应用程序中的每个更新步骤(大约每秒 30 步)调用此方法,所以我相信如果有一个它会很快出现,就像这个一样。内存泄漏在哪里?还是这里有其他问题?
public IntPtr hbmMask;
public IntPtr hbmColor;
这两个字段在调用 GetIconInfo()
后最终包含位图句柄,并且必须通过 p/invoke 调用 DeleteObject()
.
来释放这些句柄
不要忘记在调用者中处理 bmp
。
这是我目前的情况:
[StructLayout(LayoutKind.Sequential)]
struct CursorInfo
{
public Int32 cbSize;
public Int32 flags
public IntPtr hCursor;
public POINT ptScreenPos;
}
[DllImport("user32.dll")]
static extern int GetSystemMetrics(SystemMetric smIndex);
public enum SystemMetric
{
SM_CXICON = 11, // 0x0B
SM_CYICON = 12, // 0x0C
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool DrawIconEx(IntPtr hdc,
int xLeft,
int yTop,
IntPtr hIcon,
int cxWidth,
int cyHeight,
int istepIfAniCur,
IntPtr hbrFlickerFreeDraw,
int diFlags);
const int DI_MASK = 0x0001;
const int DI_IMAGE = 0x0002;
const int DI_NORMAL = 0x0003;
const int DI_COMPAT = 0x0004;
const int DI_DEFAULTSIZE = 0x0008;
const int DI_NOMIRROR = 0x0010;
public struct IconInfo
{
public bool fIcon;
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask;
public IntPtr hbmColor;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
Bitmap GetCursorBitmap()
{
CursorInfo ci = new CursorInfo ();
ci.cbSize = Marshal.SizeOf (typeof(CursorInfo));
if (!GetCursorInfo (ref ci)) {
throw new Exception("Failed to get cursor info");
}
IntPtr cursorPointer = ci.hCursor;
int iconWidth = GetSystemMetrics (SystemMetric.SM_CXICON);
int iconHeight = GetSystemMetrics (SystemMetric.SM_CYICON);
Bitmap bmp;
bmp = new System.Drawing.Bitmap(iconWidth, iconHeight, PixelFormat.Format32bppRgb);
bmp.MakeTransparent();
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
DrawIconEx(hdcBitmap, 0, 0, cursorPointer, iconWidth, iconHeight, 0, IntPtr.Zero, DI_NORMAL);
// DrawIcon(hdcBitmap, 0, 0, cursorPointer); has the same problem
IconInfo hotSpotInfo = new IconInfo ();
GetIconInfo(cursorPointer, ref hotSpotInfo);
Point hotSpot = new Point(hotSpotInfo.xHotspot, hotSpotInfo.yHotspot)
gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
return bmp;
}
(我在别处使用热点信息,但我省略了那部分,因为这里重要的是获取该信息)。
这工作了很长一段时间,但最终我收到一条错误消息
A null reference or invalid value was found [GDI+ status: InvalidParameter]
来自
IntPtr hdcBitmap = gfxBmp.GetHdc();
我相当确定这是由于内存泄漏造成的。我在我的应用程序中的每个更新步骤(大约每秒 30 步)调用此方法,所以我相信如果有一个它会很快出现,就像这个一样。内存泄漏在哪里?还是这里有其他问题?
public IntPtr hbmMask;
public IntPtr hbmColor;
这两个字段在调用 GetIconInfo()
后最终包含位图句柄,并且必须通过 p/invoke 调用 DeleteObject()
.
不要忘记在调用者中处理 bmp
。