如何让光标变成等待光标?
如何向用户显示等待/忙碌光标(通常是沙漏),让他们知道程序正在执行某些操作?
How can I display the Wait/Busy Cursor (usually the hourglass) to the user to let them know the program is doing something?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
您可以使用
Cursor.Current
。
但是,如果散列操作确实很长(MSDN 将其定义为超过 2-7 秒),您可能应该使用视觉反馈指示器而不是光标来通知用户进度。有关更深入的指南,请参阅本文。
编辑:
正如 @Am 指出的,您可能需要在
Cursor.Current = Cursors.WaitCursor;
之后调用Application.DoEvents();
以确保沙漏实际显示。You can use
Cursor.Current
.However, if the hashing operation is really lengthy (MSDN defines this as more than 2-7 seconds), you should probably use a visual feedback indicator other than the cursor to notify the user of the progress. For a more in-depth set of guidelines, see this article.
Edit:
As @Am pointed out, you may need to call
Application.DoEvents();
afterCursor.Current = Cursors.WaitCursor;
to ensure that the hourglass is actually displayed.实际上,
暂时设置等待光标,但不能确保等待光标显示到操作结束。程序中的其他程序或控件可以轻松地将光标重置回默认箭头,就像在操作仍在运行时移动鼠标时发生的情况一样。
显示等待光标的更好方法是将窗体中的 UseWaitCursor 属性设置为 true:
这将为窗体上的所有控件显示等待光标,直到将此属性设置为 false。
如果您希望等待光标显示在应用程序级别,您应该使用:
Actually,
temporarily sets the Wait cursor, but doesn’t ensure that the Wait cursor shows until the end of your operation. Other programs or controls within your program can easily reset the cursor back to the default arrow as in fact happens when you move mouse while operation is still running.
A much better way to show the Wait cursor is to set the UseWaitCursor property in a form to true:
This will display wait cursor for all controls on the form until you set this property to false.
If you want wait cursor to be shown on Application level you should use:
在前一种方法的基础上,我的首选方法(因为这是经常执行的操作)是将等待光标代码包装在 IDisposable 帮助器类中,以便它可以与 using() (一行代码)一起使用,采用可选参数,运行其中的代码,然后清理(恢复光标)。
用法:
Building on the previous, my preferred approach (since this is a frequently performed action) is to wrap the wait cursor code in an IDisposable helper class so it can be used with using() (one line of code), take optional parameters, run the code within, then clean up (restore cursor) afterwards.
Usage:
在窗体或窗口级别使用 UseWaitCursor 更容易。
典型的用例如下所示:
为了获得更好的 UI 体验,您应该从不同的线程使用异步。
It is easier to use UseWaitCursor at the Form or Window level.
A typical use case can look like below:
For a better UI experience you should use Asynchrony from a different thread.
我的方法是在后台工作人员中进行所有计算。
然后像这样更改光标:
在线程的完成事件中恢复光标:
注意,这也可以针对特定控件完成,因此仅当鼠标位于其上方时光标才会是沙漏。
My approach would be to make all the calculations in a background worker.
Then change the cursor like this:
And in the thread's finish event restore the cursor:
Note, this can also be done for specific controls, so the cursor will be the hourglass only when the mouse is above them.
对于 Windows 窗体应用程序,可选择禁用 UI 控件可能非常有用。所以我的建议如下:
用法:
For Windows Forms applications an optional disabling of a UI-Control can be very useful. So my suggestion looks like this:
Usage:
好的,我创建了一个静态异步方法。这禁用了启动操作并更改应用程序光标的控件。它将操作作为任务运行并等待完成。当调用者等待时,控制权返回给调用者。因此,即使忙碌图标旋转,应用程序也能保持响应。
这是主窗体的代码,
我必须使用单独的记录器来执行虚拟操作(我正在使用 Nlog),并且我的主记录器正在写入 UI(富文本框)。仅当在表单上的特定容器上时,我无法显示繁忙的光标(但我没有努力尝试。)所有控件都有 UseWaitCursor 属性,但它似乎对控件没有任何影响我尝试过(也许是因为它们不在顶部?)
这是主日志,它显示了按照我们期望的顺序发生的事情:
OK so I created a static async method. That disabled the control that launches the action and changes the application cursor. It runs the action as a task and waits for to finish. Control returns to the caller while it waits. So the application remains responsive, even while the busy icon spins.
Here's the code form the main form
I had to use a separate logger for the dummy action (I am using Nlog) and my main logger is writing to the UI (a rich text box). I wasn't able to get the busy cursor show only when over a particular container on the form (but I didn't try very hard.) All controls have a UseWaitCursor property, but it doesn't seem have any effect on the controls I tried (maybe because they weren't on top?)
Here's the main log, which shows things happening in the order we expect:
好吧,其他人的观点已经很清楚了,但我想做一些补充,如下:
Okey,Other people's view are very clear, but I would like to do some added, as follow:
通过下面的课程,您可以提出 Donut“异常安全”的建议。
CursorHandler 类
With the class below you can make the suggestion of Donut "exception safe".
the class CursorHandler
将其与 WPF 一起使用:
Use this with WPF:
您可以使用:
&&
You can use:
&&
一个简单的 ScopeGuard 是一个很好的帮手:
然后
A simple
ScopeGuard
is a nice helper:and then
在 .Net Windows 应用程序中对我有用的是:
不需要
Application.DoEvents();
。What worked for me in a .Net Windows Application:
No need for
Application.DoEvents();
.