如何在c#中渲染鼠标光标纹理

本文关键字:鼠标 光标 纹理 | 更新日期: 2024-09-23 01:08:56

以下是迄今为止我所拥有的:

[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步)都调用这个方法,所以我可以相信,如果有一个更新步骤,它会很快出现,就像这个一样。内存泄漏在哪里?或者这里还有其他问题吗?

如何在c#中渲染鼠标光标纹理

public IntPtr hbmMask;
public IntPtr hbmColor;

在调用GetIconInfo()之后,这两个字段最终都包含位图句柄,并且必须通过对DeleteObject()的p/invoke调用来释放这些句柄。

不要忘记在调用者中处理bmp