wait cursor

  • Thread starter Thread starter Vlad Simionescu
  • Start date Start date
V

Vlad Simionescu

Hello

I'm trying to let my Windows Form application perform a lengthy
operation while displaying a progress bar in a modal dialog window;
the dialog has a cancel button. The dialog is displayed in the main
thread while the work is done in a background thread. I managed to do
it except for one minor problem: I want the cursor to be hourglass
when it is over the main window and be normal (arrow) when it is over
the dialog box. I cannot do it. Setting the Cursor property of the
main window to Cursors.WaitCursor (before displaying the dialog) won't
help, though I expected it would, and I know of nothing else I could
do. I searched Google thoroughly (as much as I could) and to my
surprise couldn't find any answer.
(Instead, I can make the cursor hourglass on the dialog window, by
setting its Cursor property, but it's not at all how it should
behave.)

Please help me if anybody knows what is to be done. I suppose it's
either a simple call I don't know or a problem with .NET / C# (I'm
writing in C#, I forgot to mention).

V. Simionescu
 
Hi Vlad,
I'm trying to let my Windows Form application perform a lengthy
operation while displaying a progress bar in a modal dialog window;
the dialog has a cancel button. The dialog is displayed in the main
thread while the work is done in a background thread. I managed to do
it except for one minor problem: I want the cursor to be hourglass
when it is over the main window and be normal (arrow) when it is over
the dialog box. I cannot do it. Setting the Cursor property of the
main window to Cursors.WaitCursor (before displaying the dialog) won't
help, though I expected it would, and I know of nothing else I could
do. I searched Google thoroughly (as much as I could) and to my
surprise couldn't find any answer.
(Instead, I can make the cursor hourglass on the dialog window, by
setting its Cursor property, but it's not at all how it should
behave.)

Please help me if anybody knows what is to be done. I suppose it's
either a simple call I don't know or a problem with .NET / C# (I'm
writing in C#, I forgot to mention).

I think you've found a bug.

The Windows API requires that the cursor must be periodically
(on WM_SETCURSOR) repainted, when it doesn't match the window's
class cursor. WinForms seems not to repaint the cursor, when the
form is blocked by a modal dialog.

Here a workaround using the plain old WndProc. Put the code
into your main form.

const int WM_SETCURSOR = 32;

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_SETCURSOR && Cursor == Cursors.WaitCursor)
{
// refresh the cursor
Cursor = Cursors.WaitCursor;
}
}

Not very smart, but it does its job.

Salut
Rob
 
Robert Jordan said:
I think you've found a bug.

The Windows API requires that the cursor must be periodically
(on WM_SETCURSOR) repainted, when it doesn't match the window's
class cursor. WinForms seems not to repaint the cursor, when the
form is blocked by a modal dialog.

Here a workaround using the plain old WndProc. Put the code
into your main form.

const int WM_SETCURSOR = 32;

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_SETCURSOR && Cursor == Cursors.WaitCursor)
{
// refresh the cursor
Cursor = Cursors.WaitCursor;
}
}

Not very smart, but it does its job.

Salut
Rob


Thanks a lot.
It worked, though not exactly as you wrote it. I had to replace

Cursor = Cursors.WaitCursor;

with

Cursor.Current = Cursors.WaitCursor;

otherwise it issued a stack overflow exception. I don't know exactly
why, I'm not an expert in Win API details, I just supposed it had to
do with the fact that setting Cursor might trigger other events that
in turn lead to a new call of WndProc. Since I knew that setting
Cursor.Current is "local", I tried it and it worked. So, for others
interested, the exact code that worked for me is:

const int WM_SETCURSOR = 32;

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_SETCURSOR && Cursor == Cursors.WaitCursor)
{
// refresh the cursor
Cursor.Current = Cursors.WaitCursor;
}
}

So I guess it really was a bug. Curious, isn't it ? Not that there was
a bug, but that it seems no one noticed it before, I would think that
setting the cursor to hourglass on the main window during a progress
dialog is the obvious thing to do. Maybe they did notice it and I
didn't find their postings.

One last "personal touch" - did you say Salut on purpose ? It's
romanian for Hello, and I am romanian, as can be seen from my e-mail
(or maybe from my name).

Salut yourself, and thanks again.
Vlad
 
Hi Vlad,
Thanks a lot.

You're welcome.
It worked, though not exactly as you wrote it. I had to replace

Cursor = Cursors.WaitCursor;

with

Cursor.Current = Cursors.WaitCursor;

Sorry for that. I had to wrote the code from memory after I've
closed the project w/out saving into the clipboard.
One last "personal touch" - did you say Salut on purpose ? It's
romanian for Hello, and I am romanian, as can be seen from my e-mail
(or maybe from my name).

Actually it was your name. I used to speak romanian, but now
it seems that I'm confusing greetings with saying goodbye ;-)

bye
Rob
 
Actually, I think the best way is like this:

const int WM_SETCURSOR = 32;

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_SETCURSOR)
{
// refresh the cursor
Cursor.Current = Cursor;
}
}

This way it will draw the right cursor (from the Cursor property)
whatever that is; like it was before it worked only for WaitCursor.
Practically it fixes what the base WndProc should have done and
doesn't.
I used to speak romanian,

That makes you a very rare case among westerners, I guess.
but now it seems that I'm confusing greetings with saying goodbye ;-)

Not at all, Salut is used also for goodbye, it's general. It's latin,
BTW, the romans used it too or something very close. "Morituri te
salutant", as you may know. (I may be slightly off-topic here, sorry.
;) )

Bye.
Vlad
 
Actually, I think the best way is like this:

...

if (m.Msg == WM_SETCURSOR)
{
// refresh the cursor
Cursor.Current = Cursor;
}

Seems that's not quite OK, this way it won't paint the window resize
cursor at the edges of the window. I think after all it's best like it
was before:

const int WM_SETCURSOR = 32;

protected override void WndProc (ref Message m)
{
base.WndProc (ref m);
if (m.Msg == WM_SETCURSOR && Cursor == Cursors.WaitCursor)
{
// refresh the cursor
Cursor.Current = Cursor;
}
}
 
Back
Top