WindowHelper.cs
using System.Collections;
using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; namespace GenXdev.Helpers { public enum DeviceCap { VERTRES = 10, DESKTOPVERTRES = 117, // http://pinvoke.net/default.aspx/gdi32/GetDeviceCaps.html } public static class DesktopInfo { [DllImport("gdi32.dll")] public static extern int GetDeviceCaps(IntPtr hdc, int nIndex); [PreserveSig()] [DllImport("gdi32.dll")] public static extern IntPtr CreateDC( string lpszDriver, string lpszDevice, IntPtr lpszOutput, IntPtr lpInitData ); public static float getScalingFactor(int monitor) { Graphics g = Graphics.FromHwnd(IntPtr.Zero); var AllScreens = (from q in WpfScreenHelper.Screen.AllScreens select q).ToArray(); IntPtr desktop = CreateDC( AllScreens[monitor].DeviceName, AllScreens[monitor].DeviceName, IntPtr.Zero, IntPtr.Zero ); int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES); int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES); float ScreenScalingFactor = (float)PhysicalScreenHeight / (float)LogicalScreenHeight; return ScreenScalingFactor; // 1.25 = 125% } } public class WindowObj { ///<summary>Windows handle to identify the current windows</summary> public IntPtr Handle { get; private set; } ///<summary>Name of the windows</summary> public string Title { get; private set; } ///<summary>Get the children of a window</summary> public ICollection<WindowObj> Children { get; private set; } /// <summary> /// Get a custom representation of the window class base on https://docs.microsoft.com/en-us/windows/win32/winmsg/about-window-classes documentation /// </summary> public string WindowType { get; private set; } /// <summary> /// Get the name of the class that represents the windows /// </summary> public string WindowClassName { get; private set; } private const UInt32 WM_CLOSE = 0x0010; private static int Amount = 0; /// <summary>Creates a window object with a handle and a window title</summary> /// <param name="handle"></param> /// <param name="title"></param> public WindowObj(IntPtr handle, string title) { Handle = handle; Title = title; StringBuilder stringBuilder = new StringBuilder(256); GetClassName(handle, stringBuilder, stringBuilder.Capacity); WindowType = GetWindowClass(stringBuilder.ToString()); WindowClassName = stringBuilder.ToString(); Children = new List<WindowObj>(); ArrayList handles = new ArrayList(); EnumedWindow childProc = GetWindowHandle; EnumChildWindows(handle, childProc, handles); foreach (IntPtr item in handles) { int capacityChild = GetWindowTextLength(handle) * 2; StringBuilder stringBuilderChild = new StringBuilder(capacityChild); GetWindowText(handle, stringBuilder, stringBuilderChild.Capacity); StringBuilder stringBuilderChild2 = new StringBuilder(256); GetClassName(handle, stringBuilderChild2, stringBuilderChild2.Capacity); WindowObj win = new WindowObj(item, stringBuilder.ToString()); win.WindowClassName = stringBuilderChild2.ToString(); win.WindowType = GetWindowClass(stringBuilderChild2.ToString()); Children.Add(win); } } [DllImport("user32.dll")] static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo); private const int MOUSEEVENTF_MOVE = 0x0001; private const int WM_SYSCOMMAND = 0x0112; private const int SC_MONITORPOWER = 0xF170; private const int MonitorTurnOn = -1; private const int MonitorShutoff = 2; public static void WakeMonitor() { //Turn them on PostMessage((IntPtr) 0xffff, WM_SYSCOMMAND, SC_MONITORPOWER, MonitorTurnOn); System.Threading.Thread.Sleep(150); mouse_event(MOUSEEVENTF_MOVE, 0, 1, 0, UIntPtr.Zero); System.Threading.Thread.Sleep(40); mouse_event(MOUSEEVENTF_MOVE, 0, -1, 0, UIntPtr.Zero); } public static void SleepMonitor() { //Turn them off PostMessage((IntPtr)0xffff, WM_SYSCOMMAND, SC_MONITORPOWER, MonitorShutoff); } [DllImport("user32.dll")] static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); [DllImport("kernel32.dll")] static extern IntPtr GetConsoleWindow(); private static bool GetWindowHandle(IntPtr windowHandle, ArrayList windowHandles) { windowHandles.Add(windowHandle); return true; } ///<summary>A class to have better manipulation of windows sizes</summary> private struct RectStruct { public int Left { get; set; } public int Top { get; set; } public int Right { get; set; } public int Bottom { get; set; } public int Width { get; set; } public int Height { get; set; } } /// <summary>Open a new Process with the given path and return a window object if the process have a user interface, else return null</summary> /// <param name="filePath">Path of the file to look for</param> /// <param name="timeToWait">Time to wait until the proccess execute, *Only apply for process with a window interface*</param> public static WindowObj Open(string filePath, int timeToWait = -1) { if (!File.Exists(filePath)) throw new Exception(string.Format("The filePath {0} is not valid", filePath)); Process newProcess = Process.Start(filePath); if (timeToWait == -1) newProcess.WaitForInputIdle(); else newProcess.WaitForInputIdle(timeToWait * 1000); if (newProcess != null && newProcess.MainWindowHandle != IntPtr.Zero) return new WindowObj(newProcess.MainWindowHandle, newProcess.MainWindowTitle); return null; } /// <summary>Look for the existence of a process with the given name an return the first occurrence of the process as a Window object</summary> /// <param name="name">Name of the process</param> /// <param name="attempts">Amount of tries that it will look for the window</param> /// <param name="waitInterval">Amount ot time it will stop the thread while waiting for the windows in each attemp</param> public static WindowObj GetWindow(string name, int attempts = 1, int waitInterval = 1000) { IEnumerable<Process> currentProcesses = Process.GetProcesses(); int counter = 0; while (counter < attempts) { foreach (Process p in currentProcesses) if (p.MainWindowHandle != IntPtr.Zero && p.MainWindowTitle == name) return new WindowObj(p.MainWindowHandle, p.MainWindowTitle); System.Threading.Thread.Sleep(waitInterval); currentProcesses = Process.GetProcesses(); counter++; } return null; } public static WindowObj GetFocusedWindow() { var sb = new StringBuilder(); var handle = GetForegroundWindow(); return new WindowObj(handle, GetWindowTitle(handle)); } /// <summary>Look for the existence of processes with the given name an return all occurrences of the process as Windows objects, *case sensitive*</summary> /// <param name="name">Name of the process</param> /// <param name="attempts">Amount of tries that it will look for the window</param> /// <param name="waitInterval">Amount ot time it will stop the thread while waiting for the windows in each attemp</param> public static IEnumerable<WindowObj> GetWindows(string name, int attempts = 1, int waitInterval = 1000) { IEnumerable<Process> currentProcesses = Process.GetProcesses(); ICollection<WindowObj> windows = new List<WindowObj>(); int counter = 0; while (counter < attempts) { foreach (Process p in currentProcesses) if (p.MainWindowHandle != IntPtr.Zero && p.ProcessName == name) windows.Add(new WindowObj(p.MainWindowHandle, p.MainWindowTitle)); if (windows.Count > 0) break; System.Threading.Thread.Sleep(waitInterval); currentProcesses = Process.GetProcesses(); counter++; } return windows; } public static IEnumerable<WindowObj> GetMainWindow(Process p, int attempts = 1, int waitInterval = 1000) { IEnumerable<Process> currentProcesses = Process.GetProcesses(); ICollection<WindowObj> windows = new List<WindowObj>(); int counter = 0; while (counter < attempts) { if (p.MainWindowHandle != IntPtr.Zero) windows.Add(new WindowObj(p.MainWindowHandle, p.MainWindowTitle)); if (windows.Count > 0) break; System.Threading.Thread.Sleep(waitInterval); currentProcesses = Process.GetProcesses(); counter++; } return windows; } /// <summary>Look for the existense of a process in all processes an return the first ocurrence of a process that contains the given name as a Window object</summary> /// <param name="name">Name of the process</param> /// <param name="attempts">Amount of tries that it will look for the window</param> /// <param name="waitInterval">Amount ot time it will stop the thread while waiting for the windows in each attemp</param> public static WindowObj GetWindowWithPartialName(string name, int attempts = 1, int waitInterval = 1000) { IEnumerable<Process> currentProcesses = Process.GetProcesses(); int counter = 0; while (counter < attempts) { foreach (Process p in currentProcesses) if (p.MainWindowHandle != IntPtr.Zero && p.MainWindowTitle.ToLower().Contains(name.ToLower())) return new WindowObj(p.MainWindowHandle, p.MainWindowTitle); System.Threading.Thread.Sleep(waitInterval); currentProcesses = Process.GetProcesses(); counter++; } return null; } /// <summary>Look for the existense of a process in all processes an return the processes that contains the given name as Windows objects</summary> /// <param name="name">Name of the process</param> /// <param name="attempts">Amount of tries that it will look for at least one window</param> /// <param name="waitInterval">Amount ot time it will stop the thread while waiting for the windows in each attemp</param> public static IEnumerable<WindowObj> GetWindowsWithPartialName(string name, int attempts = 1, int waitInterval = 1000) { IEnumerable<Process> currentProcesses = Process.GetProcesses(); ICollection<WindowObj> windows = new List<WindowObj>(); int counter = 0; while (counter < attempts) { foreach (Process p in currentProcesses) if (p.MainWindowHandle != IntPtr.Zero && p.MainWindowTitle.ToLower().Contains(name.ToLower())) windows.Add(new WindowObj(p.MainWindowHandle, p.MainWindowTitle)); if (windows.Count > 0) break; System.Threading.Thread.Sleep(waitInterval); currentProcesses = Process.GetProcesses(); counter++; } return windows; } /// <summary> /// Get the active windows if possible. /// </summary> /// <returns></returns> public static WindowObj GetActive() { IntPtr handle = GetActiveWindow(); if (handle != IntPtr.Zero) { foreach (Process p in Process.GetProcesses()) if (p.MainWindowHandle == handle) return new WindowObj(p.MainWindowHandle, p.MainWindowTitle); } return null; } /// <summary>Focus the current window</summary> public void Focus() { AllowSetForegroundWindow(-1); SetForegroundWindow(this.Handle); } public void SetForeground() { ShowWindowAsync(this.Handle, (int)ShowWindowCommands.Show); SetForegroundWindow(this.Handle); } /// <summary>Maximize the current window</summary> public bool Maximize() { return ShowWindowAsync(this.Handle, (int)ShowWindowCommands.Maximize); } /// <summary>Minimize the current window</summary> public bool Minimize() { return ShowWindowAsync(this.Handle, (int)ShowWindowCommands.Minimize); } /// <summary>Return the current windows at its first state when the windows was created</summary> public bool Restore() { return ShowWindowAsync(this.Handle, (int)ShowWindowCommands.Restore); } /// <summary>Return the current windows at its default state</summary> public bool DefaultState() { return ShowWindowAsync(this.Handle, (int)ShowWindowCommands.ShowDefault); } public static string GetWindowTitle(IntPtr hWnd) { var length = GetWindowTextLength(hWnd) + 1; var title = new StringBuilder(length); GetWindowText(hWnd, title, length); return title.ToString(); } /// <summary>Hide the current window /// *If the application close with a hide process, this will not be close unless close method /// calls or manually kill the process*</summary> public bool Hide() { return ShowWindowAsync(this.Handle, (int)ShowWindowCommands.Hide); } /// <summary>Shows the current windows if it was hide</summary> public bool Show() { return ShowWindowAsync(this.Handle, (int)ShowWindowCommands.Show); } /// <summary>Close the current windows</summary> public bool Close() { return SendMessage(this.Handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero) == IntPtr.Zero; } public bool SendMessage(UInt32 Msg, IntPtr wParam, IntPtr lParam) { return SendMessage(this.Handle, Msg, wParam, lParam) == IntPtr.Zero; } /// <summary>Resize the current window with the given params</summary> /// <param name="width">New width of the current windows</param> /// <param name="height">New height of the current windows</param> public bool Resize(int width, int height) { return MoveWindow(this.Handle, 0, 0, width, height, true); } /// <summary>Resize the current window with the given params</summary> /// <param name="pixels">this will use as new width and new height of the windows</param> public bool Resize(int pixels) { return MoveWindow(this.Handle, 0, 0, pixels, pixels, true); } /// <summary>Move the current window with the given params</summary> /// <param name="X">New X coordinate of the current windows</param> /// <param name="Y">New Y coordinate of the current windows</param> public bool Move(int X, int Y) { RectStruct rect = new RectStruct(); GetWindowRect(this.Handle, ref rect); rect.Width = rect.Right - rect.Left + Amount; rect.Height = rect.Bottom - rect.Top + Amount; return MoveWindow(this.Handle, X, Y, rect.Width, rect.Height, true); } public bool Move(int X, int Y, int W, int H) { return MoveWindow(this.Handle, X, Y, W, H, true); } /// <summary>Return the position of the windows as X, Y coordinates</summary> public Point Position() { RectStruct rect = new RectStruct(); GetWindowRect(this.Handle, ref rect); return new Point(rect.Left, rect.Top); } public int Left { get { return Position().X; } set { Move(value, Position().Y); } } public int Top { get { return Position().Y; } set { Move(Position().X, value); } } public int Width { get { return Size().Width; } set { Resize(value, Size().Height); } } public int Height { get { return Size().Height; } set { Resize(Size().Width, value); } } /// <summary>Return the Size of the windows as width, height coordinates</summary> public Size Size() { RectStruct rect = new RectStruct(); GetWindowRect(this.Handle, ref rect); rect.Width = rect.Right - rect.Left + Amount; rect.Height = rect.Bottom - rect.Top + Amount; return new Size(rect.Width, rect.Height); } /// <summary>Return the position and size of the windows as X, Y, with, height coordinates</summary> /* public Rect Area() { RectStruct rect = new RectStruct(); GetWindowRect(this.Handle, ref rect); rect.Width = rect.Right - rect.Left + Amount; rect.Height = rect.Bottom - rect.Top + Amount; return new System.Windows.(rect.Left, rect.Top, rect.Width, rect.Height); } */ /// <summary>Check if the current windows is visible</summary> public bool IsVisible() { return IsWindowVisible(this.Handle); } [DllImport("user32.dll")] static extern bool AllowSetForegroundWindow(int dwProcessId); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); [DllImport("user32.dll")] private static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, ref RectStruct rectangle); [DllImport("kernel32.dll")] private static extern int GetProcessId(IntPtr handle); [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId); [DllImport("user32.dll", SetLastError = true)] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetActiveWindow(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SetFocus(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] private static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab); [DllImport("user32.dll")] private static extern IntPtr GetFocus(); [DllImport("user32.dll")] static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); private delegate bool EnumedWindow(IntPtr handleWindow, ArrayList handles); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool EnumChildWindows(IntPtr window, EnumedWindow callback, ArrayList lParam); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern int GetWindowTextLength(IntPtr hWnd); private enum ShowWindowCommands { /// <summary> /// Hides the window and activates another window. /// </summary> Hide = 0, /// <summary> /// Activates and displays a window. If the window is minimized or /// maximized, the system restores it to its original size and position. /// An application should specify this flag when displaying the window /// for the first time. /// </summary> Normal = 1, /// <summary> /// Activates the window and displays it as a minimized window. /// </summary> ShowMinimized = 2, /// <summary> /// Maximizes the specified window. /// </summary> Maximize = 3, // is this the right value? /// <summary> /// Activates the window and displays it as a maximized window. /// </summary> ShowMaximized = 3, /// <summary> /// Displays a window in its most recent size and position. This value /// is similar to <see cref="Win32.ShowWindowCommand.Normal"/>, except /// the window is not activated. /// </summary> ShowNoActivate = 4, /// <summary> /// Activates the window and displays it in its current size and position. /// </summary> Show = 5, /// <summary> /// Minimizes the specified window and activates the next top-level /// window in the Z order. /// </summary> Minimize = 6, /// <summary> /// Displays the window as a minimized window. This value is similar to /// <see cref="Win32.ShowWindowCommand.ShowMinimized"/>, except the /// window is not activated. /// </summary> ShowMinNoActive = 7, /// <summary> /// Displays the window in its current size and position. This value is /// similar to <see cref="Win32.ShowWindowCommand.Show"/>, except the /// window is not activated. /// </summary> ShowNA = 8, /// <summary> /// Activates and displays the window. If the window is minimized or /// maximized, the system restores it to its original size and position. /// An application should specify this flag when restoring a minimized window. /// </summary> Restore = 9, /// <summary> /// Sets the show state based on the SW_* value specified in the /// STARTUPINFO structure passed to the CreateProcess function by the /// program that started the application. /// </summary> ShowDefault = 10, /// <summary> /// <b>Windows 2000/XP:</b> Minimizes a window, even if the thread /// that owns the window is not responding. This flag should only be /// used when minimizing windows from a different thread. /// </summary> ForceMinimize = 11 } private string GetWindowClass(string windowClass) { List<string> values = new List<string>(){ "ComboLBox","DDEMLEvent","Message","#32768", "#32769","#32770","#32771","#32772","Button","Edit","ListBox","MDIClient", "ScrollBar","Static","" }; if (windowClass == "#32768") return "Menu"; else if (windowClass == "#32769") return "DektopWindow"; else if (windowClass == "#32770") return "DialogBox"; else if (windowClass == "#32771") return "TaskSwitchWindowClass"; else if (windowClass == "#32772") return "IconTitlesClass"; return values.SingleOrDefault(s => s == windowClass); } [DllImport("user32.dll", SetLastError = true)] static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll")] static extern int SetWindowLong(IntPtr hWnd, int nIndex, UInt32 dwNewLong); public void RemoveBorder() { const int GWL_STYLE = -16; const long WS_CAPTION = 0x00C00000L; const long WS_THICKFRAME = 0x00040000L; const long WS_MINIMIZEBOX = 0x00020000L; const long WS_MAXIMIZEBOX = 0x00010000L; const long WS_SYSMENU = 0x00080000L; long lStyle = GetWindowLong(this.Handle, GWL_STYLE); lStyle &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU); SetWindowLong(this.Handle, GWL_STYLE, (uint) lStyle); } } } |