首页 > 其他分享 >UNO 设置平台进入全屏窗口模式的方法

UNO 设置平台进入全屏窗口模式的方法

时间:2024-09-12 08:55:04浏览次数:12  
标签:窗口 代码 PlatformProvider window void 全屏 public UNO

本文记录在 UNO Platform 的桌面窗口项目里,进入和退出全屏窗口的方法,此方法包括 UNO 的 WPF 和 GTK 和 WinUI 版本的实现

在 2024.06 的 5.2.139 的 UNO 版本里面,可通过如下简单方法进入全屏

Microsoft.UI.Xaml.Window window = ...
window.AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen);

通过如上方式即可让某个窗口进入全屏

以下为旧实现方法


实现思路是添加抽象的 IPlatformProvider 接口,在接口里面分别添加进入全屏和退出全屏的方法,如以下代码。接着再分别在 Skia.GTK 和 Skia.WPF 和 WinUI 平台上实现对接方法。所谓跨平台,就是各个平台都实现一遍

public interface IPlatformProvider
{
    void EnterFullScreen();
    void ExitFullScreen();
}

为了方便让 UNO 统一平台的项目可以方便使用,再定义一个静态类,用于注入 IPlatformProvider 的各个平台的实现。此处如果依赖注入机制方便对接的话,也可以对接一份进入到容器里,如果不方便对接,那就继续沿用静态类型

public static class PlatformHelper
{
    public static IPlatformProvider? PlatformProvider
    {
        get => _platformProvider;
        set
        {
            if (_platformProvider != null)
            {
                throw new InvalidOperationException("PlatformProvider can only be set once");
            }

            _platformProvider = value;
        }
    }

    private static IPlatformProvider? _platformProvider;
}

以下是各个平台的具体实现

在 WPF 平台下的实现,我使用的是 WPF 稳定的全屏化窗口方法 博客里面提供的方式进行全屏,以下代码省略 FullScreenHelper 的代码,大家可以在本文末尾获取到全部代码

public class PlatformProvider : IPlatformProvider
{
    public PlatformProvider(Window window)
    {
        _window = window;
    }

    private readonly Window _window;

    public void EnterFullScreen()
    {
        FullScreenHelper.StartFullScreen(_window);
    }

    public void ExitFullScreen()
    {
        FullScreenHelper.EndFullScreen(_window);
    }
}

如果想要达成更好的效果,可以使用以下 walterlv 大佬提供的方法,额外设置 WindowChrome 修复边框白边

    internal class WindowPlatformProvider : IPlatformProvider
    {
        private readonly Window _window;
        private readonly WindowChrome _windowChrome;

        public WindowPlatformProvider(Window window)
        {
            _window = window;
            _windowChrome = new WindowChrome
            {
                GlassFrameThickness = WindowChrome.GlassFrameCompleteThickness,
                CaptionHeight = 32,
                CornerRadius = new CornerRadius(),
                ResizeBorderThickness = new Thickness(6),
                UseAeroCaptionButtons = false,
            };
            WindowChrome.SetWindowChrome(_window, _windowChrome);
        }

        public bool IsFullScreen { get; private set; }

        public void EnterFullScreen()
        {
            IsFullScreen = true;
            _window.WindowStyle = WindowStyle.None;
            WindowChrome.SetWindowChrome(_window, null);
            FullScreenHelper.StartFullScreen(_window);
        }

        public void ExitFullScreen()
        {
            IsFullScreen = false;
            _window.WindowStyle = WindowStyle.SingleBorderWindow;
            WindowChrome.SetWindowChrome(_window, _windowChrome);
            FullScreenHelper.EndFullScreen(_window);
        }
    }

对接的代码放在 App.xaml.cs 的 构造 里面,如以下代码

public partial class App : WpfApp
{
    public App()
    {
        var host = new WpfHost(Dispatcher, () => new AppHead());
        host.Run();
        PlatformHelper.PlatformProvider = new PlatformProvider(MainWindow!);
    }
}

下面是 WinUI 项目里面的定义,代码如下

internal class PlatformProvider : IPlatformProvider
{
    public PlatformProvider(Window window)
    {
        _window = window;
    }

    private readonly Window _window;

    public void EnterFullScreen()
    {
        _window.AppWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
    }

    public void ExitFullScreen()
    {
        _window.AppWindow.SetPresenter(AppWindowPresenterKind.Default);
    }
}

对应的对接代码需要编写在 AppHead.xaml.cs 的 OnLaunched 里面,如以下代码

    protected override void OnLaunched(LaunchActivatedEventArgs args)
    {
        base.OnLaunched(args);
#if WINDOWS10_0_17763_0_OR_GREATER
        PlatformHelper.PlatformProvider = new PlatformProvider(MainWindow!);
#endif
        MainWindow.SetWindowIcon();
    }

额外的关于 UWP 的全屏,请参阅 win10 UWP 全屏

最后是 GTK 项目的平台定义,代码如下

public class GtkPlatformProvider : IPlatformProvider
{
    public GtkPlatformProvider(GtkHost gtkHost)
    {
        _gtkHost = gtkHost;
    }

    private readonly GtkHost _gtkHost;

    public void EnterFullScreen()
    {
        _gtkHost.Window?.Fullscreen();
    }

    public void ExitFullScreen()
    {
        _gtkHost.Window?.Unfullscreen();
    }
}

对应的 GTK 对接代码如下

    public static void Main(string[] args)
    {
        ExceptionManager.UnhandledException += delegate (UnhandledExceptionArgs expArgs)
        {
            Console.WriteLine("GLIB UNHANDLED EXCEPTION" + expArgs.ExceptionObject.ToString());
            expArgs.ExitApplication = true;
        };

        var host = new GtkHost(() => new AppHead());
        PlatformHelper.PlatformProvider = new GtkPlatformProvider(host);
        host.Run();
    }

如果仅需更改 GTK 窗口尺寸,请参阅 UNO.Skia.Gtk 设置窗口尺寸变化方法

以上代码就完成了 UNO 的 WPF 和 GTK 和 WinUI 桌面平台的窗口全屏的实现。为了测试效果,进入 MainPage.xaml 里面添加一个 ToggleButton 按钮,用来控制进入和退出全屏,界面代码如下

    <ToggleButton x:Name="FullScreenButton" HorizontalAlignment="Center" VerticalAlignment="Center" Click="FullScreenButton_OnClick">全屏</ToggleButton>

后台代码如下

    private void FullScreenButton_OnClick(object sender, RoutedEventArgs e)
    {
        var toggleButton = (ToggleButton) sender;
        if (toggleButton.IsChecked is true)
        {
            PlatformHelper.PlatformProvider?.EnterFullScreen();
        }
        else
        {
            PlatformHelper.PlatformProvider?.ExitFullScreen();
        }
    }

完成代码之后,分别切换到 UNO 的 WPF 和 GTK 和 WinUI 平台上,进行构建和运行项目。测试点击全屏按钮时,是否能够符合预期的进入和退出全屏模式。如下图是在 UOS 上使用 Skia.GTK 的测试效果

代码放在 githubgitee 上,可以使用如下命令行拉取代码

先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码

git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 0b1371317210b0a5e000484d57ee3ae7fc844e24

以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码,将 gitee 源换成 github 源进行拉取代码

git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin 0b1371317210b0a5e000484d57ee3ae7fc844e24

获取代码之后,进入 RalllawfairlekolairHemyiqearkice 文件夹,即可获取到源代码

标签:窗口,代码,PlatformProvider,window,void,全屏,public,UNO
From: https://www.cnblogs.com/lindexi/p/18030699

相关文章

  • Pipelines.Sockets.Unofficial 一个纯托管实现对接 System.IO.Pipelines 的 Sockets
    本文将和大家介绍Pipelines.Sockets.Unofficial这个由纯托管代码实现的,对接了System.IO.Pipelines的Sockets库。这个库不仅代码性能高,且上层调用的API足够简洁本文介绍的Pipelines.Sockets.Unofficial库是在GitHub上使用最友好的MIT协议开源的项目,详细请参阅https......
  • WPF UNO 测试固定尺寸且水平和垂直对齐设置 Stretch 的元素在容器内的布局行为
    本文将告诉大家我对WPF的自定义布局容器和自定义控件进行的布局行为测试中的一个小点,即测试固定元素的尺寸的情况下或元素尺寸为有限尺寸的情况下,同步设置元素的水平和垂直对齐为Stretch来测试元素在容器内的布局行为,元素分别在容器给元素的布局尺寸大于元素的尺寸和小于元素......
  • LeetCode算法—滑动窗口
    一:滑动窗口1、窗口:滑动窗口的核心就是一个窗口;通常使用两个指针表示(一个指向左边界;一个指向右边界);窗口中的元素就是当前字串2、滑动:窗口从数组或字符串的起始位置开始,逐步向右滑动。当窗口无法满足条件时,调整左边界以缩小窗口;当窗口满足条件时,尝试记录当前窗口的结果,并继续调整......
  • 滑动窗口&动态规划-1031. 两个非重叠子数组的最大和
    问题描述问题求解本题还挺巧妙,有点类似两数和的扩展题。对于两个线段,我们可以固定右线段,然后寻找左线段的最大值。固定右线段使用到的算法是滑动窗口,寻找左线段最大值的算法是动态规划。时间复杂度:O(n)classSolution:defmaximizeWin(self,prizePositions:List[int......
  • 震惊!!一男子用尽了各种方式都搜不到这个资源,于是他竟然将手伸向了......!?pyqt pyside
    震惊!!一男子用尽了各种方式都搜不到这个资源,于是他竟然将手伸向了......!?pyqtpyside随窗口自适应、可缩放、拖动QLabel需求场景实现功能和使用1.参数设置2.设置图片3.缩放4.拖动5.小惊喜(裁剪图片)完整使用案例1.使用QtDesigner设计一个简单界面2.引用制......
  • LeetCode:2555. 两个线段获得的最多奖品 动态规划+滑动窗口
    2555.两个线段获得的最多奖品today2555两个线段获得的最多奖品题目描述在X轴上有一些奖品。给你一个整数数组prizePositions,它按照非递减顺序排列,其中prizePositions[i]是第i件奖品的位置。数轴上一个位置可能会有多件奖品。再给你一个整数k。你可以选择两......
  • 一文带你学会使用滑动窗口
    ​​......
  • CG学习笔记 / 创建窗口、消息循环、窗口消息
    #include<Windows.h>LRESULTCALLBACKWndProc(HWNDhwnd,UINTmsg,WPARAMwParam,LPARAMlParam){ switch(msg) { caseWM_CLOSE: PostQuitMessage(69);//exitCode->wParam break; caseWM_KEYDOWN: if(wParam=='F') { Set......
  • 洛谷题单指南-常见优化技巧-P1886 滑动窗口 /【模板】单调队列
    原题链接:https://www.luogu.com.cn/problem/P1886题意解读:单调队列模版题。解题思路:采用双端队列维护单调的序列,单调队列三部曲:1、去头,当窗口内元素个数超过k,队头出队2、去尾,当要加入的元素会破坏单调性,队尾出队3、入队,将元素的下标存入队列每一次入队后,队头元素即为窗口最......
  • TCP滑动窗口(面试)
    TCP三次握手和四次挥手TCP滑动窗口是什么?如果传输的数据比较大,需要拆分为多个数据包进行发送。如果TCP协议需要收到确认应答后,才可以发送下一个数据包。这样的方法效率偏低为了避免这种情况,TCP使用了滑动窗口。滑动窗口用于控制发送方和接收方之间的数据传输。滑动窗......