Moved user32Dll Imports to seperate File.
Added Z-Order.
This commit is contained in:
parent
c5e5922bee
commit
f9c1f4e739
@ -1,12 +1,13 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace OBSBlur.Window;
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
public class WindowManager : IDisposable
|
public partial class WindowManager : IDisposable
|
||||||
{
|
{
|
||||||
public readonly HashSet<WindowInfo> Windows = new(1024);
|
private readonly HashSet<WindowInfo> _windows = new(1024);
|
||||||
|
private List<IntPtr> _zOrder = GetWindowZOrder();
|
||||||
|
public IntPtr[] WindowZOrder => _zOrder.ToArray();
|
||||||
|
public WindowInfo[] WindowInfos => _windows.ToArray();
|
||||||
public int UpdateInterval = 10;
|
public int UpdateInterval = 10;
|
||||||
private bool _keepUpdating = true;
|
private bool _keepUpdating = true;
|
||||||
public WindowManager()
|
public WindowManager()
|
||||||
@ -15,14 +16,46 @@ public class WindowManager : IDisposable
|
|||||||
{
|
{
|
||||||
while (_keepUpdating)
|
while (_keepUpdating)
|
||||||
{
|
{
|
||||||
Windows.Clear();
|
WindowInfo[] windowInfoBefore = WindowInfos;
|
||||||
|
IntPtr[] zOrderBefore = WindowZOrder;
|
||||||
|
_windows.Clear();
|
||||||
EnumWindows(GetWindowInfo, 0);
|
EnumWindows(GetWindowInfo, 0);
|
||||||
|
_zOrder = GetWindowZOrder();
|
||||||
|
|
||||||
|
WindowsUpdated?.Invoke(WindowInfos);
|
||||||
|
WindowInfo[] changedWindows = WindowInfos.Where(info => !windowInfoBefore.Contains(info)).ToArray();
|
||||||
|
if(changedWindows.Length > 0)
|
||||||
|
WindowsChanged?.Invoke(windowInfoBefore.Where(b => changedWindows.Select(c => c.WindowHandle).Contains(b.WindowHandle)).ToArray(), changedWindows);
|
||||||
|
if (zOrderBefore.Length != WindowZOrder.Length)
|
||||||
|
WindowZOrderChanged?.Invoke(WindowZOrder);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IntPtr[] zOrderAfter = WindowZOrder;
|
||||||
|
for(int i = 0; i < zOrderBefore.Length; i++)
|
||||||
|
if (!zOrderBefore[i].Equals(zOrderAfter[i]))
|
||||||
|
{
|
||||||
|
WindowZOrderChanged?.Invoke(zOrderAfter);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Thread.Sleep(UpdateInterval);
|
Thread.Sleep(UpdateInterval);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
t.Start();
|
t.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public delegate void WindowsUpdatedHandler(WindowInfo[] windowInfos);
|
||||||
|
public event WindowsUpdatedHandler WindowsUpdated;
|
||||||
|
|
||||||
|
public delegate void WindowsChangedHandler(WindowInfo[] before, WindowInfo[] after);
|
||||||
|
public event WindowsChangedHandler WindowsChanged;
|
||||||
|
|
||||||
|
public delegate void WindowZOrderChangedHandler(IntPtr[] newOrder);
|
||||||
|
|
||||||
|
public event WindowZOrderChangedHandler WindowZOrderChanged;
|
||||||
|
|
||||||
private bool GetWindowInfo(IntPtr windowHandle, IntPtr lParam)
|
private bool GetWindowInfo(IntPtr windowHandle, IntPtr lParam)
|
||||||
{
|
{
|
||||||
WindowPlacement windowPlacement = new ();
|
WindowPlacement windowPlacement = new ();
|
||||||
@ -43,38 +76,11 @@ public class WindowManager : IDisposable
|
|||||||
if (windowTitle.Length < 1)
|
if (windowTitle.Length < 1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Windows.Add(new WindowInfo(windowHandle, windowTitle, processInfo, windowPlacement));
|
_windows.Add(new WindowInfo(windowHandle, windowTitle, processInfo, windowPlacement));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
||||||
|
|
||||||
private delegate bool EnumWindowsProc(IntPtr windowHandle, IntPtr lParam);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static extern bool GetWindowPlacement(IntPtr windowHandle, ref WindowPlacement lpwndpl);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern uint GetWindowThreadProcessId(IntPtr windowHandle, out uint lpdwProcessId);
|
|
||||||
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
||||||
static extern IntPtr SendMessage(IntPtr windowHandle, uint message, IntPtr wParam, [Out] StringBuilder lParam);
|
|
||||||
|
|
||||||
public static string GetWindowTextRaw(IntPtr windowHandle)
|
|
||||||
{
|
|
||||||
// ReSharper disable twice InconsistentNaming
|
|
||||||
const uint WM_GETTEXTLENGTH = 0x000E;
|
|
||||||
const uint WM_GETTEXT = 0x000D;
|
|
||||||
// Allocate correct string length first
|
|
||||||
int length = (int)SendMessage(windowHandle, WM_GETTEXTLENGTH, IntPtr.Zero, null);
|
|
||||||
StringBuilder sb = new (length + 1);
|
|
||||||
SendMessage(windowHandle, WM_GETTEXT, sb.Capacity, sb);
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
65
OBSBlur/Window/WindowManagerUser32Dll.cs
Normal file
65
OBSBlur/Window/WindowManagerUser32Dll.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
|
public partial class WindowManager
|
||||||
|
{
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern IntPtr GetForegroundWindow();
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
|
static extern IntPtr GetDesktopWindow();
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
static extern IntPtr GetTopWindow(IntPtr hWnd);
|
||||||
|
static List<IntPtr> GetWindowZOrder()
|
||||||
|
{
|
||||||
|
const uint GW_HWNDNEXT = 2;
|
||||||
|
const uint GW_HWNDLAST = 1;
|
||||||
|
IntPtr desktopWindow = GetDesktopWindow();
|
||||||
|
IntPtr topWindow = GetTopWindow(desktopWindow);
|
||||||
|
IntPtr bottomWindow = GetWindow(topWindow, GW_HWNDLAST);
|
||||||
|
|
||||||
|
IntPtr currentWindow = topWindow;
|
||||||
|
List<IntPtr> order = new();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
order.Add(currentWindow);
|
||||||
|
} while ((currentWindow = GetWindow(currentWindow, GW_HWNDNEXT)) != bottomWindow);
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
||||||
|
|
||||||
|
private delegate bool EnumWindowsProc(IntPtr windowHandle, IntPtr lParam);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool GetWindowPlacement(IntPtr windowHandle, ref WindowPlacement lpwndpl);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern uint GetWindowThreadProcessId(IntPtr windowHandle, out uint lpdwProcessId);
|
||||||
|
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
static extern IntPtr SendMessage(IntPtr windowHandle, uint message, IntPtr wParam, [Out] StringBuilder lParam);
|
||||||
|
|
||||||
|
public static string GetWindowTextRaw(IntPtr windowHandle)
|
||||||
|
{
|
||||||
|
// ReSharper disable twice InconsistentNaming
|
||||||
|
const uint WM_GETTEXTLENGTH = 0x000E;
|
||||||
|
const uint WM_GETTEXT = 0x000D;
|
||||||
|
// Allocate correct string length first
|
||||||
|
int length = (int)SendMessage(windowHandle, WM_GETTEXTLENGTH, IntPtr.Zero, null);
|
||||||
|
StringBuilder sb = new (length + 1);
|
||||||
|
SendMessage(windowHandle, WM_GETTEXT, sb.Capacity, sb);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user