首页 > 解决方案 > 如何知道是否在应用程序 C# 中创建了任何表单?

问题描述

我知道有从表单类继承的类的事件处理程序。通过使用这些事件,我们可以了解是否创建了表单。例如表单加载事件处理程序。我正在从事由太多表格组成的几乎大型项目。在这个项目中,用户可以创建多个工作空间,并在每个工作空间中打开不同的表单。当用户关闭工作区时,所有相关的表单都应该关闭。为了实现此功能,我考虑了一个字典,其中包含工作区 id 的键,其值是相关的打开表单。因此,我应该在用户打开表单时添加这些值。如果我向每个表单加载的事件处理程序添加一行代码,则可以做到这一点,但这需要时间。我想知道我是否可以理解从主窗体打开一个窗体。

ps:我熟悉Application.Openforms。在这种情况下没有帮助。

标签: c#.netwinforms

解决方案


感谢@Jimi 和@TnTinMn。最简单的解决方案(需要更少的努力)是使用WindowOpenedEvent。此事件侦听器识别已打开的窗口。值得一提的是,当在您的操作系统上打开任何窗口时,都会引发此事件。我们可以将打开/创建的窗口的进程 ID 与我们的应用程序进程 ID 进行比较,以了解哪个表单与应用程序相关。请注意,应将UIAutomationClientUIAutomationType DLL 添加到项目中。这些 DLL 位于: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\UIAutomationClient.dll

我已将以下代码添加到 Program.cs 文件中。

           MainForm mainForm = new MainForm();
           Automation.AddAutomationEventHandler(
           WindowPattern.WindowOpenedEvent, AutomationElement.RootElement,
           TreeScope.Subtree, (uiElm, evt) =>
           {
               AutomationElement element = uiElm as AutomationElement;
               if (element == null) return;
               try
               {
                   if (element.Current.ProcessId == Process.GetCurrentProcess().Id)
                   {
                       IntPtr elmHandle = (IntPtr)element.Current.NativeWindowHandle;
                       Form form = Application.OpenForms.OfType<Form>()
                           .Where(f => (f.AccessibilityObject as Control.ControlAccessibleObject).Handle == elmHandle)
                           .FirstOrDefault();
                       mainForm.UpdateTabFormsDict(form); // adding a open form to the current tab
                   }
               }
               catch (ElementNotAvailableException)
               { /* May happen when Debugging => ignore or log */
               }
           });

有关更多信息,您可以在任何表单加载时查看 Run 事件。WindowPattern 还提供WindowClosedEvent


推荐阅读