很抱歉这篇长篇文章!我有一些解释要做,我害怕...我有一个不使用WinForms的应用程序(在Unity3d中,但对于Windows),所以我不能使用Cursor类,它是System.Windows.Forms命名空间的一部分。但同样,我希望能够设置光标的当前形状。
经过大量研究和谷歌搜索,我发现使用P / Invoke调用user32.dll中的某些方法是可能的。我得到了(有点)工作:
使用以下方法查找窗口的句柄:
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
为windameame的类名和窗口标题提供null。然后使用返回的IntPtr调用它:
[DllImport("user32.dll")]
public static extern IntPtr SetClassLong(IntPtr hwnd, int index, IntPtr dwNewLong);
为索引提供“-4”以将指针指向处理所有低级窗口消息的WindowProc,然后使用:
System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate()
生成指向我在托管代码中实现的新WndProc委托的本机指针。它的签名如下:
public long WndProc(IntPtr hwnd, uint msg, uint wparam, int lparam);
总之,我基本上用托管回调覆盖了本机窗口过程,然后我负责处理所有窗口消息。但是我对重写标准窗口过程的整个实现并不感兴趣,我只是希望能够控制光标在窗口上时绘制鼠标光标形状的方式。因此,为此,我可以使用此函数调用默认窗口proc:
[DllImport("user32.dll")]
public static extern long DefWindowProc(IntPtr hwnd, uint msg, uint wparam, int lparam);
然后立即使用以下方法将光标设置为其他内容:
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr SetCursor(IntPtr hCursor);
这种作品。 :)我说“有点”,因为我看到一些闪烁发生,因为默认窗口proc首先将光标设置为类光标,然后立即,我的实现将其设置为我想要使用的自定义光标的setCursor。通过将类游标设置为null可以解决这种情况。这样做会导致系统不绘制光标并期望应用程序为每个窗口消息设置光标,这正是我正在做的事情,所以它会阻止他们争取谁设置光标并消除闪烁。这在MSDN上记录:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648393%28v=vs.85%29.aspx
他们解释说必须将类游标设置为null。但那是我的知识不足的地方。 :(类游标使用SetClassLong设置,如上文所述。
但是游标新值的数据类型是IntPtr。此数据类型不可为空,如果我传入null,编译器会抱怨,并且传入IntPtr.zero不起作用。那么我该如何完成文章建议呢?如何使用P / Invoke将类游标设置为null?