Win32の進行状況ダイアログを使用しています。最もひどいことは、私が電話するときです:
progressDialog.StopProgressDialog();
消えません。ユーザーがマウスをその上に移動するまで画面に表示されたままになり、その後突然消えます。
の呼び出しStopProgressDialog
はすぐに戻ります(つまり、同期呼び出しではありません)。呼び出しが戻った後に何かをすることでこれを証明できます:
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();
}
フォーム:
- 灰色で始まります
- 見つめていることを示すために赤に変わります
- 灰色に戻り、停止と呼んだことを示します
StopProgressDialog
したがって、進行状況ダイアログがまだそこにあり、私をあざけり、メッセージを表示していることを除いて、への呼び出しが戻ってきました。
進行状況ダイアログの停止
10秒間表示されない
さらに、進行状況ダイアログは、
System.Threading.Thread.Sleep(10000);
10秒の睡眠が終わりました。
.NETWinFormsに限定されません
同じコードがDelphiでも失敗します。これは、Windowのウィンドウのオブジェクトラッパーでもあります。
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
StopProgressDialog
失敗した場合は例外がスローされます。
IProgressDialogのほとんどのメソッドは、C#(またはDelphi)に変換されると、失敗したCOMHRESULTSを母国語の例外に変換するコンパイラの自動メカニズムを使用します。
つまり、COM呼び出しがエラーHRESULT(つまり、ゼロ未満の値)を返した場合、次の2つのシグニチャは例外をスローします。
//C#
void StopProgressDialog();
//Delphi
procedure StopProgressDialog; safecall;
以下では、HRESULTを確認し、自分で反応することができます。
//C#
[PreserveSig]
int StopProgressDialog();
//Delphi
function StopProgressDialog: HRESULT; stdcall;
HRESULTは32ビット値です。上位ビットが設定されている場合(または値が負の場合)、エラーになります。
私は前者の構文を使用しています。したがって、StopProgressDialog
がエラーを返す場合、それは自動的に言語例外に変換されます。
注:構文を使用したSaGの[PreserveSig]
場合、返されるHRESULTはゼロです。
MsgWait?
症状は、レイモンド・チェンがかつて説明したものと似ています。これは、PeekMessageとそれに続くMsgWaitForMultipleObjectsの誤った使用に関係しています。
「プログラムが動かなくなって、必要なレコードより1つ少ないレコードが報告されることがあります。更新する値を取得するには、マウスを動かす必要があります。しばらくすると、2つ遅れ、次に3つ遅れます...」
ただし、CLR .NET WinFormsとネイティブWin32コードで同じように失敗するため、失敗はIProgressDialogにあることを意味します。