title: Win32: IProgressDialog will not disappear until you mouse over it
body: <p>i'm using the <a href="http://msdn.microsoft.com/en-us/library/bb775248(VS.85).aspx" rel="nofollow noreferrer">Win32 progress dialog</a>. The damnest thing is that when i call:</p>
  
  <pre><code>progressDialog.StopProgressDialog();
  </code></pre>
  
  <p>it doesn't disappear. It stays on screen until the user moves her mouse over it - <em>then</em> it suddenly disappers. </p>
  
  <p>The call to <code>StopProgressDialog</code> returns right away (i.e. it's not a synchronous call). i can prove this by doing things after the call has returned:</p>
  
  <pre><code>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();
  }
  </code></pre>
  
  <p>The form:</p>
  
  <ul>
  <li>starts gray</li>
  <li>turns red to show we've stared</li>
  <li>turns back to gray color to show we've called <strong>stop</strong></li>
  </ul>
  
  <p>So the call to <code>StopProgressDialog</code> has returned, except the progress dialog is still sitting there, mocking me, showing the message:</p>
  
  <blockquote>
    <p>Stopping Progress Dialog</p>
  </blockquote>
  
  <p><a href="https://i.stack.imgur.com/5YXHR.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/5YXHR.png" alt="alt text"></a>
  </p>
  
  <hr>
  
  <h2>Doesn't Appear for 10 seconds</h2>
  
  <p>Additionally, the progress dialog does not appear on screen until the</p>
  
  <pre><code>System.Threading.Thread.Sleep(10000); 
  </code></pre>
  
  <p>ten second sleep is over.</p>
  
  <hr>
  
  <h2>Not limited to .NET WinForms</h2>
  
  <p>The same code also fails in Delphi, which is also an object wrapper around Window's windows:</p>
  
  <pre><code>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;
  </code></pre>
  
  <hr>
  
  <h2>PreserveSig</h2>
  
  <p>An exception would be thrown if <code>StopProgressDialog</code> was failing.</p>
  
  <p><em>Most</em> 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. </p>
  
  <p>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):</p>
  
  <pre><code>//C#
  void StopProgressDialog();
  
  //Delphi
  procedure StopProgressDialog; safecall;
  </code></pre>
  
  <p>Whereas the following lets you see the HRESULT's and react yourself:</p>
  
  <pre><code>//C#
  [PreserveSig]
  int StopProgressDialog();
  
  //Delphi
  function StopProgressDialog: HRESULT; stdcall;
  </code></pre>
  
  <p>HRESULT is a 32-bit value. If the high-bit is set (or the value is negative) it is an error.</p>
  
  <p>i am using the former syntax. So if <code>StopProgressDialog</code> is returning an error it will be automatically converted to a language exception. </p>
  
  <p><strong>Note:</strong> Just for SaG i used the <code>[PreserveSig]</code> syntax, the returned HRESULT is zero;</p>
  
  <hr>
  
  <h2>MsgWait?</h2>
  
  <p>The symptom is similar to what <a href="http://blogs.msdn.com/oldnewthing/archive/2005/02/17/375307.aspx" rel="nofollow noreferrer">Raymond Chen described once</a>, which has to do with the incorrect use of PeekMessage followed by MsgWaitForMultipleObjects:</p>
  
  <blockquote>
    <p>"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..."</p>
  </blockquote>
  
  <p>But that would mean that the failure is in IProgressDialog, since it fails equally well on CLR .NET WinForms and native Win32 code.</p>