Moved user32Dll Imports to seperate File.

Added Z-Order.
This commit is contained in:
glax 2024-04-15 22:56:46 +02:00
parent c5e5922bee
commit f9c1f4e739
2 changed files with 105 additions and 34 deletions

View File

@ -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()
{

View 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();
}
}