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.