The code defines a static class ProgramExtensions
in the window_tracker
namespace, which imports various Windows API functions from the user32.dll
library and provides methods to retrieve window text, find windows, and retrieve the foreground window. The class includes a delegate EnumWindowsProc
to filter which windows to include and uses various attributes and classes to handle the imported functions and their return types.
npm run import -- "list window handles"
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace window_tracker
{
public static class ProgramExtensions
{
[DllImport("user32.dll",
"SetLastError = true")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll",
"SetLastError = true")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll",
"CharSet = CharSet.Unicode")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll",
"CharSet = CharSet.Unicode")]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
// Delegate to filter which windows to include
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
/// <summary> Get the text for the window pointed to by hWnd </summary>
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if(size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
/// <summary> Find all windows that match the given filter </summary>
/// <param name="filter"> A delegate that returns true for windows
/// that should be returned and false for windows that should
/// not be returned </param>
public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
{
IntPtr found = IntPtr.Zero;
List<IntPtr> windows = new List<IntPtr>();
EnumWindows(delegate (IntPtr wnd, IntPtr param)
{
if(filter(wnd, param))
{
// only add the windows that pass the filter
windows.Add(wnd);
}
// but return true here so that we iterate all windows
return true;
}, found);
return windows;
}
/// <summary> Find all windows that contain the given title text </summary>
/// <param name="titleText"> The text that the window title must contain. </param>
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
return FindWindows(delegate (IntPtr wnd, IntPtr param)
{
return GetWindowText(wnd).Contains(titleText);
});
}
public static Process GetProcess(IntPtr wnd)
{
uint proc;
GetWindowThreadProcessId(wnd, out proc);
return Process.GetProcessById((int)proc);
}
public static string GetProcessTitle(IntPtr wnd)
{
return GetProcess(wnd).MainWindowTitle;
}
public static bool IsForeground(IntPtr wnd)
{
return GetForegroundWindow() == wnd;
}
public static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)
{
WINDOWPLACEMENT placement = new WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);
GetWindowPlacement(hwnd, ref placement);
return placement;
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPLACEMENT
{
public int length;
public int flags;
public ShowWindowCommands showCmd;
public POINTAPI ptMinPosition;
public POINTAPI ptMaxPosition;
public RECT rcNormalPosition;
}
public struct POINTAPI {
public int x;
public int y;
}
public struct RECT {
public int left;
public int top;
public int right;
public int bottom;
}
public enum ShowWindowCommands : int
{
Hide = 0,
Normal = 1,
Minimized = 2,
Maximized = 3,
}
}
}
csharp
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace WindowTracker
{
public static class WindowTracker
{
private const int MAX_TITLE_LENGTH = 256;
private const string USER32_DLL_NAME = "user32.dll";
[DllImport(USER32_DLL_NAME, SetLastError = true)]
private static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl);
[DllImport(USER32_DLL_NAME, SetLastError = true)]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport(USER32_DLL_NAME, CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport(USER32_DLL_NAME, CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport(USER32_DLL_NAME)]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport(USER32_DLL_NAME)]
private static extern IntPtr GetForegroundWindow();
// Delegate to filter which windows to include
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
/// <summary> Get the text for the window pointed to by hWnd </summary>
public static string GetWindowText(IntPtr hWnd)
{
return GetWindowText(hWnd, MAX_TITLE_LENGTH);
}
private static string GetWindowText(IntPtr hWnd, int maxCount)
{
int size = GetWindowTextLength(hWnd);
if (size > 0)
{
var builder = new StringBuilder(size + 1);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
/// <summary> Get the text for the window pointed to by hWnd </summary>
public static string GetTitle(IntPtr hWnd)
{
return GetWindowText(hWnd);
}
/// <summary> Find all windows that match the given filter </summary>
/// <param name="filter"> A delegate that returns true for windows
/// that should be returned and false for windows that should
/// not be returned </param>
public static IEnumerable<IntPtr> FindWindows(EnumWindowsProc filter)
{
if (filter == null)
{
throw new ArgumentNullException(nameof(filter));
}
return EnumWindowsProcWrapper(filter);
}
private static IEnumerable<IntPtr> EnumWindowsProcWrapper(EnumWindowsProc filter)
{
var found = IntPtr.Zero;
var windows = new List<IntPtr>();
EnumWindows(delegate (IntPtr wnd, IntPtr param)
{
if (filter(wnd, param))
{
// only add the windows that pass the filter
windows.Add(wnd);
}
// but return true here so that we iterate all windows
return true;
}, found);
return windows;
}
/// <summary> Find all windows that contain the given title text </summary>
/// <param name="titleText"> The text that the window title must contain. </param>
public static IEnumerable<IntPtr> FindWindowsWithText(string titleText)
{
if (string.IsNullOrEmpty(titleText))
{
throw new ArgumentException("Title text cannot be null or empty.", nameof(titleText));
}
return StringComparer.OrdinalIgnoreCase.Equals(titleText, titleText.ToLower())
? FindWindows(w => GetWindowText(w).Contains(titleText, StringComparison.OrdinalIgnoreCase))
: FindWindows(w => GetWindowText(w).Contains(titleText, StringComparison.OrdinalIgnoreCase) || GetWindowText(w).Contains(titleText.ToLower(), StringComparison.OrdinalIgnoreCase));
}
public static Process GetProcess(IntPtr wnd)
{
if (wnd == IntPtr.Zero)
{
throw new ArgumentException("Window handle is zero.", nameof(wnd));
}
var proc = GetProcessId(wnd);
return Process.GetProcessById((int)proc);
}
private static uint GetProcessId(IntPtr wnd)
{
uint proc;
GetWindowThreadProcessId(wnd, out proc);
return proc;
}
public static string GetProcessTitle(IntPtr wnd)
{
return GetProcess(wnd).MainWindowTitle;
}
public static bool IsForeground(IntPtr wnd)
{
return GetForegroundWindow() == wnd;
}
public static WINDOWPLACEMENT GetPlacement(IntPtr hwnd)
{
if (hwnd == IntPtr.Zero)
{
throw new ArgumentException("Window handle is zero.", nameof(hwnd));
}
var placement = new WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);
GetWindowPlacement(hwnd, ref placement);
return placement;
}
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPLACEMENT
{
public int length;
public int flags;
public ShowWindowCommands showCmd;
public POINTAPI ptMinPosition;
public POINTAPI ptMaxPosition;
public RECT rcNormalPosition;
}
public struct POINTAPI
{
public int x;
public int y;
}
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
public enum ShowWindowCommands : int
{
Hide = 0,
Normal = 1,
Minimized = 2,
Maximized = 3,
}
}
}
Code Breakdown
ProgramExtensions
in the window_tracker
namespace.user32.dll
library, which provides Windows API functions.GetWindowPlacement
GetWindowThreadProcessId
GetWindowText
GetWindowTextLength
EnumWindows
GetForegroundWindow
EnumWindowsProc
to filter which windows to include.GetWindowText(IntPtr hWnd)
: Retrieves the text for the window pointed to by hWnd
.FindWindows(EnumWindowsProc filter)
: Finds all windows that match the given filter.filter
: A delegate that returns true for windows that should be returned and false for windows that should not be returned.hWnd
: An integer pointer to a window handle.lpwndpl
, lpdwProcessId
, strText
, lParam
: Parameters for the imported functions.bool
: Returns true if the function is successful, false otherwise.uint
: Returns the thread ID of the process that owns the specified window.int
: Returns the length of the window text or the result of the EnumWindows
function.string
: Returns the text for the window pointed to by hWnd
.IEnumerable<IntPtr>
: Returns a collection of window handles.DllImport
attribute is used to import the functions from the user32.dll
library.[return: MarshalAs(UnmanagedType.Bool)]
attribute is used to specify the return type of the GetWindowPlacement
function.StringBuilder
class is used to retrieve the text for the window.EnumWindows
function is used to find all windows that match the given filter.GetForegroundWindow
function is used to retrieve the handle of the foreground window.