我正在使用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);
十秒钟的睡眠结束了。
不限于 .NET WinForms
同样的代码在 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;
保留签名
StopProgressDialog
如果失败会抛出异常。
IProgressDialog 中的大多数方法,在翻译成 C#(或 Delphi)时,使用编译器将失败的 COM HRESULTS 转换为本地语言异常的自动机制。
换句话说,如果 COM 调用返回错误 HRESULT(即小于零的值),以下两个签名将引发异常:
//C#
void StopProgressDialog();
//Delphi
procedure StopProgressDialog; safecall;
而以下内容可让您查看 HRESULT 并自行做出反应:
//C#
[PreserveSig]
int StopProgressDialog();
//Delphi
function StopProgressDialog: HRESULT; stdcall;
HRESULT 是一个 32 位值。如果设置了高位(或值为负),则为错误。
我正在使用前一种语法。因此,如果StopProgressDialog
返回错误,它将自动转换为语言异常。
注意:仅对于 SaG,我使用了[PreserveSig]
语法,返回的 HRESULT 为零;
消息等待?
症状类似于Raymond Chen 曾经描述的,这与错误使用 PeekMessage 后跟 MsgWaitForMultipleObjects 有关:
“有时我的程序卡住了,报告的记录比它应该报告的少。我必须摇动鼠标才能更新值。再过一段时间,它落后了两个,然后是三个……”
但这意味着失败出现在 IProgressDialog 中,因为它在 CLR .NET WinForms 和本机 Win32 代码上同样失败。