【问题标题】:Change the cursor over a user control更改用户控件上的光标
【发布时间】:2016-06-02 13:25:47
【问题描述】:

我有一个显示图像的用户控件,当将鼠标悬停在控件上时,图像的名称会显示在图像下方的标签中。我已将此用户控件放在TableLayoutPanel 单元格中,这会创建一个图像表。

当鼠标移过每个控件,甚至是表单本身时,我正在尝试更改光标。

我试着把

Cursor.Current = Cursors.Hand

在控制器的MouseEnter 事件、TableLayoutPanel 甚至在父窗体中尝试过这个,但没有任何运气。什么都没发生。为什么?

我也注意到这在用户控件中很常见,进入用户控件时很难改变鼠标光标。

有人知道如何更改用户控件中的光标吗?

【问题讨论】:

    标签: c# .net winforms user-controls


    【解决方案1】:

    在内部,每个窗口都有一个与之关联的光标。 (在 Windows 中,控件是一种窗口。)当鼠标指针移到该窗口上时,操作系统会向它发送一条消息 (WM_SETCURSOR),询问它应该显示什么光标。窗口以其关联的光标响应,系统使用它。例如,这就是文本框显示 I 型光标的方式。

    当然,光标是全局资源,所以虽然可以临时更改,但是只要鼠标指针移到另一个控件上,就会发生上述过程,光标会变回来。这就是设置Cursor.Current 时发生的情况。这对全局光标进行了临时更改,但该临时更改基本上由与您的控件关联的光标还原。当例如显示忙碌的光标时,像这样的临时更改非常方便。它使您不必记住将忙碌光标改回标准指针。

    如果您总是希望在鼠标指针悬停在控件上时显示特定光标,则需要将该光标与该控件相关联。操作系统为此提供了一种方法,并且在 WinForms 中有一个非常简单的包装器。只需将控件的Cursor property设置为您想要的任何类型的光标。这可以是系统提供的标准光标之一,也可以是您创建的自定义 Cursor 对象。您可以在设计时或在控件的构造函数中设置此属性。

    值得注意的是Cursor属性是一个环境属性,是一种特殊类型的属性。如果环境属性没有显式设置为值,它将从控件的父级继承其值。所以这意味着您可以为整个表单设置Cursor 属性,并且表单上的所有控件都将继承该值并显示相同的光标。 (在内部,每个控件实际上是一个单独的窗口,因此如果没有这个,您需要为 每个 控件设置光标。)

    不过,如果您有敏锐的眼光,您会立即发现问题。 Cursors.Hand 光标丑陋且不标准。 (这不会影响其他Cursors 选项。)由于其年代久远,WinForms 实际上并没有为此使用系统手形光标。它使用自己的硬编码黑白版本,会像拇指酸痛一样突出。如果你想修复它,这将需要一些额外的工作。 I wrote up a solution a while back that shows how to subclass and fix the built-in LinkLabel control。您可以将此调整为任何控件,包括UserControl。除名称外,所有代码都是相同的。在阅读了我在此处回答开头的背景信息后,您应该清楚代码在做什么。

    最后一个警告:Cursors.Hand 光标经常被误用。有时,您会看到人们在按钮或其他控件上使用此光标只是为了表明它可以“单击”。手形光标几乎专门用于 Web 样式的超链接。操作系统本身遵循this convention,设计良好的应用程序也应如此。这意味着它不应该用于标准按钮或任何看起来柔韧的东西——保留它用于具有弱可见性并且看起来不可点击的链接。我无法从问题中判断您的用例是否合适。可能是,因为听起来您创建了一个超链接。但我只是觉得我应该提及这一点,以使未来的读者受益。

    【讨论】:

    • 谢谢,这就是我所说的答案。
    【解决方案2】:

    在 UserControl 的构造函数中添加这一行:

    this.Cursor = Cursors.Hand;
    

    设置 Cursor.Current 和 this.Cursor 是有区别的。检查this post

    只是一个补充:

    要重置整个 UserControl 的光标,即使其中一个组成控件具有不同的光标,我们也可以使用如下函数:

    private void SetCursor(Control rootControl, Cursor cursor)
    {
        foreach (Control control in rootControl.Controls)
        {
            control.Cursor = cursor;
            if (control.HasChildren)
            {
                SetCursor(control, cursor);
            }
        }
    }
    

    【讨论】:

    • “加法”有点毫无意义。 Cursor 是环境属性。假设您没有修改这些子控件的Cursor 属性,它们将自动继承父控件的光标集。我的回答包含更多细节。
    • “假设”。我在回答中也提到了这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-23
    • 2015-08-24
    相关资源
    最近更新 更多