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

时间:2016-04-17 23:39:51

标签: c# winapi mouse gdi

这是我到目前为止所拥有的:

[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步),所以我可以相信,如果有一个它会很快显示,就像这个一样。虽然内存泄漏在哪里?或者这里还有其他一些问题吗?

1 个答案:

答案 0 :(得分:1)

public IntPtr hbmMask;
public IntPtr hbmColor;

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

不要忘记将bmp丢弃在来电者中。