|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionMaking your WinForm applications User Friendly is important. One aspect of a good user experience is informing your user that your application is unresponsive during short periods of work. This article introduces an effective and simple way of adding application wide WaitCursors using one line of start-up code. BackgroundRecently, I have been working on a WinForms project at home that occasionally performs some short (less than 5 seconds) running tasks. I wanted the user to be informed that during that short period the UI is unresponsive, so I chose to use the Using the codeFrom a developer's point of view, using the WaitCursor library could not get any simpler. Add a reference to the WaitCursor assembly and then add the following line to your application start-up code: ApplicationWaitCursor.Cursor = Cursors.WaitCursor;
That’s it!
You can of course use any ApplicationWaitCursor.Delay =
new TimeSpan(0, 0, 0, 1, 0); // Delay of 1 second
How the library came aboutDuring development of a recent WinForms project at home, I had decided to use the cursor to indicate short running tasks to the user, like so: private void DoShortRunningTask()
{
Cursor.Current = Cursors.WaitCursor;
.. do some work ..
Cursor.Current = Cursors.Default;
}
Now, before you say "Where’s the exception handling code?", I am trying to illustrate how I eventually came to my final cut of the WaitCursor library. The above code works, or, at least it works most of the time. I, of course, found that without any exception handling I could end up with the private void DoShortRunningTask() { Cursor.Current = Cursors.WaitCursor; try { .. do some work .. } finally { Cursor.Current = Cursors.Default; } } Now that’s better, I've guaranteed that the Then I remembered how I used to use C++ stack based destructors to perform tear down work upon exiting of a method: void DoShortRunningTask() { StWaitCursor cursor = new StWaitCursor(); .. do some work .. // Implicitly called ~StWaitCursor returns the Cursor to Default } But I couldn't use C# destructors the same way since you can't guarantee when a C# destructor is called since the Garbage Collector thread is responsible for that. Instead, C# uses a different language feature, the private void DoShortRunningTask()
{
using (new StWaitCursor())
{
.. do some work ..
}
}
This code, of course, requires the public class StWaitCursor : IDisposable
{
public StWaitCursor()
{
Cursor.Current = Cursors.WaitCursor;
}
public void Dispose()
{
Cursor.Current = Cursors.Default;
}
}
There, nice and simple. I found, however, that if my short running task was too short then the user sees a quick flickering of the Cursor to and from the After quite a few iterations and refactorings, I came up with what I called the Some things I foundDuring development of the WaitCursor library, I discovered that I could not set So eventually I ended up with a generic private void DoShortRunningTask()
{
using (new StWaitCursor(new TimeSpan(0, 0, 0, 0, 500))
{
.. do some work ..
}
}
However, it still meant I had to be explicit about where I wanted my Then I had an attack of brilliance and came up with the The only caveat I found was when I dragged a window around which blocks the That's where I am up to with the current WaitCursor implementation and in brief how I got there. You can easily derive from the private void SaveChanges()
{
using (new StStatusBar(stbMain, "Saving Changes...")
{
.. do some work ..
}
// StStatusBar.IDispose could return the Text
// of the StatusBar to its original value
}
Note that the source code does not contain the HistoryVersion 1.0.0.0 (12th March 2005)
Version 1.0.1.0 (16th March 2005)
|
||||||||||||||||||||||