Windows窗体应用程序中的非抗锯齿手形光标!

βӔḺ*_*ⱫŌŔ 7 .net c# cursor winforms

好的,所以你知道在Windows Vista和Windows 7 MS中如何更改手形光标(当你将鼠标悬停在超链接上时显示的手形光标),并为它添加了更多细节,以便它具有抗锯齿效果并且边缘平滑且美观顺畅?

那么,为什么它不像Windows Forms应用程序那样?

我看着一个看起来像是由一个穴居人绘制的蹩脚手形光标,有没有办法以编程方式告诉它显示实际安装在系统中的那个?我查看了Windows目录中的Cursors文件夹,旧的手形光标甚至都没有!那么为什么WinForms仍在使用旧版本呢?我怎样才能'升级'呢?

Cod*_*ray 9

是的,WinForms控件仍然使用Windows 98/2000附带的旧式手形光标.它缺乏Aero游标附带的抗锯齿效果.这是因为.NET Framework包含自己的硬编码游标,而不是系统默认使用.我认为这是因为.NET的早期版本的目标是Windows 95之类的操作系统没有与这个游标捆绑在一起,但是还没有完成考古学来证明它.

幸运的是,它很容易强制它使用正确的.您只需告诉操作系统您希望它使用默认手形光标,然后无论用户运行程序的Windows版本是什么,即使他们已将鼠标光标更改为默认值,也是正确的主题.

最简单的方法是对现有控件进行子类化,覆盖WndProc函数以拦截WM_SETCURSOR消息,并告诉它使用系统IDC_HAND游标.你只需要一点P/Invoke魔法.

以下代码是使用该LinkLabel控件的外观示例:

public class LinkLabelEx : LinkLabel
{
    private const int WM_SETCURSOR = 0x0020;
    private const int IDC_HAND = 32649;

    [DllImport("user32.dll", CharSet=CharSet.Auto, SetLastError=true)]
    private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);

    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    private static extern IntPtr SetCursor(IntPtr hCursor);

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_SETCURSOR)
        {
            // Set the cursor to use the system hand cursor
            SetCursor(LoadCursor(IntPtr.Zero, IDC_HAND));

            // Indicate that the message has been handled
            m.Result = IntPtr.Zero;
            return;
        }

        base.WndProc(ref m);
    }
}
Run Code Online (Sandbox Code Playgroud)


Ham*_*ian 8

请原谅我复活一年的线程!!!

在搞乱原始解决方案并查看反映的LinkLabel源代码之后,我"终于"找到了一种快速而干净的方法:

using System.Runtime.InteropServices;

namespace System.Windows.Forms {
    public class LinkLabelEx : LinkLabel {
        private const int IDC_HAND = 32649;

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);

        private static readonly Cursor SystemHandCursor = new Cursor(LoadCursor(IntPtr.Zero, IDC_HAND));

        protected override void OnMouseMove(MouseEventArgs e) {
            base.OnMouseMove(e);

            // If the base class decided to show the ugly hand cursor
            if(OverrideCursor == Cursors.Hand) {
                // Show the system hand cursor instead
                OverrideCursor = SystemHandCursor;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这个类实际上做了我们想要的:它显示了没有闪烁的正确的系统手形光标,并且仅在控件的LinkArea上执行此操作.

  • 我建议不要在每次鼠标移动时创建一个新光标。这似乎是不必要的内存泄漏。相反,我会创建一个静态字段来设置一个静态只读游标变量,然后在需要时引用它。 (2认同)