Cleanup, Namespaces, Repeated updates in WindowManager
This commit is contained in:
parent
231b592610
commit
02314701f4
2
OBSBlur.sln.DotSettings
Normal file
2
OBSBlur.sln.DotSettings
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=GETTEXTLENGTH/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -1,79 +1,3 @@
|
|||||||
using System.Diagnostics;
|
using OBSBlur.Window;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
new WindowManager();
|
|
||||||
|
|
||||||
internal class WindowManager
|
|
||||||
{
|
|
||||||
internal Dictionary<IntPtr, WINDOWPLACEMENT> placements = new();
|
|
||||||
internal Dictionary<IntPtr, string> windowTitles = new();
|
|
||||||
internal Dictionary<IntPtr, Process> processes = new();
|
|
||||||
private const int cutoffStr = 17;
|
|
||||||
public WindowManager()
|
|
||||||
{
|
|
||||||
EnumWindows(WindowPlacement, 0);
|
|
||||||
uint hwndCount = 1;
|
|
||||||
//Group and print by pid
|
|
||||||
foreach (int pid in processes.DistinctBy(kv => kv.Value.Id).Select(kv => kv.Value.Id).ToArray())
|
|
||||||
{
|
|
||||||
foreach(IntPtr hwnd in processes.Where(kv => kv.Value.Id == pid).Select(x => x.Key))
|
|
||||||
Console.WriteLine($"{hwndCount++,3} {hwnd,8} {processes[hwnd].Id,8} {processes[hwnd].ProcessName.Substring(0, Math.Min(cutoffStr, processes[hwnd].ProcessName.Length)),cutoffStr} {windowTitles[hwnd].Substring(0, Math.Min(cutoffStr, windowTitles[hwnd].Length)),-cutoffStr} {placements[hwnd]}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool WindowPlacement(IntPtr hwnd, IntPtr lParam)
|
|
||||||
{
|
|
||||||
WINDOWPLACEMENT placement = new ();
|
|
||||||
GetWindowPlacement(hwnd, ref placement);
|
|
||||||
RECT n = placement.NormalPosition;
|
|
||||||
//Do not add if Window is not a drawable
|
|
||||||
if (n is { Left: 0, Top: 0, Right: 0, Bottom: 0 })
|
|
||||||
return true;
|
|
||||||
|
|
||||||
uint pid;
|
|
||||||
GetWindowThreadProcessId(hwnd, out pid);
|
|
||||||
Process process = Process.GetProcessById((int)pid);
|
|
||||||
//nvcontainer does not have a window name
|
|
||||||
if (process.ProcessName.Equals("nvcontainer"))
|
|
||||||
return true;
|
|
||||||
string name = GetWindowTextRaw(hwnd);
|
|
||||||
//Do not add, if window does not have a name
|
|
||||||
if (name.Length < 1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
processes.Add(hwnd, process);
|
|
||||||
windowTitles.Add(hwnd, name);
|
|
||||||
placements.Add(hwnd, placement);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
||||||
|
|
||||||
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
|
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
|
||||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
||||||
|
|
||||||
|
|
||||||
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
||||||
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [Out] StringBuilder lParam);
|
|
||||||
|
|
||||||
public static string GetWindowTextRaw(IntPtr hwnd)
|
|
||||||
{
|
|
||||||
UInt32 WM_GETTEXTLENGTH = 0x000E;
|
|
||||||
UInt32 WM_GETTEXT = 0x000D;
|
|
||||||
// Allocate correct string length first
|
|
||||||
int length = (int)SendMessage(hwnd, WM_GETTEXTLENGTH, IntPtr.Zero, null);
|
|
||||||
StringBuilder sb = new (length + 1);
|
|
||||||
SendMessage(hwnd, WM_GETTEXT, sb.Capacity, sb);
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
new WindowManager();
|
@ -1,25 +1,27 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct POINT
|
public struct Point
|
||||||
{
|
{
|
||||||
public int X;
|
public int X;
|
||||||
public int Y;
|
public int Y;
|
||||||
|
|
||||||
public POINT(int x, int y)
|
public Point(int x, int y)
|
||||||
{
|
{
|
||||||
this.X = x;
|
this.X = x;
|
||||||
this.Y = y;
|
this.Y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator System.Drawing.Point(POINT p)
|
public static implicit operator System.Drawing.Point(Point p)
|
||||||
{
|
{
|
||||||
return new System.Drawing.Point(p.X, p.Y);
|
return new System.Drawing.Point(p.X, p.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator POINT(System.Drawing.Point p)
|
public static implicit operator Point(System.Drawing.Point p)
|
||||||
{
|
{
|
||||||
return new POINT(p.X, p.Y);
|
return new Point(p.X, p.Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
@ -1,11 +1,13 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct RECT
|
public struct Rectangle
|
||||||
{
|
{
|
||||||
public int Left, Top, Right, Bottom;
|
public int Left, Top, Right, Bottom;
|
||||||
|
|
||||||
public RECT(int left, int top, int right, int bottom)
|
public Rectangle(int left, int top, int right, int bottom)
|
||||||
{
|
{
|
||||||
Left = left;
|
Left = left;
|
||||||
Top = top;
|
Top = top;
|
||||||
@ -13,10 +15,10 @@ public struct RECT
|
|||||||
Bottom = bottom;
|
Bottom = bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RECT(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
|
public Rectangle(System.Drawing.Rectangle r) : this(r.Left, r.Top, r.Right, r.Bottom) { }
|
||||||
|
|
||||||
public int X
|
public int X
|
||||||
{
|
{
|
||||||
get { return Left; }
|
get { return Left; }
|
||||||
set { Right -= (Left - value); Left = value; }
|
set { Right -= (Left - value); Left = value; }
|
||||||
}
|
}
|
||||||
@ -51,37 +53,37 @@ public struct RECT
|
|||||||
set { Width = value.Width; Height = value.Height; }
|
set { Width = value.Width; Height = value.Height; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator System.Drawing.Rectangle(RECT r)
|
public static implicit operator System.Drawing.Rectangle(Rectangle r)
|
||||||
{
|
{
|
||||||
return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
|
return new System.Drawing.Rectangle(r.Left, r.Top, r.Width, r.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator RECT(System.Drawing.Rectangle r)
|
public static implicit operator Rectangle(System.Drawing.Rectangle r)
|
||||||
{
|
{
|
||||||
return new RECT(r);
|
return new Rectangle(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator ==(RECT r1, RECT r2)
|
public static bool operator ==(Rectangle r1, Rectangle r2)
|
||||||
{
|
{
|
||||||
return r1.Equals(r2);
|
return r1.Equals(r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(RECT r1, RECT r2)
|
public static bool operator !=(Rectangle r1, Rectangle r2)
|
||||||
{
|
{
|
||||||
return !r1.Equals(r2);
|
return !r1.Equals(r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(RECT r)
|
public bool Equals(Rectangle r)
|
||||||
{
|
{
|
||||||
return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
|
return r.Left == Left && r.Top == Top && r.Right == Right && r.Bottom == Bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
if (obj is RECT)
|
if (obj is Rectangle)
|
||||||
return Equals((RECT)obj);
|
return Equals((Rectangle)obj);
|
||||||
else if (obj is System.Drawing.Rectangle)
|
else if (obj is System.Drawing.Rectangle)
|
||||||
return Equals(new RECT((System.Drawing.Rectangle)obj));
|
return Equals(new Rectangle((System.Drawing.Rectangle)obj));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
|||||||
enum ShowWindowCommands
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
|
public enum ShowWindowCommands
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Hides the window and activates another window.
|
/// Hides the window and activates another window.
|
@ -1,11 +1,13 @@
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains information about the placement of a window on the screen.
|
/// Contains information about the placement of a window on the screen.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Serializable]
|
[Serializable]
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
internal struct WINDOWPLACEMENT
|
public struct WINDOWPLACEMENT
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
|
/// The length of the structure, in bytes. Before calling the GetWindowPlacement or SetWindowPlacement functions, set this member to sizeof(WINDOWPLACEMENT).
|
||||||
@ -28,17 +30,17 @@ internal struct WINDOWPLACEMENT
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The coordinates of the window's upper-left corner when the window is minimized.
|
/// The coordinates of the window's upper-left corner when the window is minimized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public POINT MinPosition;
|
public Point MinPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The coordinates of the window's upper-left corner when the window is maximized.
|
/// The coordinates of the window's upper-left corner when the window is maximized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public POINT MaxPosition;
|
public Point MaxPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The window's coordinates when the window is in the restored position.
|
/// The window's coordinates when the window is in the restored position.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public RECT NormalPosition;
|
public Rectangle NormalPosition;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the default (empty) value.
|
/// Gets the default (empty) value.
|
27
OBSBlur/Window/WindowInfo.cs
Normal file
27
OBSBlur/Window/WindowInfo.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
|
public struct WindowInfo
|
||||||
|
{
|
||||||
|
internal IntPtr WindowHandle { get; init; }
|
||||||
|
public WINDOWPLACEMENT WindowPlacement { get; init; }
|
||||||
|
public string WindowTitle { get; init; }
|
||||||
|
public Process ProcessInfo { get; init; }
|
||||||
|
|
||||||
|
public WindowInfo(IntPtr windowHandle, string windowTitle, Process processInfo, WINDOWPLACEMENT windowPlacement)
|
||||||
|
{
|
||||||
|
this.WindowHandle = windowHandle;
|
||||||
|
this.ProcessInfo = processInfo;
|
||||||
|
this.WindowPlacement = windowPlacement;
|
||||||
|
this.WindowTitle = windowTitle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
const int cutoffStr = 17;
|
||||||
|
string processNameStr = ProcessInfo.ProcessName.Substring(0, Math.Min(cutoffStr, ProcessInfo.ProcessName.Length));
|
||||||
|
string windowTitleStr = WindowTitle.Substring(0, Math.Min(cutoffStr, WindowTitle.Length));
|
||||||
|
return $"{WindowHandle,8} {ProcessInfo.Id,8} {processNameStr,cutoffStr} {windowTitleStr,-cutoffStr} {WindowPlacement}";
|
||||||
|
}
|
||||||
|
}
|
81
OBSBlur/Window/WindowManager.cs
Normal file
81
OBSBlur/Window/WindowManager.cs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OBSBlur.Window;
|
||||||
|
|
||||||
|
public class WindowManager : IDisposable
|
||||||
|
{
|
||||||
|
public readonly HashSet<WindowInfo> Windows = new();
|
||||||
|
public int UpdateInterval = 10;
|
||||||
|
private bool KeepUpdating = true;
|
||||||
|
public WindowManager()
|
||||||
|
{
|
||||||
|
Thread t = new (() =>
|
||||||
|
{
|
||||||
|
while(KeepUpdating)
|
||||||
|
EnumWindows(WindowPlacement, 0);
|
||||||
|
Thread.Sleep(UpdateInterval);
|
||||||
|
});
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool WindowPlacement(IntPtr windowHandle, IntPtr lParam)
|
||||||
|
{
|
||||||
|
WINDOWPLACEMENT windowPlacement = new ();
|
||||||
|
GetWindowPlacement(windowHandle, ref windowPlacement);
|
||||||
|
Rectangle n = windowPlacement.NormalPosition;
|
||||||
|
//Do not add if Window is not a drawable
|
||||||
|
if (n is { Left: 0, Top: 0, Right: 0, Bottom: 0 })
|
||||||
|
return true;
|
||||||
|
|
||||||
|
uint pid;
|
||||||
|
GetWindowThreadProcessId(windowHandle, out pid);
|
||||||
|
Process processInfo = Process.GetProcessById((int)pid);
|
||||||
|
//nvcontainer does not have a window name
|
||||||
|
if (processInfo.ProcessName.Equals("nvcontainer"))
|
||||||
|
return true;
|
||||||
|
string windowTitle = GetWindowTextRaw(windowHandle);
|
||||||
|
//Do not add, if window does not have a name
|
||||||
|
if (windowTitle.Length < 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
KeepUpdating = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user