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.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
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;
|
||||
private bool _keepUpdating = true;
|
||||
public WindowManager()
|
||||
@ -15,14 +16,46 @@ public class WindowManager : IDisposable
|
||||
{
|
||||
while (_keepUpdating)
|
||||
{
|
||||
Windows.Clear();
|
||||
WindowInfo[] windowInfoBefore = WindowInfos;
|
||||
IntPtr[] zOrderBefore = WindowZOrder;
|
||||
_windows.Clear();
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
WindowPlacement windowPlacement = new ();
|
||||
@ -43,38 +76,11 @@ public class WindowManager : IDisposable
|
||||
if (windowTitle.Length < 1)
|
||||
return true;
|
||||
|
||||
Windows.Add(new WindowInfo(windowHandle, windowTitle, processInfo, windowPlacement));
|
||||
_windows.Add(new WindowInfo(windowHandle, windowTitle, processInfo, windowPlacement));
|
||||
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()
|
||||
{
|
||||
|
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…
Reference in New Issue
Block a user