public static void GetMonitorContentScale(IntPtr monitor, out float scaleX, out float scaleY) { uint xDpi, yDpi; if (Win32Platform.IsWindows81OrGreater) { ShCore.GetDpiForMonitor(monitor, MonitorDpiType.MDT_EFFECTIVE_DPI, out xDpi, out yDpi); } else { IntPtr dc = User32.GetDC(IntPtr.Zero); xDpi = (uint)Gdi32.GetDeviceCaps(dc, DeviceCap.LogPixelsX); yDpi = (uint)Gdi32.GetDeviceCaps(dc, DeviceCap.LogPixelsY); User32.ReleaseDC(IntPtr.Zero, dc); } scaleX = xDpi / (float)Win32Platform.DEFAULT_DPI; scaleY = yDpi / (float)Win32Platform.DEFAULT_DPI; }
/// <inheritdoc /> protected override void SetupInternal(Configurator config) { IsWindows7OrGreater = IsWindowsVersionOrGreaterWin32( NativeHelpers.HiByte((ushort)NtDll.WinVer.Win32WinNTWin7), NativeHelpers.LoByte((ushort)NtDll.WinVer.Win32WinNTWin7), 0); IsWindows8OrGreater = IsWindowsVersionOrGreaterWin32( NativeHelpers.HiByte((ushort)NtDll.WinVer.Win32WinNTWin8), NativeHelpers.LoByte((ushort)NtDll.WinVer.Win32WinNTWin8), 0); IsWindows81OrGreater = IsWindowsVersionOrGreaterWin32( NativeHelpers.HiByte((ushort)NtDll.WinVer.Win32WinNTWinBlue), NativeHelpers.LoByte((ushort)NtDll.WinVer.Win32WinNTWinBlue), 0); IsWindows10AnniversaryUpdateOrGreaterWin32 = IsWindows10BuildOrGreaterWin32(14393); IsWindows10CreatorsUpdateOrGreaterWin32 = IsWindows10BuildOrGreaterWin32(15063); var windowsVersionFlags = new List <string>(); if (IsWindows7OrGreater) { windowsVersionFlags.Add(nameof(IsWindows7OrGreater)); } if (IsWindows8OrGreater) { windowsVersionFlags.Add(nameof(IsWindows8OrGreater)); } if (IsWindows81OrGreater) { windowsVersionFlags.Add(nameof(IsWindows81OrGreater)); } if (IsWindows10AnniversaryUpdateOrGreaterWin32) { windowsVersionFlags.Add(nameof(IsWindows10AnniversaryUpdateOrGreaterWin32)); } if (IsWindows10CreatorsUpdateOrGreaterWin32) { windowsVersionFlags.Add(nameof(IsWindows10CreatorsUpdateOrGreaterWin32)); } Engine.Log.Trace(string.Join(", ", windowsVersionFlags), MessageSource.Win32); if (IsWindows10CreatorsUpdateOrGreaterWin32) { User32.SetProcessDpiAwarenessContext(DpiAwarenessContext.DpiAwarenessContextPerMonitorAwareV2); } else if (IsWindows81OrGreater) { User32.SetProcessDpiAwareness(ProcessDpiAwareness.ProcessPerMonitorDpiAware); } else { User32.SetProcessDPIAware(); } // todo: load libraries - if any, probably XInput? // Initialize audio. AudioContext ctx = null; #if OpenAL ctx ??= OpenALAudioAdapter.TryCreate(this); #endif ctx ??= WasApiAudioContext.TryCreate(this); ctx ??= new NullAudioContext(); Audio = ctx; Engine.Log.Trace("Audio init complete.", MessageSource.Win32); PopulateKeyCodes(); RegisterWindowClass(); CreateHelperWindow(); PollMonitors(); Engine.Log.Trace("Platform helpers created.", MessageSource.Win32); var windowInitialSize = new Rect { Right = (int)config.HostSize.X, Bottom = (int)config.HostSize.Y }; GetFullWindowRect(DEFAULT_WINDOW_STYLE, DEFAULT_WINDOW_STYLE_EX, DEFAULT_DPI, ref windowInitialSize); int initialWidth = windowInitialSize.Right - windowInitialSize.Left; int initialHeight = windowInitialSize.Bottom - windowInitialSize.Top; WindowStyles windowStyle = DEFAULT_WINDOW_STYLE; if (config.HiddenWindow) { windowStyle &= ~WindowStyles.WS_VISIBLE; windowStyle &= ~WindowStyles.WS_MINIMIZE; // This will override the hide otherwise config.InitialDisplayMode = DisplayMode.Initial; } IntPtr windowHandle = User32.CreateWindowEx( DEFAULT_WINDOW_STYLE_EX, CLASS_NAME, config.HostTitle, windowStyle, (int)CreateWindowFlags.CW_USEDEFAULT, (int)CreateWindowFlags.CW_USEDEFAULT, // Position - default initialWidth, initialHeight, // Size - initial IntPtr.Zero, // No parent window IntPtr.Zero, // No window menu Kernel32.GetModuleHandle(null), IntPtr.Zero ); if (windowHandle == IntPtr.Zero) { CheckError("Couldn't create window.", true); return; } Engine.Log.Trace("Window created.", MessageSource.Win32); string[] args = Environment.GetCommandLineArgs(); bool forceAngle = CommandLineParser.FindArgument(args, "angle", out string _); bool forceMesa = CommandLineParser.FindArgument(args, "software", out string _); // Create graphics context. if (!forceAngle && !forceMesa) { try { var wgl = new WglGraphicsContext(); wgl.Init(User32.GetDC(_helperWindowHandle), windowHandle, this); if (wgl.Valid) { Context = wgl; } } catch (Exception ex) { Engine.Log.Warning($"Couldn't create WGL context, falling back if possible.\n{ex}", MessageSource.Win32); } } #if ANGLE if (Context == null && !forceMesa) { try { var egl = new EglGraphicsContext(); egl.Init(User32.GetDC(windowHandle), windowHandle, this); if (egl.Valid) { Context = egl; } } catch (Exception ex) { Engine.Log.Warning($"Couldn't create EGL context, falling back if possible.\n{ex}", MessageSource.Win32); } } #endif if (Context == null) { try { var gallium = new GalliumGraphicsContext(); gallium.Init(windowHandle, this); if (gallium.Valid) { Context = gallium; } } catch (Exception ex) { Engine.CriticalError(new Exception("Couldn't create MESA context.", ex)); } } if (Context == null) { Engine.CriticalError(new Exception("Couldn't create graphics context!")); return; } // Adjust window size to account for DPI scaling of the window frame and optionally DPI scaling of the content area. // This cannot be done until we know what monitor it was placed on - so it's done post creation. var rect = new Rect { Right = (int)config.HostSize.X, Bottom = (int)config.HostSize.Y }; rect.ClientToScreen(windowHandle); GetFullWindowRect(ref rect); User32.SetWindowPos(_windowHandle, IntPtr.Zero, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, WindowPositionFlags.SWP_NOACTIVATE | WindowPositionFlags.SWP_NOZORDER); _windowHandle = windowHandle; }