将光标更改为用户控件

时间:2016-06-02 13:25:47

标签: c# .net winforms user-controls

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

我试图在鼠标移过每个控件时,甚至在表单本身上更改光标。

我试过把

Cursor.Current = Cursors.Hand

在控制器的MouseEnter事件中尝试了这个,TableLayoutPanel甚至在父表单中没有运气。什么都没发生。为什么?

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

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

2 个答案:

答案 0 :(得分:3)

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

当然,光标是一个全局资源,因此虽然它可以暂时改变,但只要鼠标指针移动到另一个控件上,就会发生上述过程并且光标将被更改回来。这是您设置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,因此设计良好的应用程序也应如此。这意味着它不应该用于标准按钮或任何看起来柔韧的东西 - 保留其用于具有弱示能力的链接,否则看起来不可点击。我无法从问题中判断出您的用例是否合适。它可能是,因为它听起来像你已经创建了一个超链接。但我觉得我应该为了未来读者的利益而提及这一点。

答案 1 :(得分:1)

在UserControl的构造函数中添加以下行:

this.Cursor = Cursors.Hand;

设置Cursor.Current和this.Cursor之间存在差异。检查this post

只是一个补充:

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

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