在没有实际表单显示的情况下进入表单模态消息循环
本文关键字:表单 模态 循环 消息 情况下 显示 | 更新日期: 2023-09-27 17:49:13
我有一个WinForms应用程序,其中一个主要形式是MainForm
。这个应用程序在一定的时间间隔内调用了一些预定的操作。这个操作需要很多时间来执行,所以它是在后台线程中启动的。运行时显示有进度的表格- LoaderForm
。该形式通过loader.ShowDialog(mainForm)
表示为模态;
这个工作正常,除非操作开始时:
-
MainForm
在任务栏被最小化 -
MainForm
隐藏在托盘中(根本不显示在任务栏中)
LoaderForm
,除非应用程序被激活。问题是,即使MainForm
在没有适当处理的情况下在视觉上不可见,LoaderForm
也会显示出来。
实现预期行为的最简单方法是什么?
示例代码
Imports System.ComponentModel
Public Class MainForm
Private Sub Timer_Tick(sender As Object, e As EventArgs) Handles uiTimer.Tick
uiTimer.Enabled = False
Using loader = New LoaderForm()
loader.ShowDialog(Me)
End Using
End Sub
End Class
Public Class LoaderForm
Private Sub LoaderForm_Shown(sender As Object, e As EventArgs) Handles MyBase.Shown
worker.RunWorkerAsync()
End Sub
Private Sub Worker_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles worker.RunWorkerCompleted
Me.Close()
End Sub
End Class
我们可以通过调用未记录的 Win32 api BeginModalMessageLoop
和EndModalMessageLoop
来创建一个新的模态消息循环,而无需实际显示模态对话框。
注意:这些api没有文档记录,所以我们不应该实际使用它们。
//Capture method reference using reflection
_methodBeginLoop = FindMethod(typeof (Application), "BeginModalMessageLoop");
_methodEndLoop = FindMethod(typeof (Application), "EndModalMessageLoop");
private static MethodInfo FindMethod(Type type, string methodName)
{
const BindingFlags BINDING_FLAGS = BindingFlags.Static | BindingFlags.NonPublic;
MemberInfo[] members = type.FindMembers(MemberTypes.Method, BINDING_FLAGS,
new MethodFilter(methodName).Matches, null);
if (members.Length == 1)
return members[0] as MethodInfo;
return null;
}
对于阻塞主表单上的输入,可以使用
Application.OpenForms[0].Invoke(new Action(() =>
{
_methodBeginLoop.Invoke(null, null);
}
对于UnBlocking在main form上的输入,可以使用
Application.OpenForms[0].Invoke(new Action(() =>
{
_methodEndLoop.Invoke(null, null);
}