简体   繁体   中英

Get list of open WPF windows in forms application

I have a hybrid Forms/WPF application (main windows is WindowsForms) and I am trying to implement an auto logout feature to close all forms/windows except the main window.

For the forms I can call: My.Application.OpenForms

However calling System.Windows.Application.Current.Windows results in a Null Reference exception.

How can I get a list of WPF windows from Windows Forms?

We have faced a similar problem. We solved it by making the application a WPF application, instead of a Windows Forms application. This will allow you to access both the WPF System.Windows.Application.Current.Windows and the System.Windows.Forms.Application.OpenForms .

An alternative solution is to create a list of all open forms and windows in a sort of utility class and walk that list when them closing all. A base form/window could be handy here.

The solution I have found is to get all the window handles related to the process, get the window handle for the open forms and those that belong to the process, are visible and are not in the open forms list are the WPF windows.

While this may not work for all circumstances it seems to be good enough for my purposes:

<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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM