Exemplo n.º 1
0
        /// <summary>
        /// 开始进入全屏模式
        /// 进入全屏模式后,窗口可通过 API 方式(也可以用 Win + Shift + Left/Right)移动,调整大小,但会根据目标矩形寻找显示器重新调整到全屏状态。
        /// 进入全屏后,不要修改样式等窗口属性,在退出时,会恢复到进入前的状态
        /// 进入全屏模式后会禁用 DWM 过渡动画
        /// </summary>
        public static void StartFullScreen(System.Windows.Window window)
        {
            if (window == null)
            {
                throw new ArgumentNullException(nameof(window), $"{nameof(window)} 不能为 null");
            }

            //确保不在全屏模式
            if (window.GetValue(BeforeFullScreenWindowPlacementProperty) == null &&
                window.GetValue(BeforeFullScreenWindowStyleProperty) == null)
            {
                var hwnd = new WindowInteropHelper(window).EnsureHandle();
                var hwndSource = HwndSource.FromHwnd(hwnd);

                //获取当前窗口的位置大小状态并保存
                var placement = InteropMethods.GetWindowPlacement(hwnd);
                window.SetValue(BeforeFullScreenWindowPlacementProperty, placement);

                //修改窗口样式
                var style = (InteropValues.WindowStyles) InteropMethods.GetWindowLongPtr(hwnd, InteropValues.GWL_STYLE);
                window.SetValue(BeforeFullScreenWindowStyleProperty, style);
                //将窗口恢复到还原模式,在有标题栏的情况下最大化模式下无法全屏,
                //这里采用还原,不修改标题栏的方式
                //在退出全屏时,窗口原有的状态会恢复
                //去掉WS_THICKFRAME,在有该样式的情况下不能全屏
                //去掉WS_MAXIMIZEBOX,禁用最大化,如果最大化会退出全屏
                //去掉WS_MAXIMIZE,使窗口变成还原状态,不使用ShowWindow(hwnd, ShowWindowCommands.SW_RESTORE),避免看到窗口变成还原状态这一过程(也避免影响窗口的Visible状态)
                style &= ~(InteropValues.WindowStyles.WS_THICKFRAME | InteropValues.WindowStyles.WS_MAXIMIZEBOX | InteropValues.WindowStyles.WS_MAXIMIZE);
                InteropMethods.SetWindowLong(hwnd, InteropValues.GWL_STYLE, (IntPtr) style);

                //禁用 DWM 过渡动画 忽略返回值,若DWM关闭不做处理
                InteropMethods.DwmSetWindowAttribute(hwnd, InteropValues.DwmWindowAttribute.DWMWA_TRANSITIONS_FORCEDISABLED, 1,
                    sizeof(int));

                //添加Hook,在窗口尺寸位置等要发生变化时,确保全屏
                hwndSource.AddHook(KeepFullScreenHook);

                if (InteropMethods.GetWindowRect(hwnd, out var rect))
                {
                    //不能用 placement 的坐标,placement是工作区坐标,不是屏幕坐标。

                    //使用窗口当前的矩形调用下设置窗口位置和尺寸的方法,让Hook来进行调整窗口位置和尺寸到全屏模式
                    InteropMethods.SetWindowPos(hwnd, (IntPtr) InteropValues.HWND_TOP, rect.Left, rect.Top, rect.Width,
                        rect.Height, (int) InteropValues.WindowPositionFlags.SWP_NOZORDER);
                }
            }
        }