Maui学习之路(三)--Winui3深入探讨

Maui的学习之路 --- Winui3深入探讨

学习Maui已经有一段时间,随着不断地深入,对Maui有了一些初步的了解。

我们都知道Maui为了保持平台原生特性,所以在每一个平台都使用了平台自身的原生开发框架,如在Windows系统使用了Winui3作为UI框架,Mac平台使用了UIKit作为UI框架,(我愿称之为“套娃”或者是对不同平台做了一层“抽象”),所以如果直接操作Maui的对象的某个属性或者方法实际他背后去转调了平台相关的属性或者方法。

有了这样的认识那么我们就会深刻的理解到如果我想改变某些东西,其实也可以自己去直接操作平台相关的方法,而并不一定需要操作Maui对象(如果Maui未提供这样的能力,你只能这么做)。

在做Windows桌面程序开发时,我们常常有这样的需求,你的exe程序同一时间只能运行一份(单例),你很希望程序打开就全屏,别人不能轻易关闭(通常在工业领域这样的需求极大)。

基于以上需求,我们来深入了解学习一下,如何实现:

首先使用Maui模板创建的每一个工程有有一个Platforms的目录,这个本质上是对应多平台的一个工程集合(在Xamarin中如果你需要构建一个真正的跨平台程序,实际是做不到的,你需要通过Xamarin.Form的模板创建不同平台的入口,然后抽出公用的平台无关逻辑来作为跨平台的共享资源),有了这个设计Maui真正实现了一份代码到处编译到处运行,而你在别的平台编译并不需要对工程做任何特别的改动(目前支持MacWindows平台编译)(这里不做深入探讨,如果你想了解MauiXamarin工程上的区别请看这个视频:.NET MAUI 跨平台开发合集_哔哩哔哩_bilibili[1]

188efb04ff5345196dc3045277f8d148.png

其次对于Maui的可执行工程(非dll)来说,对应平台的程序的真正入口并非是MauiProgramMauiApplication,他实际是Platforms下对应的平台的Main或者是App,比如对Window来说,Maui启动程序的真正入口是Platforms/Windows/App这个对象。

613382312ab73049d9c6a7ec24e6a05b.png
Window单例实现

有了上面的认识作为基础,那么实现一个单例非常简单,在Wpf或者Winform上做过相同的设计,如今只需要搬运过来即可(在Wpf或是Winform实现单例的方式很多,最常用的是使用Mutex)实现方式请查阅:零食栏 - .NET MAUI Community Toolkit - .NET Community Toolkit | Microsoft Docs [2]在Platform/Windows/App.xaml.cs中增加单例检查

public partial class App : MauiWinUIApplication
{/// <summary>/// Initializes the singleton application object.  This is the first line of authored code/// executed, and as such is the logical equivalent of main() or WinMain()./// </summary>public App(){this.InitializeComponent();}static Mutex? __SingleMutex;protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();protected override void OnLaunched(LaunchActivatedEventArgs args){if (!IsSingleInstance()){//Process.GetCurrentProcess().Kill();Environment.Exit(0);return;}base.OnLaunched(args);}static bool IsSingleInstance(){const string applicationId = "813342EB-7796-4B13-98F1-14C99E778C6E";__SingleMutex = new Mutex(false, applicationId);GC.KeepAlive(__SingleMutex);try{return __SingleMutex.WaitOne(0, false);}catch (Exception){__SingleMutex.ReleaseMutex();return __SingleMutex.WaitOne(0, false);}}
}
实现一个无边框窗体

在这之前我其实已经写过一篇Maui在windows上实现无边框的方式,有兴趣的同学可以去查阅一下(链接:Window窗体设置)。Maui实际提供了一名为Window的类型,不过很可惜这个类型中并没有任何有设置窗口相关的属性(比如:宽,高,背景色等等,另外也没法通过修改Style来修改样式),很明显Maui是一个跨平台的设计,因为在移动端并不存在所谓的窗口大小概念,通常打开都是全屏。如果我们需要对窗体进行修改,那么需要拿到Window对象后面管理的Native对象才行

获取Native对象

  • 方法1:注册Maui提供的生命周期函数

在不同的平台会推送相关的程序生命周期通知(在这里可以获取到平台相关操作对象包括对应的ApplicationWindow),使用这个方式存在一些弊端就是当使用多窗体方案时,你没法定位哪个是主窗体(当然第一个创建的必然就是主窗体了),详情请看:应用生命周期 - .NET MAUI | Microsoft Docs[3](这里不做过多探讨如果你像知道细节可以看这个视频:.NET MAUI BLAZOR 生命周期_哔哩哔哩_bilibili[4]

  • 方法2:访问Window下的Handler属性

Maui Window类型中存在这样一个属性Handler(类型是IElementHandler,实现类型是ElementHandler)(所有的Maui控件对象都存在这个个属性),该属性中记录了平台的Native映射对象(如果你希望修改native对象的外观,可以访问他下属的属性PlatformView(将其转换成对应平台的native对象))(注意在刚开始new Window对象时Handler对象并不存在,你可以注册HandlerChanged事件捕获他的变化)(在Winodw平台PlatformView对象是Microsoft.UI.Xaml.Window类型)

学习必要的Winui3相关知识

Winui开始微软带来了窗口的全新设计,如果需要实现诸如窗口大小修改,标题栏修改,全屏实现等等功能你需要学习如下知识:

  • 自定义标题栏

链接:标题栏自定义 - Windows apps | Microsoft Docs[5]

  • AppWindow

这是Win10之后引入的窗口操作对象,学习链接:使用 AppWindow 类显示应用的辅助窗口 - Windows apps | Microsoft Docs[6]以及AppWindow Class (Microsoft.UI.Windowing) - Windows App SDK | Microsoft Docs[7]

注意:官网相关的学习资料在不同的文档中介绍存在偏差,主要是部分设计是老设计,尚未及时更新,请以Windows App SDK 1.1版本为准

通过学习以上知识,我们可以进行部分功能定制

  1. 更改窗口尺寸:

var winuiWindow = Window.Handler?.PlatformView as MicrosoftuiXaml.Window;if (winuiWindow is null)return;var appWindow = winuiWindow.GetAppWindow();if (appWindow is null)return;var displyArea = MicrosoftuiWindowing.DisplayArea.Primary;double scalingFactor = winuiWindow.GetDisplayDensity();var width = 800 * scalingFactor;var height = 600 * scalingFactor;double startX = (displyArea.WorkArea.Width - width) / 2.0;double startY = (displyArea.WorkArea.Height - height) / 2.0;appWindow.MoveAndResize(new((int)startX, (int)startY, (int)width, (int)height), displyArea);
  1. 最大化(使用Win32消息):

var winuiWindow = Window.Handler?.PlatformView as MicrosoftuiXaml.Window;if (winuiWindow is null)return;var windowHanlde = winuiWindow.GetWindowHandle();User32.PostMessage(windowHanlde, WindowMessage.WM_SYSCOMMAND, new IntPtr((int)SysCommands.SC_MINIMIZE), IntPtr.Zero);
  1. 最小化(使用Win32消息):

var winuiWindow = Window.Handler?.PlatformView as MicrosoftuiXaml.Window;if (winuiWindow is null)return;var windowHanlde = winuiWindow.GetWindowHandle();User32.PostMessage(windowHanlde, WindowMessage.WM_SYSCOMMAND, new IntPtr((int)SysCommands.SC_MINIMIZE), IntPtr.Zero);
  1. 全屏:

var winuiWindow = Window.Handler?.PlatformView as MicrosoftuiXaml.Window;if (winuiWindow is null)return;var appWindow = winuiWindow.GetAppWindow();if (appWindow is null)return;//注意由于Maui默认开启了扩展TitleBar(标题栏融合模式?)所以先要去掉 否则全屏仍然会出现 关闭等按钮//虽然关闭了标题栏融合模式,但是全屏时仍然会存在一个类似标题栏的东西,如果需要处理需要进行深度定制(可以查看我的github项目)winuiWindow.ExtendsContentIntoTitleBar = false;appWindow.SetPresenter(MicrosoftuiWindowing.AppWindowPresenterKind.FullScreen);
  1. 修改Maui默认标题栏颜色:

var winuiWindow = Window.Handler?.PlatformView as MicrosoftuiXaml.Window;if (winuiWindow is null)return;var application = MicrosoftuiXaml.Application.Current;var res = application.Resources;//看到这里你一定会疑惑为什么是这样,如果你有兴趣,可以查阅Winui3的源码res["WindowCaptionBackground"] = new MicrosoftuixmlMedia.SolidColorBrush(Microsoftui.Colors.Red);//修改标题栏后需要主动刷新才会生效(否则需要你人为进行一次最小化处理)TriggertTitleBarRepaint();

以上Demo都已经上传Github 地址:WPFDevelopersOrg/Demo[8] ,请查阅MauiApp1这个demo

最后放一个目前我已经实现的Maui Win11的演示效果:

该项目已上传github地址:WPFDevelopersOrg/MauiToolkit[9]

参考资料

[1]

.NET MAUI 跨平台开发合集_哔哩哔哩_bilibili: https://www.bilibili.com/video/BV1VW4y1k7Bk?p=3

[2]

零食栏 - .NET MAUI Community Toolkit - .NET Community Toolkit | Microsoft Docs : https://docs.microsoft.com/zh-cn/dotnet/communitytoolkit/maui/alerts/snackbar

[3]

应用生命周期 - .NET MAUI | Microsoft Docs: https://docs.microsoft.com/zh-cn/dotnet/maui/fundamentals/app-lifecycle

[4]

.NET MAUI BLAZOR 生命周期_哔哩哔哩_bilibili: https://www.bilibili.com/video/BV1vA4y1d74A?spm_id_from=333.999.0.0

[5]

标题栏自定义 - Windows apps | Microsoft Docs: https://docs.microsoft.com/zh-cn/windows/apps/develop/title-bar?tabs=winui3

[6]

使用 AppWindow 类显示应用的辅助窗口 - Windows apps | Microsoft Docs: https://docs.microsoft.com/zh-cn/windows/apps/design/layout/app-window

[7]

AppWindow Class (Microsoft.UI.Windowing) - Windows App SDK | Microsoft Docs: https://docs.microsoft.com/zh-CN/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindow?view=windows-app-sdk-1.1

[8]

WPFDevelopersOrg/Demo: https://github.com/WPFDevelopersOrg/Demo

[9]

WPFDevelopersOrg/MauiToolkit: https://github.com/WPFDevelopersOrg/MauiToolkit

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos 7.1 apache 源码编译安装

Apache编译安装 一&#xff0c;需要软件&#xff1a; http://mirrors.cnnic.cn/apache//apr/apr-1.5.2.tar.gz 1.apr-1.5.2.tar.gz http://mirrors.cnnic.cn/apache//apr/apr-util-1.5.4.tar.gz 2.apr-util-1.5.4.tar.gz http://exim.mirror.fr/pcre/pcre-8.38.tar.gz 3.pcre-8…

通过两级网关设计来路由服务网格流量

编者的话本文是来自笔者的公司 Tetrate[1] 工程师 Petr McAllister 的分享&#xff0c;Tetrate 的拳头产品是 Tetrate Service Bridge[2]&#xff08;下文简称 TSB&#xff09;&#xff0c;它是在开源的 Istio 和 Envoy 基础上构建的&#xff0c;但为其增加了管理平面。简介Tet…

H5开发中常用的js方法

2019独角兽企业重金招聘Python工程师标准>>> h5和app之间的webview交互 这是常用的交互方法之一&#xff0c;iOS可以使用WKWebView,安卓可以使用JsBridge,完成常见的交互效果。function webViewHandler(iosCallback, adrCallback) {if (getMobileOperatingSystem() …

GPS RTK(银河1)基准站架设、移动站设置完整操作流程

本文讲解GPS RTK(银河1)基站架设完整操作流程,包括相对坐标、点校正等操作。 文章目录 一、架设基准站二、启动基准站三、架设移动站四、设置移动站一、架设基准站 基准站一定要架设在视野比较开阔,周围环境比较空旷的地方,地势比较高的地方;避免架在高压输变电设备附近…

在.NET 6.0上使用Kestrel配置和自定义HTTPS

本章是《定制ASP NET 6.0框架系列文章》的第四篇。在本章&#xff0c;我们将学习ASP.NET Core的Kestrel配置和自定义HTTPS&#xff0c;好我们开始正文。在ASP.NET Core中&#xff0c;默认情况下HTTPS处于打开状态&#xff0c;这个不是问题&#xff0c;我们无需禁用它。因为如果…

Virtualbox安装增强工具失败

在安装Virtualbox增强工具安装时出现unable to find the sources of your current Linux kernel&#xff0c;安装失败&#xff0c;导致主机与虚拟机之间不能共享文件夹&#xff0c;不能复制粘贴&#xff0c;鼠标也不能直接移动到物理机&#xff0c;需要按快捷键才行。 解决办法…

C语言试题118之求1到20的每个数的阶层之和

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:求 1+2!+3!+…+20!的和 分析:此程序只是把累加变成了累乘。 2 、温馨提示 想获取更多…

java.lang.NoSuchFieldError: EMPTY_ORDERED_ITERATOR起因及解决办法

java.lang.NoSuchFieldError: EMPTY_ORDERED_ITERATOR 最近这个错误遇到了好多次&#xff0c;不过都很轻松的解决了&#xff0c;问题的起因是多了一个collection包&#xff0c;如下图 看到了&#xff0c;只要把其中的一个删除掉&#xff0c;更新启动Tomcat就行了。 本文转自suc…

[转]EL函数、自定义EL函数、自定义标签

EL函数 1、EL函数的作用&#xff1a;操作字符串 2、在JSP页面中要引入EL函数库 <% taglib prefix"fn" uri"http://java.sun.com/jsp/jstl/functions" %> 3、语法 ${ fn:方法名(参数) } 4、实例 <% page language"java" contentTyp…

C语言试题119之利用递归方法求 5的阶层

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:利用递归方法求 5的阶层 分析:递归公式:fn=fn_1*4的阶层 2 、温馨提示 想获取更多C…

深入学习http协议(转)

http://www.blogjava.net/zjusuyong/articles/304788.html转载来的&#xff0c;没看到原文地址。http协议学习系列1. 基础概念篇1.1 介绍HTTP是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写。它的发展是万维网协会&#xff08;World Wide Web Co…

CSS浮动属性Float到底什么怎么回事,下面详细解释一下

float 是 css 的定位属性。在传统的印刷布局中&#xff0c;文本可以按照需要围绕图片。一般把这种方式称为“文本环绕”。在网页设计中&#xff0c;应用了CSS的float属性的页面元素就像在印刷布局里面的被文字包围的图片一样。浮动的元素仍然是网页流的一部分。这与使用绝对 定…

MAUI Developer Day in GCR

点击蓝字关注我们编辑&#xff1a;Alan Wang排版&#xff1a;Rani Sun活动介绍作为一个支持在单一代码库中开发能够运行在 Android、iOS、macOS 和 Windows 等多平台的应用程序的跨平台框架&#xff0c;.NET MAUI &#xff08;多平台应用程序用户界面&#xff09;还在预览版时就…

C语言试题126之请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二个字母。

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 判断第二…

【ArcGIS风暴】ArcGIS点云抽稀(稀疏化LAS点)详解案例教程

考虑对过采样 LAS 数据(例如通过摄影测量方式获得的点云以及多个叠加激光雷达扫描的返回值)使用稀疏化LAS点工具,以优化显示性能和加速分析操作。 文章目录 1. 创建las数据集2. 稀疏化LAS点适用版本:ArcGIS10.6以上。 1. 创建las数据集 扩展阅读:ArcGIS10.6创建LAS数据集…

20145313张雪纯《信息安全系统设计基础》第11周学习总结

20145313张雪纯《信息安全系统设计基础》第11周学习总结 教材 异常控制流&#xff08;ECF&#xff09; 最简单的“平滑序列”类型的控制流是指PC中相邻的指令在存储器中也相邻。而异常控制流则是指程序变量表示的内部程序状态中的变化、系统状态的变化等突发情况使得控制系统做…

Silverlight 5 beta新特性探索系列:9.视频快进快退和TextSearch对象对文字项查询

本节讲诉两个新特性&#xff1a;一、在Silverlight 5中可以控制MediaElement对象播放的视频进行快进快退控制。二、在Silverlight 5中的文字项进行搜索查询。 一、对于MediaElement媒体播放对象的视频进行快退快进控制 它是通过MediaElement.PlaybackRate属性进行控制的。当前此…

【错误异常大全】:ArcGIS Engine中C#无法引用ESRI.ArcGIS.AxControls问题

ArcGIS Engine中C#无法引用ESRI.ArcGIS.AxControls问题&#xff0c;具体如下。 发现在引用列表中找不到ESRI.ArcGIS.AxControls服务。 一直显示感叹号。 多次尝试添加无果&#xff0c;解决方法&#xff1a;选中引用列表中的ESRI.ArcGIS.AxControls&#xff0c;在属性表窗口中将…

C语言试题122之利用递归函数调用方式,将所输入的 5 个字符,以相反顺序打印出来。

✅作者简介:大家好我是码莎拉蒂,CSDN博客专家🥇🥇🥇 📃个人主页:个人主页 🔥系列专栏:C语言试题200例 💬推荐一款模拟面试、刷题神器👉 点击跳转进入网站 1、题目 题目:利用递归函数调用方式,将所输入的 5 个字符,以相反顺序打印出来。 2 、温馨提示 想…