/// <summary> /// Finds valid device settings based upon the desired settings. /// </summary> /// <param name="settings">The desired settings.</param> /// <returns>The best valid device settings matching the input settings.</returns> public static DeviceSettings FindValidSettings(DeviceSettings settings) { try { GraphicsDeviceManager.EnsureD3D9(); } catch (Exception e) { throw new NoCompatibleDevicesException("Could not initialize Direct3D9.", e); } if (!Enumeration9.HasEnumerated) { Enumeration9.Enumerate(); } DeviceSettings newSettings = settings.Clone(); Direct3D9Settings d3d9 = FindValidD3D9Settings(settings); newSettings.Direct3D9 = d3d9; return(newSettings); }
void CreateDevice(DeviceSettings settings) { DeviceSettings oldSettings = CurrentSettings; CurrentSettings = settings; ignoreSizeChanges = true; bool keepCurrentWindowSize = false; if (settings.BackBufferWidth == 0 && settings.BackBufferHeight == 0) { keepCurrentWindowSize = true; } // handle the window state in Direct3D9 (it will be handled for us in DXGI) // check if we are going to windowed or fullscreen mode if (settings.Windowed) { if (oldSettings != null && !oldSettings.Windowed) { NativeMethods.SetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE, (uint)windowedStyle); } } else { if (oldSettings == null || oldSettings.Windowed) { savedTopmost = game.Window.TopMost; long style = NativeMethods.GetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE); style &= ~WindowConstants.WS_MAXIMIZE & ~WindowConstants.WS_MINIMIZE; windowedStyle = style; windowedPlacement = new WINDOWPLACEMENT(); windowedPlacement.length = WINDOWPLACEMENT.Length; NativeMethods.GetWindowPlacement(game.Window.Handle, ref windowedPlacement); } // hide the window until we are done messing with it game.Window.Hide(); NativeMethods.SetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE, (uint)(WindowConstants.WS_POPUP | WindowConstants.WS_SYSMENU)); WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); placement.length = WINDOWPLACEMENT.Length; NativeMethods.GetWindowPlacement(game.Window.Handle, ref placement); // check if we are in the middle of a restore if ((placement.flags & WindowConstants.WPF_RESTORETOMAXIMIZED) != 0) { // update the flags to avoid sizing issues placement.flags &= ~WindowConstants.WPF_RESTORETOMAXIMIZED; placement.showCmd = WindowConstants.SW_RESTORE; NativeMethods.SetWindowPlacement(game.Window.Handle, ref placement); } } if (settings.Windowed) { if (oldSettings != null && !oldSettings.Windowed) { fullscreenWindowWidth = oldSettings.BackBufferWidth; fullscreenWindowHeight = oldSettings.BackBufferHeight; } } else { if (oldSettings != null && oldSettings.Windowed) { windowedWindowWidth = oldSettings.BackBufferWidth; windowedWindowHeight = oldSettings.BackBufferHeight; } } // check if the device can be reset, or if we need to completely recreate it Result result = SlimDX.Direct3D9.ResultCode.Success; bool canReset = CanDeviceBeReset(oldSettings, settings); if (canReset) { result = ResetDevice(); } if (result == SlimDX.Direct3D9.ResultCode.DeviceLost) { deviceLost = true; } else if (!canReset || result.IsFailure) { if (oldSettings != null) { ReleaseDevice(); } InitializeDevice(); } UpdateDeviceInformation(); // check if we changed from fullscreen to windowed mode if (oldSettings != null && !oldSettings.Windowed && settings.Windowed) { NativeMethods.SetWindowPlacement(game.Window.Handle, ref windowedPlacement); game.Window.TopMost = savedTopmost; } // check if we need to resize if (settings.Windowed && !keepCurrentWindowSize) { int width; int height; if (NativeMethods.IsIconic(game.Window.Handle)) { WINDOWPLACEMENT placement = new WINDOWPLACEMENT(); placement.length = WINDOWPLACEMENT.Length; NativeMethods.GetWindowPlacement(game.Window.Handle, ref placement); // check if we are being restored if ((placement.flags & WindowConstants.WPF_RESTORETOMAXIMIZED) != 0 && placement.showCmd == WindowConstants.SW_SHOWMINIMIZED) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE); Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle); width = rect.Width; height = rect.Height; NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_MINIMIZE); } else { NativeRectangle frame = new NativeRectangle(); NativeMethods.AdjustWindowRect(ref frame, (uint)windowedStyle, false); int frameWidth = frame.right - frame.left; int frameHeight = frame.bottom - frame.top; width = placement.rcNormalPosition.right - placement.rcNormalPosition.left - frameWidth; height = placement.rcNormalPosition.bottom - placement.rcNormalPosition.top - frameHeight; } } else { Rectangle rect = NativeMethods.GetClientRectangle(game.Window.Handle); width = rect.Width; height = rect.Height; } // check if we have a different desired size if (width != settings.BackBufferWidth || height != settings.BackBufferHeight) { if (NativeMethods.IsIconic(game.Window.Handle)) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE); } if (NativeMethods.IsZoomed(game.Window.Handle)) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_RESTORE); } NativeRectangle rect = new NativeRectangle(); rect.right = settings.BackBufferWidth; rect.bottom = settings.BackBufferHeight; NativeMethods.AdjustWindowRect(ref rect, NativeMethods.GetWindowLong(game.Window.Handle, WindowConstants.GWL_STYLE), false); NativeMethods.SetWindowPos(game.Window.Handle, IntPtr.Zero, 0, 0, rect.right - rect.left, rect.bottom - rect.top, WindowConstants.SWP_NOZORDER | WindowConstants.SWP_NOMOVE); Rectangle r = NativeMethods.GetClientRectangle(game.Window.Handle); int clientWidth = r.Width; int clientHeight = r.Height; // check if the size was modified by Windows if (clientWidth != settings.BackBufferWidth || clientHeight != settings.BackBufferHeight) { DeviceSettings newSettings = CurrentSettings.Clone(); newSettings.BackBufferWidth = 0; newSettings.BackBufferHeight = 0; if (newSettings.Direct3D9 != null) { newSettings.Direct3D9.PresentParameters.BackBufferWidth = GameWindowSize.Width; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize newSettings.Direct3D9.PresentParameters.BackBufferHeight = GameWindowSize.Height; // #23510 2010.10.31 add yyagi: to avoid setting BackBufferSize=ClientSize } CreateDevice(newSettings); } } } // if the window is still hidden, make sure it is shown if (!game.Window.Visible) { NativeMethods.ShowWindow(game.Window.Handle, WindowConstants.SW_SHOW); } // set the execution state of the thread if (!IsWindowed) { NativeMethods.SetThreadExecutionState(WindowConstants.ES_DISPLAY_REQUIRED | WindowConstants.ES_CONTINUOUS); } else { NativeMethods.SetThreadExecutionState(WindowConstants.ES_CONTINUOUS); } ignoreSizeChanges = false; }