Exemple #1
0
        /// <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;
        }