多线程结束阻塞第三方对话窗体的方法

最近用到了《Syncfusion Essential Studio》这个组件,这不是重点,重点是在用到 Grid 组件,想要将其导出为Excel文件时遇到了问题。

导出中组件会自己弹出一个阻塞的 MessageBox 对话窗口,窗口显示了遍历表格所用时间,标题为英文显得煞是突兀,由于直接引用的 .DLL 文件,无法将对话窗口的语句注释掉。

因为自己所用到的组件版本比较老,加之此东西比较生僻网上也很少有详实的参考资料,官网的开发文档也没找到设置取消的方法。

只能通过别的方法变通地解决这个不和谐的问题。网上找了下思路,觉得通过标题获取窗口句柄的方法来关闭窗口的方法比较合适。

以下是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//用于找到MessageBox的句柄
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//关闭窗口
[DllImport("user32.dll")]
static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);
/*.....*/
GridExcelConverterControl gridExcelContrl = new GridExcelConverterControl();
try
{
gridExcelContrl.GridToExcel(this.Grid_BatchModify, fileName /*,
ConverterOptions.ColumnHeaders | ConverterOptions.RowHeaders*/);
ptr = FindWindow(null, "窗口标题"); //查找MessageBox的弹出窗口,注意对应标题
EndDialog(ptr, out result); //查找到窗口关闭
MessageBox.Show(@"导出成功");
}
catch
{
MessageBox.Show(@"导出失败");
}
finally
{
gridExcelContrl.Dispose();
}

好了🎉,小功告成,让我们来看看效果吧……欸?!😡怎么还是有呢?仔细一看,哈哈自己逗了,窗口出来的时候是阻塞状态,后面的销毁流程是无法执行的。

看来只能让销毁函数独立于对话窗口去销毁它了,于是换个思路,用独立的线程去关闭这个窗口,我们先做个销毁的线程,让它一直循环直到获取到窗口销毁然后退出执行。

程序如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//用于找到MessageBox的句柄
[DllImport("user32.dll", EntryPoint = "FindWindow", CharSet = CharSet.Auto)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//关闭窗口
[DllImport("user32.dll")]
static extern bool EndDialog(IntPtr hDlg, out IntPtr nResult);
/*.....*/
GridExcelConverterControl gridExcelContrl = new GridExcelConverterControl();
try
{
Thread closeDlg = new Thread(delegate()
{
IntPtr ptr = IntPtr.Zero;
IntPtr result;
while (ptr == IntPtr.Zero) //循环直到找到同标题的窗口
ptr = FindWindow(null, "窗口标题"); //查找MessageBox的弹出窗口,注意对应标题
EndDialog(ptr, out result); //查找到窗口则关闭
});
closeDlg.Start();
gridExcelContrl.GridToExcel(this.Grid_BatchModify, fileName /*,
ConverterOptions.ColumnHeaders | ConverterOptions.RowHeaders*/);
MessageBox.Show(@"导出成功");
}
catch
{
MessageBox.Show(@"导出失败");
}
finally
{
gridExcelContrl.Dispose();
}

写完抓紧跑起来试试,哟嚯😁。可以了,这样一来导出的时候再也不会有烦人的英文窗口弹出来告诉你“导出用了0.00000000n秒”这件事了。

Ps:其实窗口还是存在过的,我们没法在内部跳过窗口创建的这一部,只是从外面结束掉而已,因为程序执行很快所以窗口几乎没有 show 出来就被终止掉了。

另外文中EndDialog函数在有的时候也可以用DestroyWindow这个函数,根据需要终结的窗口类型去选用,不然可能会关闭不成功哦~

这就是我的方法,希望能抛砖引玉,给需要的朋友一点思路。

谢谢😄