diff --git a/OBSBlur.sln.DotSettings b/OBSBlur.sln.DotSettings
new file mode 100644
index 0000000..af49136
--- /dev/null
+++ b/OBSBlur.sln.DotSettings
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file
diff --git a/OBSBlur/Program.cs b/OBSBlur/Program.cs
index f0a1008..bd46a94 100644
--- a/OBSBlur/Program.cs
+++ b/OBSBlur/Program.cs
@@ -1,79 +1,3 @@
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text;
-
-new WindowManager();
-
-internal class WindowManager
-{
- internal Dictionary placements = new();
- internal Dictionary windowTitles = new();
- internal Dictionary 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();
- }
-}
+using OBSBlur.Window;
+new WindowManager();
\ No newline at end of file
diff --git a/OBSBlur/POINT.cs b/OBSBlur/Window/POINT.cs
similarity index 59%
rename from OBSBlur/POINT.cs
rename to OBSBlur/Window/POINT.cs
index 5c362f1..1aefb23 100644
--- a/OBSBlur/POINT.cs
+++ b/OBSBlur/Window/POINT.cs
@@ -1,25 +1,27 @@
using System.Runtime.InteropServices;
+namespace OBSBlur.Window;
+
[StructLayout(LayoutKind.Sequential)]
-public struct POINT
+public struct Point
{
public int X;
public int Y;
- public POINT(int x, int y)
+ public Point(int x, int y)
{
this.X = x;
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);
}
- 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()
diff --git a/OBSBlur/RECT.cs b/OBSBlur/Window/Rectangle.cs
similarity index 69%
rename from OBSBlur/RECT.cs
rename to OBSBlur/Window/Rectangle.cs
index 932c795..6f69ad7 100644
--- a/OBSBlur/RECT.cs
+++ b/OBSBlur/Window/Rectangle.cs
@@ -1,11 +1,13 @@
using System.Runtime.InteropServices;
+namespace OBSBlur.Window;
+
[StructLayout(LayoutKind.Sequential)]
-public struct RECT
+public struct Rectangle
{
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;
Top = top;
@@ -13,10 +15,10 @@ public struct RECT
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
- {
+ {
get { return Left; }
set { Right -= (Left - value); Left = value; }
}
@@ -51,37 +53,37 @@ public struct RECT
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);
}
- 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);
}
- public static bool operator !=(RECT r1, RECT r2)
+ public static bool operator !=(Rectangle r1, Rectangle 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;
}
public override bool Equals(object obj)
{
- if (obj is RECT)
- return Equals((RECT)obj);
+ if (obj is Rectangle)
+ return Equals((Rectangle)obj);
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;
}
diff --git a/OBSBlur/ShowWindowCommands.cs b/OBSBlur/Window/ShowWindowCommands.cs
similarity index 97%
rename from OBSBlur/ShowWindowCommands.cs
rename to OBSBlur/Window/ShowWindowCommands.cs
index a354855..b037a15 100644
--- a/OBSBlur/ShowWindowCommands.cs
+++ b/OBSBlur/Window/ShowWindowCommands.cs
@@ -1,4 +1,6 @@
-enum ShowWindowCommands
+namespace OBSBlur.Window;
+
+public enum ShowWindowCommands
{
///
/// Hides the window and activates another window.
diff --git a/OBSBlur/WINDOWPLACEMENT.cs b/OBSBlur/Window/WINDOWPLACEMENT.cs
similarity index 91%
rename from OBSBlur/WINDOWPLACEMENT.cs
rename to OBSBlur/Window/WINDOWPLACEMENT.cs
index ed24c83..ccc83a1 100644
--- a/OBSBlur/WINDOWPLACEMENT.cs
+++ b/OBSBlur/Window/WINDOWPLACEMENT.cs
@@ -1,11 +1,13 @@
using System.Runtime.InteropServices;
+namespace OBSBlur.Window;
+
///
/// Contains information about the placement of a window on the screen.
///
[Serializable]
[StructLayout(LayoutKind.Sequential)]
-internal struct WINDOWPLACEMENT
+public struct 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
///
/// The coordinates of the window's upper-left corner when the window is minimized.
///
- public POINT MinPosition;
+ public Point MinPosition;
///
/// The coordinates of the window's upper-left corner when the window is maximized.
///
- public POINT MaxPosition;
+ public Point MaxPosition;
///
/// The window's coordinates when the window is in the restored position.
///
- public RECT NormalPosition;
+ public Rectangle NormalPosition;
///
/// Gets the default (empty) value.
diff --git a/OBSBlur/Window/WindowInfo.cs b/OBSBlur/Window/WindowInfo.cs
new file mode 100644
index 0000000..94d4e5e
--- /dev/null
+++ b/OBSBlur/Window/WindowInfo.cs
@@ -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}";
+ }
+}
\ No newline at end of file
diff --git a/OBSBlur/Window/WindowManager.cs b/OBSBlur/Window/WindowManager.cs
new file mode 100644
index 0000000..bfba1ff
--- /dev/null
+++ b/OBSBlur/Window/WindowManager.cs
@@ -0,0 +1,81 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace OBSBlur.Window;
+
+public class WindowManager : IDisposable
+{
+ public readonly HashSet 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;
+ }
+}
+