/// <summary> /// Gets the dpi of the display. If the window is not on any monitor the primary monitor's /// dpi is returned instead. /// <para/> /// On Windows version lower than 8, the dpi is the same for all monitors. /// </summary> /// <param name="windowHandle">The handle of the window displayed by the monitor</param> /// <returns>The dpi of the current display</returns> public static MonitorDpi GetDpi(IntPtr windowHandle) { if ((Environment.OSVersion.Version.Major >= 6 && Environment.OSVersion.Version.Minor >= 2) || Environment.OSVersion.Version.Major >= 10) { uint dpiX; uint dpiY; var monitor = UnsafeNative.MonitorFromWindow(windowHandle, UnsafeNative.MonitorOptions.MONITOR_DEFAULTTONULL); if (monitor == IntPtr.Zero) { monitor = UnsafeNative.MonitorFromPoint(new UnsafeNative.POINT { x = 0, y = 0 }, UnsafeNative.MonitorOptions.MONITOR_DEFAULTTOPRIMARY); } UnsafeNative.GetDpiForMonitor(monitor, UnsafeNative.DpiType.Effective, out dpiX, out dpiY); return(new MonitorDpi { x = dpiX, y = dpiY }); } else { var desktop = Graphics.FromHwnd(IntPtr.Zero).GetHdc(); var logicalPixelsx = (uint)UnsafeNative.GetDeviceCaps(desktop, UnsafeNative.DeviceCap.LOGPIXELSX); var logicalPixelsy = (uint)UnsafeNative.GetDeviceCaps(desktop, UnsafeNative.DeviceCap.LOGPIXELSY); return(new MonitorDpi { x = logicalPixelsx, y = logicalPixelsy }); } }
/// <summary> /// Adds a shadow effect to a window /// </summary> /// <param name="wrapper"> /// A managed object that should not be finalized until the platform invoke call returns. /// </param> /// <param name="windowHandle">The hwnd of the window</param> public static void AddShadow(object wrapper, IntPtr windowHandle) { var myHandleRef = new HandleRef(wrapper, windowHandle); UnsafeNative.SetClassLong(myHandleRef, UnsafeNative.GCL_STYLE, new IntPtr(UnsafeNative.GetClassLongPtr(myHandleRef, UnsafeNative.CS_DROPSHADOW).ToInt32() | UnsafeNative.CS_DROPSHADOW)); }
/// <summary> /// Sends the specified message string to a window. The SendMessage function calls the window /// procedure for the specified window and does not return until the window procedure has /// processed the message. /// </summary> /// <param name="hwnd">A handle to the window whose window procedure will receive the message.</param> /// <param name="message">The message to be sent to the window</param> /// <exception cref="Win32Exception">Win32 error occures</exception> /// <exception cref="ArgumentException">HWND is <see cref="IntPtr.Zero"/></exception> /// <exception cref="ArgumentNullException"><paramref name="message"/> is null</exception> /// <exception cref="ArgumentException"><paramref name="message"/> is empty</exception> public static void SendMessage(IntPtr hwnd, string message) { if (hwnd == IntPtr.Zero) { throw new ArgumentException("HWND cannot be IntPtr.Zero"); } if (message == null) { throw new ArgumentNullException("The message cannot be null"); } if (message == "") { throw new ArgumentException("The message cannot be empty"); } var messageBytes = Encoding.Default.GetBytes(message); /* ANSII encoding */ var data = new UnsafeNative.COPYDATASTRUCT { dwData = (IntPtr)100, lpData = message, cbData = messageBytes.Length + 1 /* +1 because of 0 termination */ }; if (UnsafeNative.SendMessage(hwnd, UnsafeNative.WM_COPYDATA, IntPtr.Zero, ref data) != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
/// <summary> /// Sends the specified message to a window or windows. The SendMessage function calls the /// window procedure for the specified window and does not return until the window procedure /// has processed the message. /// </summary> /// <param name="hwnd">The window handle of the sending window</param> /// <param name="windowMessage">The message to be sent.</param> /// <param name="wParam">Additional message-specific information.</param> /// <param name="lParam">Additional message-specific information.</param> public static void SendMessage(IntPtr hwnd, WindowsMessages windowMessage, IntPtr wParam, IntPtr lParam) { if (UnsafeNative.SendMessage(hwnd, (int)windowMessage, wParam, lParam) != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
/// <summary> /// Brings the thread that created the specified window into the foreground and activates the /// window. Keyboard input is directed to the window, and various visual cues are changed for /// the user. The system assigns a slightly higher priority to the thread that created the /// foreground window than it does to other threads. /// </summary> /// <param name="hwnd"> /// A handle to the window that should be activated and brought to the foreground. /// </param> /// <returns>Returns true if successful; otherwise false</returns> /// <exception cref="ArgumentException"><paramref name="hwnd"/> is <see cref="IntPtr.Zero"/></exception> public static bool ActivateWindow(IntPtr hwnd) { if (hwnd == IntPtr.Zero) { throw new ArgumentException("HWND cannot be IntPtr.Zero"); } return(UnsafeNative.SetForegroundWindow(hwnd)); }
/// <summary> /// Defines a new window message that is guaranteed to be unique throughout the system. The /// message value can be used when sending or posting messages. /// </summary> /// <param name="message">The message to be registered.</param> /// <returns>Returns a message identifier in the range 0xC000 through 0xFFFF</returns> /// <exception cref="Win32Exception">Win32 error occures</exception> public static uint RegisterWindowMessage(string message) { var result = UnsafeNative.RegisterWindowMessage(message); if (result == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(result); }
/// <summary> /// Extracts an icon from a exe, dll or ico file. /// </summary> /// <param name="filename">The filename of the resource</param> /// <param name="iconIndex">THe index of the icon</param> /// <returns>The icon represented by a byte array</returns> public static byte[] ExtractAssociatedIcon(string filename, int iconIndex = 0) { if (filename == null) { throw new ArgumentNullException(nameof(filename)); } if (filename == "") { throw new ArgumentException("filename is empty"); } unsafe { IntPtr[] largeIcons = new IntPtr[] { IntPtr.Zero }; try { var count = UnsafeNative.ExtractIconEx(filename, iconIndex, largeIcons, null, 1); if (count > 0 && largeIcons[0] != IntPtr.Zero) { var icon = Icon.FromHandle(largeIcons[0]); using (var stream = new MemoryStream()) { icon.ToBitmap().Save(stream, ImageFormat.Png); stream.Seek(0, SeekOrigin.Begin); return(stream.ToArray()); } } else { return(null); } } catch (Exception) { throw; } finally { foreach (IntPtr ptr in largeIcons) { if (ptr != IntPtr.Zero) { UnsafeNative.DestroyIcon(ptr); } } } } }
/// <summary> /// The message is sent to all top-level windows in the system, including disabled or /// invisible unowned windows, overlapped windows, and pop-up windows; but the message is not /// sent to child windows. /// </summary> /// <param name="registeredWindowMessage"> /// The registered window message. use <see cref="Win32Api.RegisterWindowMessage(string)"/> /// to register a message. /// </param> /// <param name="wParam">Additional message-specific information.</param> /// <param name="lParam">Additional message-specific information.</param> /// <exception cref="ArgumentException">Invalid registered window message</exception> /// <exception cref="Win32Exception">Win32 error occures</exception> public static void BroadcastMessage(uint registeredWindowMessage, IntPtr wParam, IntPtr lParam) { if (registeredWindowMessage < 0xC000) { throw new ArgumentException("Not a valid registered window message"); } if (UnsafeNative.SendMessage(UnsafeNative.HWND_BROADCAST, (int)registeredWindowMessage, wParam, lParam) != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } }
/// <summary> /// Gets the path of the user's profile picture /// </summary> /// <param name="username">The username</param> /// <returns>The full path of the user's profile picture</returns> public static string GetUserTilePath(string username) { try { var stringBuilder = new StringBuilder(1000); UnsafeNative.GetUserTilePath(username, 0x80000000, stringBuilder, stringBuilder.Capacity); return(stringBuilder.ToString()); } catch { throw; } }
/// <summary> /// Gets the bounds of the monitor that contains the defined window /// </summary> /// <param name="windowHandle">The handle of the window displayed by the monitor</param> /// <returns> /// Returns the bounds of the monitor. Returns null if window is not on any monitor. /// </returns> public static Rect?GetMonitorBounds(IntPtr windowHandle) { var monitor = UnsafeNative.MonitorFromWindow(windowHandle, UnsafeNative.MonitorOptions.MONITOR_DEFAULTTONULL); if (monitor != IntPtr.Zero) { UnsafeNative.MONITORINFO monitorInfo = new UnsafeNative.MONITORINFO(); UnsafeNative.GetMonitorInfo(monitor, monitorInfo); UnsafeNative.RECT rcWorkArea = monitorInfo.rcWork; UnsafeNative.RECT rcMonitorArea = monitorInfo.rcMonitor; return(new Rect(rcMonitorArea.left, rcMonitorArea.top, Math.Abs(rcMonitorArea.left - rcMonitorArea.right), Math.Abs(rcMonitorArea.bottom - rcMonitorArea.top))); } return(null); }
/// <summary> /// Returns all window handles associated with the process id. The process id can be /// retrieved with <see cref="Process.GetCurrentProcess()"/>.Id /// </summary> /// <param name="processId">The unique identifier for the associated process.</param> /// <returns>A collection of window handles associated with the process id</returns> public static IEnumerable <IntPtr> GetAllThreadWindowHandles(int processId) { var result = new List <IntPtr>(); var threads = Process.GetProcessById(processId).Threads; for (int i = 0; i < threads.Count; i++) { UnsafeNative.EnumThreadWindows(threads[i].Id, (hWnd, lParam) => { result.Add(hWnd); return(true); }, IntPtr.Zero); } return(result); }
/// <summary> /// Sent to a window when the size or position of the window is about to change. An /// application can use this message to override the window's default maximized size and /// position, or its default minimum or maximum tracking size. /// </summary> /// <param name="windowHandle">The handle of the window displayed by the monitor</param> /// <param name="lParam">Additional message-specific information</param> public static void WmGetMinMaxInfo(IntPtr windowHandle, IntPtr lParam) { UnsafeNative.MINMAXINFO mmi = (UnsafeNative.MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(UnsafeNative.MINMAXINFO)); // Adjust the maximized size and position to fit the work area of the correct monitor System.IntPtr monitor = UnsafeNative.MonitorFromWindow(windowHandle, UnsafeNative.MonitorOptions.MONITOR_DEFAULTTONEAREST); if (monitor != System.IntPtr.Zero) { UnsafeNative.MONITORINFO monitorInfo = new UnsafeNative.MONITORINFO(); UnsafeNative.GetMonitorInfo(monitor, monitorInfo); UnsafeNative.RECT rcWorkArea = monitorInfo.rcWork; UnsafeNative.RECT rcMonitorArea = monitorInfo.rcMonitor; mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); } Marshal.StructureToPtr(mmi, lParam, true); }
/// <summary> /// Determines if the window is shown in any of the monitors. /// </summary> /// <param name="windowHandle">The handle of the window displayed by the monitor</param> /// <returns>true if the window is displayed on any monitor; otherwise false</returns> public static bool WindowIsInAnyMonitor(IntPtr windowHandle) => // If MonitorFromWindow has returned zero, we are sure that the window is not in any of // our monitors UnsafeNative.MonitorFromWindow(windowHandle, UnsafeNative.MonitorOptions.MONITOR_DEFAULTTONULL) != IntPtr.Zero;
/// <summary> /// Returns the mouse position on screen /// </summary> /// <returns>The mouse position coordinates on screen</returns> public static System.Windows.Point GetMousePosition() { UnsafeNative.Win32Point w32Mouse = new UnsafeNative.Win32Point(); UnsafeNative.GetCursorPos(ref w32Mouse); return(new System.Windows.Point(w32Mouse.X, w32Mouse.Y)); }