如何判断哪个是主窗体

时间:2021-08-26 00:40:56

标签:

一. 关于定义

主窗体的定义一般有两种。第一种就是一般上,普遍意义认为是程序中第一个被创建出来的窗体,但是由于一些程序在显示主窗体之前会有一个登录或者引导窗体,在使用完了之后直接隐藏而不是关闭。这个时候,主窗体并不会是第一个窗体。所以,第二种说法就是说,包含了软件整体功能的展示性界面所在的窗体,我们称之为主窗体。

而在本文中,所有叙述中所指的主窗体都是指的是第二种定义的主窗体

二. WPF中的主窗体与引子

对于 WPF 用户来说,我们可以直接使用:

Window window = Application.Current.MainWindow;

而对于 Winform 来说就比较麻烦,因为它并没有提供任何获得主窗体的接口属性(?)。网上有的文章说可以通过

Process.GetCurrentProcess().MainWindowHandle

来判断当前的窗体是不是主窗体,经过博主的测试发现,这个方法并不能很好的判断。经过测试核实 MainWindowHandle 有如下特点:

1. 首先,虽然这个属性的名称是 MainWindowHandle,但是不能在某个进程中使用这个属性来判断哪一个窗体是进程的主窗体;进程之间获得主窗体可以考虑使用这个方式(但不是特别好用),所以这个方法适合做运行外接程序时使用,并且仅当进程有图形界面(有窗体)时,该进程才具有与其关联的主窗口。如果关联进程没有主窗口,则 MainWindowHandle 值为零。如果刚启动了一个进程,,并且想使用其主窗口句柄,则需要考虑使用 WaitForInputIdle 方法让该进程完成启动,从而确保创建了主窗体窗口的句柄。否则,将引发异常。

一般避免这个异常的代码如下:

Process startProcess=... //获得创建一个进程 startProcess.WaitForInputIdle(); Intptr handle=startProcess.MainWindowHandle;

2. 如果这个函数是在 Show(null) 或者 Application.Run(Form) 中的窗体打开的,那么这个值是这个打开窗体的句柄;如果这个函数是在 ShowDialog(null) 或者 ShowDialog(parentForm) 或者 Show(parentForm) 的时候,这个值是父级窗体的句柄;

具体的文章参考可以见下面地址链接的文章:

参考文章

三. 三种博主的方法

博主目前有如下面所述的三种处理方式,如果有更好的方式可以在评论中和博主交流。

通过公共配置类的接口方式

原理:使用 Form 作为一个公共配置类的接口,所有的上端都通过这个公共配置类来访问主窗体的对象。

这边的公共配置类的代码一般为:

/// <summary> /// 公共配置类 /// </summary> public class CommonBase { /// <summary> /// 主窗体对象的引用 /// </summary> public static Form MainForm { get; set; } }

上端调用代码,通过在使用窗体的时候,将主窗体注入到公共配置类的接口中:

//创建主窗体 Form1 form1 = new Form1(); //设置主窗体 CommonBase.MainForm = form1; //添加到消息循环 Application.Run(form1);

由于这个公共配置类 CommonBase 会作为所有类的下端,所以所有的类都可以访问到这个主窗体。

使用派生 AppliactionContext 的方式

原理:Application.Run 有多种重载的方式,我们一般使用的是

// // 摘要: // 在当前线程上开始运行标准应用程序消息循环,并使指定窗体可见。 // // 参数: // mainForm: // 一个 System.Windows.Forms.Form,它代表要使之可见的窗体。 // // 异常: // T:System.InvalidOperationException: // 主消息循环已在当前线程上运行。 public static void Run(Form mainForm);

这边传递的是一个窗体的对象;而这个 Run 方法还有一个别的重载:

// 摘要: // 在特定的 System.Windows.Forms.ApplicationContext 中,在当前线程上开始运行标准应用程序消息循环。 // // 参数: // context: // 一个 System.Windows.Forms.ApplicationContext,应用程序将在其中运行。 // // 异常: // T:System.InvalidOperationException: // 主消息循环已在此线程上运行。 public static void Run(ApplicationContext context);