Cursor.Current 与 this.Cursor
.Net 中的 Cursor.Current
和 this.Cursor
(其中 this
是 WinForm)之间有区别吗? 我一直使用 this.Cursor
并且运气很好,但我最近开始使用 CodeRush,只是在“等待光标”块中嵌入一些代码,CodeRush 使用了 Cursor.Current
属性。 我在互联网上和工作中看到其他程序员在使用 Cursor.Current
属性时遇到了一些问题。 这让我想知道两者是否有区别。 提前致谢。
我做了一个小测试。 我有两个winform。 我单击 form1 上的按钮,将 Cursor.Current
属性设置为 Cursors.WaitCursor
,然后显示 form2。 两种形式的光标都不会改变。 它仍然是 Cursors.Default
(指针)光标。
如果我在 form1 上的按钮单击事件中将 this.Cursor
设置为 Cursors.WaitCursor
并显示 form2,则等待光标仅显示在 form1 上,默认光标位于 form2 上是期待。 所以,我仍然不知道 Cursor.Current
是做什么的。
Is there a difference between Cursor.Current
and this.Cursor
(where this
is a WinForm) in .Net? I've always used this.Cursor
and have had very good luck with it but I've recently started using CodeRush and just embedded some code in a "Wait Cursor" block and CodeRush used the Cursor.Current
property. I've seen on the Internet and at work where other programmers have had some problems with the Cursor.Current
property. It just got me to wondering if there is a difference in the two. Thanks in advance.
I did a little test. I have two winforms. I click a button on form1, set the Cursor.Current
property to Cursors.WaitCursor
and then show form2. The cursor doesn't change on either form. It remains Cursors.Default
(pointer) cursor.
If I set this.Cursor
to Cursors.WaitCursor
in the button click event on form1 and show form2, the wait cursor only shows on form1 and the default cursor is on form2 which is expected. So, I still don't know what Cursor.Current
does.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
Windows 向包含鼠标光标的窗口发送 WM_SETCURSOR 消息,使其有机会更改光标形状。 像 TextBox 这样的控件就利用了这一点,将光标更改为 I-bar。 Control.Cursor 属性决定将使用什么形状。
Cursor.Current 属性直接更改形状,无需等待 WM_SETCURSOR 响应。 在大多数情况下,这种形状不太可能长期存在。 一旦用户移动鼠标,WM_SETCURSOR 就会将其更改回 Control.Cursor。
.NET 2.0 中添加了 UseWaitCursor 属性,以便更轻松地显示沙漏。 不幸的是,它的效果不是很好。 它需要 WM_SETCURSOR 消息来更改形状,并且当您将属性设置为 true 然后执行需要一段时间的操作时,这种情况不会发生。 试试这个代码,例如:
光标永远不会改变。 为了将其敲定,您还需要使用 Cursor.Current。 这里有一个小帮助器类,可以让它变得简单:
并像这样使用它:
Windows sends the window that contains the mouse cursor the WM_SETCURSOR message, giving it an opportunity to change the cursor shape. A control like TextBox takes advantage of that, changing the cursor into a I-bar. The Control.Cursor property determines what shape will be used.
The Cursor.Current property changes the shape directly, without waiting for a WM_SETCURSOR response. In most cases, that shape is unlikely to survive for long. As soon as the user moves the mouse, WM_SETCURSOR changes it back to Control.Cursor.
The UseWaitCursor property was added in .NET 2.0 to make it easier to display an hourglass. Unfortunately, it doesn't work very well. It requires a WM_SETCURSOR message to change the shape and that won't happen when you set the property to true and then do something that takes a while. Try this code for example:
The cursor never changes. To whack that into shape, you'll need to use Cursor.Current as well. Here is a little helper class to make it easy:
And use it like this:
我相信 Cursor.Current 是当前正在使用的鼠标光标(无论它在屏幕上的位置),而 this.Cursor 是当鼠标经过窗口时将设置的光标。
I believe that Cursor.Current is the mouse cursor currently being used (regardless of where it is on the screen), while this.Cursor is the cursor it will be set to, when the mouse passes over your window.
this.Cursor
是当鼠标悬停在this
引用的窗口上时将使用的光标。 Cursor.Current 是当前鼠标光标,如果鼠标位于不同的窗口上,则可能与 this.Cursor 不同。this.Cursor
is the cursor that will be used when the mouse is over the window referred to bythis
.Cursor.Current
is the current mouse cursor, which might be different fromthis.Cursor
if the mouse is over a different window.实际上,如果您想从另一个线程使用 HourGlass ,则会返回跨线程异常,因为您试图从与最初创建表单不同的线程访问 f.Handle 。 使用 GetForegroundWindow() 而不是 user32.dll。
进而
Actually if you would like to use HourGlass from another thread that will give you back cross-threading exception because you are trying to access f.Handle from different thread than form was originally created. Use GetForegroundWindow() instead from user32.dll.
and then
我注意到关于设置光标的一个有趣的事情,所以我想澄清我自己之前的一些误解,我希望它也可以帮助其他人:
设置表单的光标时,
当您尝试使用this.cursor = Cursors.Waitcursor
您实际上是为控件而不是整个表单设置光标,因为光标是 Control 类的属性。
当然,只有当鼠标实际位于实际控件(明确地表单区域)上时,光标才会更改为给定的光标,
正如 Hans Passant 已经指出的那样:
知道窗口是否直接向控件发送消息,或者表单是否根据鼠标位置将这些消息中继到其子控件,我很可能猜测第一种方法,因为当我使用重写的 WndProc 获取消息时表单控件,例如,当我位于文本框上方时,表单不处理任何消息。 (请有人澄清这一点)
基本上我的建议是不要使用 this.cursor 并坚持使用 this.usewaitcursor,因为这会将所有子控件的光标属性更改为 waitcursor。
这个问题也与应用程序级别的 Application.usewaitcursor 相同,当您的光标没有位于一个/多个表单上时,Windows 不会发送 WM_SETCURSOR 消息,因此,如果您在移动之前启动一个耗时的同步操作,将鼠标悬停在表单区域上时,表单只能在耗时的同步操作完成后才能处理此类消息。
(我根本不建议在 UI 线程中运行耗时的任务,主要是这就是导致这里问题的原因)
我对 Hans Passant 的答案做了一些改进,因此沙漏可以在应用程序级别或表单级别设置,还可以避免跨线程操作调用中的 InvalidOperationException:
要在应用程序级别使用它:
要在表单级别使用它,您可以用于当前活动表单:
或者您可以像这样初始化表单中的局部变量:
并在稍后使用它try catch finally 块
I have noticed an interesting thing about setting cursors, so I would like to clear some misunderstandings that I myself had before and I hope it may help others too:
When you try to set a form's cursor by using
this.cursor = Cursors.Waitcursor
you actually set the cursor for the control and not the whole form since cursor is property of the Control class.
Also of course the cursor will only be changed to the given cursor when the mouse is actually over the actual control (explicitly the form's area)
As Hans Passant has already stated that:
I don't know if windows sends messages directly to controls or if the form relays those messages to it's child controls based on mouse position, I'd most likely guess on the first method since when i fetched the messages with overriding WndProc of the form control, when i was over the textbox for example, the form didn't process any messages. (please someone give clarity on this)
Basically my suggestion would be to reside from using this.cursor also and stick to this.usewaitcursor, since that changes the cursor property to waitcursor for all child controls.
The problem with this is also the same as with the application level Application.usewaitcursor, while you are not over the form/forms with your cursor no WM_SETCURSOR message is being sent by windows, so if you start a time consuming synchronous operation before moving your mouse over the form's area, the form can only process such message when the time consuming synchronous operation finishes.
(I would not suggest running time consuming tasks in the UI thread at all, mainly this is what is causing the issue here)
I made a little improvement on Hans Passant's answer, so the hourglass can be either set on application level or form level, also avoiding InvalidOperationException from cross threaded operation calls:
To use it on application level:
For using it on form level you can either use for the current active form:
or you can initialize a local variable in the form like this:
and use it later in a try catch finally block
当 LongRunningOperation() 处理消息时,这对我来说非常有用。
This works great for me when the LongRunningOperation() is processing messages.
来自 VB.net VS 2012
From VB.net VS 2012
Hans Passant 的代码对我来说没有用,因为我经常在一个类中设置等待光标并在另一个类中重置它。
例如,用户单击“连接”按钮,显示等待光标,在后台线程中建立连接,并且当准备就绪时,必须将光标重置为正常。
Hans 的 Hourglass 类对于这种情况来说太不灵活了。
此外,设置光标也不需要 Windows 消息。
我在 Utils 类中使用它:
The code from Hans Passant is not useful for me because it happens very often that I set the wait cursor in one class and reset it in another class.
For example the user clicks a button "Connect", the wait cursor is shown, in a background thread a connection is established and when it is ready the cursor must be reset to normal.
The Hourglass class from Hans is too unflexible for this scenario.
Also a Windows Message is not required to set the cursor.
I use this in a class Utils: