我有表格:Splashscreen
,Search
和NewEntry
Program.cs
启动Splashscreen
,检查一些参数,并在成功(检查用户名,权限等)后打开Search
表单。从那里我可以拨打NewEntry
表格。
因为Splashscreen
是Main()
函数调用的主要表单,一旦关闭,应用程序就会关闭(这是预期的行为)。
所以我所做的就是从Splashscreen
开始,我将Search
表格作为对话框隐藏Splashscreen
,等待Search
关闭。一旦它关闭,我也关闭Splashscreen
,这一切似乎都有意义。从Search
表单我打开NewEntry
表单(点击按钮)也作为对话框(我不希望用户来回点击并创建多个NewEntry
窗口)。< / p>
今天我必须添加一个允许用户选择文件的功能。作为一个明显的选择,我使用了OpenFileDialog
。但是只要我调用.ShowDialog()
方法,整个应用就会冻结。
我在这里和其他网站上看过Windows Forms GUI hangs when calling OpenFileDialog.ShowDialog()和OpenFileDialog.ShowDialog() freezing application c#以及其他一些帖子,当我几乎失去了希望时,我遇到了这个http://wishmesh.com/2011/06/call-to-openfiledialog-or-savefiledialog-hangs-or-freezes/
我在[STAThread]
函数
Main()
属性
一个特别感兴趣的点是: 对于OpenFileDialog,必须显式设置ShowHelp属性。
还有 ......它们不必设置为true,只需将它们初始化为true或false。
因此,当我将ShowHelp
设置为true
时,对话框会显示(使用无用的“帮助”按钮)。
进一步的研究表明,当我在(new OpenFileDialog()).ShowDialog();
内或Program.cs
内执行Splashscreen
时,它的效果很好;但是,从对话框调用时,会有一个挂起(没有ShowHelp
)。此外,来自MessageBox
...
Dialog
显示正常
有没有办法让这项工作?或者我应该以不同的方式管理我的窗户?
例如,将Search
作为主启动窗口,然后在窗口显示之前,将Splashscreen
作为对话框调用,如果失败,只需关闭主窗口?但是,我如何处理NewEntry
才能展示OpenFileDialog
或FolderBrowserDialog
?
感谢。
答案 0 :(得分:3)
最让我担心的部分是当你说你有SplashScreen等待搜索关闭时。如果你这样做
if (search.ShowDialog() == DialogResult.OK)
{
Show();
}
然后你冻结了SplashScreen的UI线程。由于它是主要形式,因此不太可能按预期工作。我建议将代码改为此。
Hide(); // Hides SplashScreen
Search search = new Search();
search.ParentForm = this;
search.Show(); // Show Search without freezing SplashScreen thread
ParentForm是我添加到搜索中的公共变量。这应该是私有的,并且应该通过getter / setter访问,但这会使代码示例保持简短。
public partial class Search: Form
{
public SplashScreen ParentForm;
...
}
接下来,您需要添加一个处理程序来处理搜索表单关闭。这将显示SplashScreen。
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
ParentForm.Show();
}
进行这些更改后,OpenFileDialog显示正常工作。
答案 1 :(得分:2)
如果在program.cs
中,您正在呼叫:Application.Run(new splashscreen());
,如果是我,我会这样做,以便您可以在启动画面关闭后打开多个表单。
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
new splashscreen().ShowDialog();
Application.Run(new Search());
}
}
这将显示启动画面,然后一旦加载了所有内容,您就可以打开搜索表单并关闭启动画面,而不必调用ShowDialog()
。 (您必须致电application.End()
以结束申请。)
答案 2 :(得分:1)
我真的很感谢你对此事的帮助。
总而言之,我创建了Form1
和Form2
来测试一些代码,这就是我所拥有的(只有相关部分):
// Form1:
void Button1Click(object sender, EventArgs e)
{
Form2 f2=new Form2();
this.Hide();
f2.Show(this);
}
// Form2:
void Form2Load(object sender, EventArgs e)
{
if (this.Owner==null) throw new ArgumentException("This window must be called with the Owner property set!");
// or just ignore, or show a MessageBox and close, or use your imagination...
}
void Form2FormClosed(object sender, FormClosedEventArgs e)
{
// sanity check...
if (this.Owner!=null && !this.Owner.Visible) this.Owner.Show();
}
因此,当我调用Form2
时,我首先隐藏当前表单并使用Show()
的重载,该重载需要1个参数并设置Form2
的{{1}}属性。或者,我可以拨打Owner
,然后拨打f2.Owner=this;
然后当f2.Show();
关闭/之后,我检查所有者是否已设置并显示该表单。
现在回到最初的问题,这里是Form2
里面的内容:
Program.cs
现在if ((new Splashscreen()).ShowDialog() == DialogResult.OK)
Application.Run(new Search());
仅显示Search
是否随Splashscreen
一起返回,而当DialogResult.OK
关闭时,应用程序会正常退出。
感谢您的帮助。
这节省了我很多时间。
P.S。
我希望我能将这两个答案标记为答案,然后掷硬币并随机标记一个。