Win32: IProgressDialog will not disappear until you mouse over it.
Posted
by Ian Boyd
on Stack Overflow
See other posts from Stack Overflow
or by Ian Boyd
Published on 2008-12-18T15:51:31Z
Indexed on
2010/04/17
10:03 UTC
Read the original article
Hit count: 413
i'm using the Win32 progress dialog. The damnest thing is that when i call:
progressDialog.StopProgressDialog();
it doesn't disappear. It stays on screen until the user moves her mouse over it - then it suddenly disappers.
The call to StopProgressDialog
returns right away (i.e. it's not a synchronous call). i can prove this by doing things after the call has returned:
private void button1_Click(object sender, EventArgs e)
{
//Force red background to prove we've started
this.BackColor = Color.Red;
this.Refresh();
//Start a progress dialog
IProgressDialog pd = (IProgressDialog)new ProgressDialog();
pd.StartProgressDialog(this.Handle, null, PROGDLG.Normal, IntPtr.Zero);
//The long running operation
System.Threading.Thread.Sleep(10000);
//Stop the progress dialog
pd.SetLine(1, "Stopping Progress Dialog", false, IntPtr.Zero);
pd.StopProgressDialog();
pd = null;
//Return form to normal color to prove we've stopped.
this.BackColor = SystemColors.Control;
this.Refresh();
}
The form:
- starts gray
- turns red to show we've stared
- turns back to gray color to show we've called stop
So the call to StopProgressDialog
has returned, except the progress dialog is still sitting there, mocking me, showing the message:
Stopping Progress Dialog
Doesn't Appear for 10 seconds
Additionally, the progress dialog does not appear on screen until the
System.Threading.Thread.Sleep(10000);
ten second sleep is over.
Not limited to .NET WinForms
The same code also fails in Delphi, which is also an object wrapper around Window's windows:
procedure TForm1.Button1Click(Sender: TObject);
var
pd: IProgressDialog;
begin
Self.Color := clRed;
Self.Repaint;
pd := CoProgressDialog.Create;
pd.StartProgressDialog(Self.Handle, nil, PROGDLG_NORMAL, nil);
Sleep(10000);
pd.SetLine(1, StringToOleStr('Stopping Progress Dialog'), False, nil);
pd.StopProgressDialog;
pd := nil;
Self.Color := clBtnFace;
Self.Repaint;
end;
PreserveSig
An exception would be thrown if StopProgressDialog
was failing.
Most of the methods in IProgressDialog, when translated into C# (or into Delphi), use the compiler's automatic mechanism of converting failed COM HRESULTS into a native language exception.
In other words the following two signatures will throw an exception if the COM call returned an error HRESULT (i.e. a value less than zero):
//C#
void StopProgressDialog();
//Delphi
procedure StopProgressDialog; safecall;
Whereas the following lets you see the HRESULT's and react yourself:
//C#
[PreserveSig]
int StopProgressDialog();
//Delphi
function StopProgressDialog: HRESULT; stdcall;
HRESULT is a 32-bit value. If the high-bit is set (or the value is negative) it is an error.
i am using the former syntax. So if StopProgressDialog
is returning an error it will be automatically converted to a language exception.
Note: Just for SaG i used the [PreserveSig]
syntax, the returned HRESULT is zero;
MsgWait?
The symptom is similar to what Raymond Chen described once, which has to do with the incorrect use of PeekMessage followed by MsgWaitForMultipleObjects:
"Sometimes my program gets stuck and reports one fewer record than it should. I have to jiggle the mouse to get the value to update. After a while longer, it falls two behind, then three..."
But that would mean that the failure is in IProgressDialog, since it fails equally well on CLR .NET WinForms and native Win32 code.
© Stack Overflow or respective owner