我有一个显示图像的用户控件,当鼠标悬停在控件上时,图像的名称会显示在图像下方的标签中。我已将此用户控件放在TableLayoutPanel
单元格中,这会创建一个图像表。
我试图在鼠标移过每个控件时,甚至在表单本身上更改光标。
我试过把
Cursor.Current = Cursors.Hand
在控制器的MouseEnter
事件中尝试了这个,TableLayoutPanel
甚至在父表单中没有运气。什么都没发生。为什么?
我也注意到这在用户控件中很常见,并且在输入用户控件时很难更改鼠标光标。
有没有人知道如何更改用户控件中的光标?
答案 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);
}
}
}