【问题标题】:Get list of open WPF windows in forms application获取表单应用程序中打开的 WPF 窗口列表
【发布时间】:2017-02-23 09:25:36
【问题描述】:

我有一个混合表单/WPF 应用程序(主窗口是 WindowsForms),我正在尝试实现自动注销功能来关闭除主窗口之外的所有表单/窗口。

我可以拨打的表格:My.Application.OpenForms

但是调用System.Windows.Application.Current.Windows 会导致空引用异常。

如何从 Windows 窗体中获取 WPF 窗口列表?

【问题讨论】:

  • 你是如何创建 WPF 窗口的?另外,您以这种方式混合两者是否有特殊原因?
  • 是的,我们有一些较旧的应用程序正在更新以使用我们在所有应用程序中使用的通用 UI 库。 WPF 窗口正在以标准方式创建并使用 ShowDialog。

标签: c# .net wpf vb.net winforms


【解决方案1】:

我们也遇到过类似的问题。我们通过使应用程序成为 WPF 应用程序而不是 Windows 窗体应用程序来解决这个问题。这将允许您访问 WPF System.Windows.Application.Current.WindowsSystem.Windows.Forms.Application.OpenForms

另一种解决方案是在某种实用程序类中创建所有打开的窗体和窗口的列表,并在它们全部关闭时遍历该列表。一个基本的表单/窗口在这里可能很方便。

【讨论】:

  • 我会在以后研究它,但目前我不想将其保留为 Windows 窗体应用程序。谢谢
【解决方案2】:

我找到的解决方案是获取与进程相关的所有窗口句柄,获取打开表单的窗口句柄以及属于进程、可见且不在打开表单列表中的是 WPF 窗口.

虽然这可能不适用于所有情况,但对于我的目的来说似乎已经足够了:

<DllImport("user32.dll", SetLastError:=True)>
Private Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Private Delegate Function EnumWindowsProc(ByVal hWnd As IntPtr, ByVal lParam As ArrayList) As Boolean

<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function EnumWindows(ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As ArrayList) As Boolean
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function GetWindowThreadProcessId(handle As IntPtr, ByRef processId As Integer) As Integer
End Function

<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function


Public Function AutoLogout_CloseWindow(hwnd As IntPtr, windowHandles As ArrayList) As Boolean
    Dim processId As Integer
    GetWindowThreadProcessId(hwnd, processId)
    If processId = Process.GetCurrentProcess.Id Then
        windowHandles.Add(hwnd)
    End If
    Return True
End Function

Public Sub AutoLogout()

  Dim windowHandles As New ArrayList()

  EnumWindows(New EnumWindowsProc(AddressOf AutoLogout_CloseWindow), windowHandles)

  Dim openFormHandles As New List(Of IntPtr)
  For Each f As Form In My.Application.OpenForms
      openFormHandles.Add(f.Handle)
  Next

  For Each hwnd As IntPtr In windowHandles   
     If Not openFormHandles.Contains(hwnd) Then
         If IsWindowVisible(hwnd) Then              
             SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero)
         End If
     End If  
  Next

End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多