2

对不起,很长的帖子!恐怕我有一些解释要做......我有一个不使用 WinForms 的应用程序(在 Unity3d 中,但用于 Windows),所以我不能使用属于 System.Windows.Forms 命名空间的 Cursor 类. 但同样,我希望能够设置光标的当前形状。

经过大量研究和谷歌搜索,我发现这可以通过对 user32.dll 中某些方法的 P/Invoke 调用来实现。我得到它(有点)工作:

使用以下命令查找窗口句柄:

    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

并为类名提供 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 首先将光标设置为类光标,然后立即将其设置为我想要使用的自定义光标设置光标。这种情况可以通过将类游标设置为空来补救。这样做会导致系统不绘制光标并期望应用程序为每个窗口消息设置光标,而这正是我正在做的事情,所以它会阻止他们争夺谁来设置光标并消除闪烁。这记录在 MSDN 上:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms648393%28v=vs.85%29.aspx

他们解释说必​​须将类光标设置为空。但这就是我的知识不足的地方。:( 类光标是使用 SetClassLong 设置的,如上面的文章中所述。

但是游标的新值的数据类型是 IntPtr。此数据类型不可为空,如果我传入 null,编译器会抱怨,并且传入 IntPtr.zero 不起作用。那么我该如何完成文章的建议呢?如何使用 P/Invoke 将类光标设置为空?

4

0 回答 0