更改用户控件上的光标
Change the cursor over a user control
我有一个显示图像的用户控件,当将鼠标悬停在该控件上时,图像名称会显示在图像下方的标签中。我已将此用户控件放在 TableLayoutPanel
单元格中,它创建了 table 个图像。
我试图在鼠标经过每个控件甚至表单本身时更改光标。
我试过把
Cursor.Current = Cursors.Hand
在控制器的 MouseEnter
事件、TableLayoutPanel
甚至在父表单中尝试过这个,但没有任何运气。什么都没发生。为什么?
我也注意到这在用户控件中很常见,进入用户控件时很难改变鼠标光标。
有人知道如何更改用户控件中的光标吗?
在内部,每个 window 都有一个与之关联的游标。 (在 Windows 中,控件是 window 的一种类型。)当鼠标指针移到 window 上时,操作系统向它发送一条消息 (WM_SETCURSOR) 询问它是什么应显示光标。 window 以其关联的光标响应,系统使用它。例如,这就是文本框显示 I 型光标的方式。
当然,光标是全局资源,所以虽然可以临时改变,但是一旦鼠标指针移到另一个控件上,就会发生上述过程,光标又会变回来。这就是设置 Cursor.Current
时发生的情况。这对全局游标进行了临时更改,但该临时更改实际上被与您的控件关联的游标恢复了。当 例如 显示忙碌的光标时,这样的临时更改非常方便。它使您不必记住将繁忙的光标更改回标准指针。
如果您始终希望在鼠标指针悬停在某个控件上时显示特定光标,则需要将该光标与该控件相关联。操作系统提供了执行此操作的方法,并且在 WinForms 中有一个非常简单的包装器。只需 将控件 的 Cursor
property 设置为您想要的任何类型的光标。这可以是系统提供的标准游标之一,也可以是您创建的自定义 Cursor
对象。您可以在设计时或在控件的构造函数中设置此 属性。
值得注意的是Cursor
属性是环境属性,是[=54=的一种特殊类型].如果环境 属性 没有被显式设置为一个值,它将从控件的父级继承它的值。所以这意味着您可以为整个窗体设置 Cursor
属性,并且窗体上的所有控件都将继承该值并显示相同的光标。 (在内部,每个控件实际上是一个单独的 window,因此如果没有这个,您需要为 每个 控件设置光标。)
不过,如果你眼尖的话,你会立刻发现一个问题。 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
游标经常被误用。有时,您会看到人们在按钮或其他控件上使用此光标只是为了表明它可以是 "clicked"。手形光标几乎专门用于网络样式的超链接。操作系统本身遵循 this convention,设计良好的应用程序也应如此。这意味着它不应该用于标准按钮或任何 看起来 柔韧的东西——保留它用于具有弱可见性并且看起来不可点击的链接。我无法从问题中判断您的用例是否合适。可能是,因为听起来您创建了一个超链接。但我只是觉得为了未来的读者的利益我应该提到这一点。
在 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);
}
}
}
我有一个显示图像的用户控件,当将鼠标悬停在该控件上时,图像名称会显示在图像下方的标签中。我已将此用户控件放在 TableLayoutPanel
单元格中,它创建了 table 个图像。
我试图在鼠标经过每个控件甚至表单本身时更改光标。
我试过把
Cursor.Current = Cursors.Hand
在控制器的 MouseEnter
事件、TableLayoutPanel
甚至在父表单中尝试过这个,但没有任何运气。什么都没发生。为什么?
我也注意到这在用户控件中很常见,进入用户控件时很难改变鼠标光标。
有人知道如何更改用户控件中的光标吗?
在内部,每个 window 都有一个与之关联的游标。 (在 Windows 中,控件是 window 的一种类型。)当鼠标指针移到 window 上时,操作系统向它发送一条消息 (WM_SETCURSOR) 询问它是什么应显示光标。 window 以其关联的光标响应,系统使用它。例如,这就是文本框显示 I 型光标的方式。
当然,光标是全局资源,所以虽然可以临时改变,但是一旦鼠标指针移到另一个控件上,就会发生上述过程,光标又会变回来。这就是设置 Cursor.Current
时发生的情况。这对全局游标进行了临时更改,但该临时更改实际上被与您的控件关联的游标恢复了。当 例如 显示忙碌的光标时,这样的临时更改非常方便。它使您不必记住将繁忙的光标更改回标准指针。
如果您始终希望在鼠标指针悬停在某个控件上时显示特定光标,则需要将该光标与该控件相关联。操作系统提供了执行此操作的方法,并且在 WinForms 中有一个非常简单的包装器。只需 将控件 的 Cursor
property 设置为您想要的任何类型的光标。这可以是系统提供的标准游标之一,也可以是您创建的自定义 Cursor
对象。您可以在设计时或在控件的构造函数中设置此 属性。
值得注意的是Cursor
属性是环境属性,是[=54=的一种特殊类型].如果环境 属性 没有被显式设置为一个值,它将从控件的父级继承它的值。所以这意味着您可以为整个窗体设置 Cursor
属性,并且窗体上的所有控件都将继承该值并显示相同的光标。 (在内部,每个控件实际上是一个单独的 window,因此如果没有这个,您需要为 每个 控件设置光标。)
不过,如果你眼尖的话,你会立刻发现一个问题。 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
游标经常被误用。有时,您会看到人们在按钮或其他控件上使用此光标只是为了表明它可以是 "clicked"。手形光标几乎专门用于网络样式的超链接。操作系统本身遵循 this convention,设计良好的应用程序也应如此。这意味着它不应该用于标准按钮或任何 看起来 柔韧的东西——保留它用于具有弱可见性并且看起来不可点击的链接。我无法从问题中判断您的用例是否合适。可能是,因为听起来您创建了一个超链接。但我只是觉得为了未来的读者的利益我应该提到这一点。
在 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);
}
}
}