public static void CenterWindowToScreen(IntPtr hwnd, bool useWorkArea = true) { try { IntPtr handle = MonitorFromWindow(GetDesktopWindow(), MONITOR.DEFAULTTONEAREST); MONITORINFOEXW monInfo = new MONITORINFOEXW(null); monInfo.cbSize = (uint)Marshal.SizeOf(monInfo); GetMonitorInfoW(handle, ref monInfo); var screenRect = useWorkArea ? monInfo.rcWork : monInfo.rcMonitor; var midX = (monInfo.rcMonitor.right - monInfo.rcMonitor.left) / 2; var midY = (monInfo.rcMonitor.bottom - monInfo.rcMonitor.top) / 2; var size = GetWindowSize(hwnd); var left = midX - (size.Width / 2); var top = midY - (size.Height / 2); SetWindowPos( hwnd, IntPtr.Zero, left, top, -1, -1, SWP.NOACTIVATE | SWP.NOSIZE | SWP.NOZORDER); } catch { } { } }
public int GetDisplayRefreshRate() { // Get a monitor handle ("HMONITOR") for the window. // If the window is straddling more than one monitor, Windows will pick the "best" one. IntPtr hmonitor = MonitorFromWindow(_hwnd, MONITOR_DEFAULTTONEAREST); if (hmonitor == IntPtr.Zero) { return(0); } // Get more information about the monitor. MONITORINFOEXW monitorInfo = new MONITORINFOEXW { cbSize = (uint)Marshal.SizeOf <MONITORINFOEXW>() }; bool bResult = GetMonitorInfoW(hmonitor, ref monitorInfo); if (!bResult) { return(0); } // Get display settings from Windows API bResult = EnumDisplaySettingsW(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, out DEVMODEW devMode); if (!bResult) { return(0); } return((int)devMode.dmDisplayFrequency); }
private unsafe bool HandleMinMaxSizes(IntPtr lParam) { bool isHandled = false; MINMAXINFO *mmi = (MINMAXINFO *)lParam; if (!_options.MinimumSize.IsEmpty) { mmi->ptMinTrackSize.X = _options.MinimumSize.Width; mmi->ptMinTrackSize.Y = _options.MinimumSize.Height; isHandled = true; } if (!_options.MaximumSize.IsEmpty) { mmi->ptMaxTrackSize.X = _options.MaximumSize.Width; mmi->ptMaxTrackSize.Y = _options.MaximumSize.Height; isHandled = true; } // https://stackoverflow.com/questions/39816031/maximize-window-maintaining-taskbar-limits if (_options.WindowFrameless && _options.WindowState == WindowState.Maximize) { IntPtr handle = MonitorFromWindow(GetDesktopWindow(), MONITOR.DEFAULTTONEAREST); MONITORINFOEXW monInfo = new MONITORINFOEXW(null); monInfo.cbSize = (uint)Marshal.SizeOf(monInfo); var captionHeight = GetSystemMetrics(SystemMetric.SM_CYCAPTION); GetMonitorInfoW(handle, ref monInfo); var workArea = monInfo.rcWork; var monitorArea = monInfo.rcMonitor; mmi->ptMaxPosition.X = Math.Abs(workArea.left - monitorArea.left) - captionHeight / 2; mmi->ptMaxPosition.Y = Math.Abs(workArea.top - monitorArea.top); mmi->ptMaxSize.X = Math.Abs(workArea.right - workArea.left) + captionHeight; mmi->ptMaxSize.Y = Math.Abs(workArea.bottom - workArea.top) + captionHeight; isHandled = true; } return(isHandled); }
private string GetTextForTextBlock() { // 1. Get the window handle ("HWND" in Win32 parlance) WindowInteropHelper helper = new WindowInteropHelper(this); IntPtr hwnd = helper.Handle; // 2. Get a monitor handle ("HMONITOR") for the window. // If the window is straddling more than one monitor, Windows will pick the "best" one. IntPtr hmonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); if (hmonitor == IntPtr.Zero) { return("MonitorFromWindow returned NULL ☹"); } // 3. Get more information about the monitor. MONITORINFOEXW monitorInfo = new MONITORINFOEXW(); monitorInfo.cbSize = (uint)Marshal.SizeOf <MONITORINFOEXW>(); bool bResult = GetMonitorInfoW(hmonitor, ref monitorInfo); if (!bResult) { return("GetMonitorInfoW returned FALSE ☹"); } // 4. Get the current display settings for that monitor, which includes the resolution and refresh rate. DEVMODEW devMode = new DEVMODEW(); devMode.dmSize = (ushort)Marshal.SizeOf <DEVMODEW>(); bResult = EnumDisplaySettingsW(monitorInfo.szDevice, ENUM_CURRENT_SETTINGS, out devMode); if (!bResult) { return("EnumDisplaySettingsW returned FALSE ☹"); } // Done! return(string.Format("{0} x {1} @ {2}hz", devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmDisplayFrequency)); }
private (MONITORINFO mi, string device) GetMonitorInfoEx(IntPtr hMonitor) { unsafe { MONITORINFOEXW miEx = default; MONITORINFO * pmi = (MONITORINFO *)&miEx; (*pmi).cbSize = (uint)sizeof(MONITORINFOEXW); if (!NativeMethods.GetMonitorInfo(new(hMonitor), pmi)) { try { throw new Win32Exception().WithMessage($"Could not read the monitor information for HMONITOR={hMonitor:X8}!"); } catch (Win32Exception e) when(e.IsInvalidMonitorHandleException() || !IsMonitorValid(hMonitor)) { throw new InvalidDisplayReferenceException(hMonitor, e); } } char *pszDevice = (char *)&miEx.szDevice; return(*pmi, new string(pszDevice)); } }
public static Rectangle FullScreenBounds(Rectangle configuredBounds) { try { IntPtr handle = MonitorFromWindow(GetDesktopWindow(), MONITOR.DEFAULTTOPRIMARY); MONITORINFOEXW monInfo = new MONITORINFOEXW(null); GetMonitorInfoW(handle, ref monInfo); RECT rect = monInfo.rcMonitor; if (rect.Width <= 0 || rect.Height <= 0) { return(configuredBounds); } return(rect); } catch { } { } return(configuredBounds); }
private static extern bool GetMonitorInfoW( IntPtr hMonitor, ref MONITORINFOEXW lpmi);
public static extern BOOL GetMonitorInfoW(IntPtr hMonitor, ref MONITORINFOEXW lpmi);
public static partial BOOL GetMonitorInfoW(IntPtr hMonitor, ref MONITORINFOEXW lpmi);
public void HandleNCCalcsize(IntPtr wParam, IntPtr lParam) { // lParam is an [in, out] that can be either a RECT* (wParam == FALSE) or an NCCALCSIZE_PARAMS*. // Since the first field of NCCALCSIZE_PARAMS is a RECT and is the only field we care about // we can unconditionally treat it as a RECT. /* DefWindowProc must be called in both the maximized and non-maximized * cases, otherwise tile/cascade windows won't work */ var nonclient = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT)); DefWindowProcW(_framelessInfo.Handle, WM.NCCALCSIZE, wParam, lParam); var client = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT)); if (IsMaximized(_framelessInfo.Handle)) { WINDOWINFO wi = new WINDOWINFO(null); GetWindowInfo(_framelessInfo.Handle, ref wi); /* Maximized windows always have a non-client border that hangs over * the edge of the screen, so the size proposed by WM_NCCALCSIZE is * fine. Just adjust the top border to remove the window title. */ var rect = new RECT(); rect.left = client.left; rect.top = (int)(nonclient.top + wi.cyWindowBorders); rect.right = client.right; rect.bottom = client.bottom; IntPtr mon = MonitorFromWindow(_framelessInfo.Handle, MONITOR.DEFAULTTOPRIMARY); MONITORINFOEXW mi = new MONITORINFOEXW(null); GetMonitorInfoW(mon, ref mi); /* If the client rectangle is the same as the monitor's rectangle, * the shell assumes that the window has gone fullscreen, so it removes * the topmost attribute from any auto-hide appbars, making them * inaccessible. To avoid this, reduce the size of the client area by * one pixel on a certain edge. The edge is chosen based on which side * of the monitor is likely to contain an auto-hide appbar, so the * missing client area is covered by it. */ if (rect.AreEqual(mi.rcMonitor)) { if (HasAutohideAppbar(ABE_BOTTOM, mi.rcMonitor)) { rect.bottom--; } else if (HasAutohideAppbar(ABE_LEFT, mi.rcMonitor)) { rect.left++; } else if (HasAutohideAppbar(ABE_TOP, mi.rcMonitor)) { rect.top++; } else if (HasAutohideAppbar(ABE_RIGHT, mi.rcMonitor)) { rect.right--; } } Marshal.StructureToPtr(rect, lParam, false); } else { /* For the non-maximized case, set the output RECT to what it was * before WM_NCCALCSIZE modified it. This will make the client size the * same as the non-client size. */ Marshal.StructureToPtr(nonclient, lParam, false); } }