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.pswp.cn/news/285403.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285403.shtml
英文地址,請注明出處:http://en.pswp.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…

【ArcGIS風暴】ArcGIS平臺上點云(.las)數據生成等高線方法案例精解

las是點云數據常見的存儲格式,攝影測量和激光雷達數據均采用此格式,點云數據常用來生成等高線,地籍測量,土方量計算等。本文講解在ArcGIS平臺上生成等高線并轉換為dwg格式供CASS使用。 擴展閱讀: 什么是點云?什么是Las數據集?一篇文章告訴你點云數據的奧秘 ArcGIS+CASS點…

通過兩級網關設計來路由服務網格流量

編者的話本文是來自筆者的公司 Tetrate[1] 工程師 Petr McAllister 的分享&#xff0c;Tetrate 的拳頭產品是 Tetrate Service Bridge[2]&#xff08;下文簡稱 TSB&#xff09;&#xff0c;它是在開源的 Istio 和 Envoy 基礎上構建的&#xff0c;但為其增加了管理平面。簡介Tet…

各個線程順序循環執行

問題描述&#xff1a;A任務執行完之后執行B任務&#xff0c;B任務執行之后再執行C任務&#xff0c;C任務執行完之后A再執行任務&#xff0c;以此循環下去 Task 1 package com.ydd.work.concurrent;2 3 import java.util.concurrent.atomic.AtomicInteger;4 /**5 * 6 * author…

python類相關

class A:def bar(self):print("BAR")self.f1() class B(A):def f1(self):print("B") class C:def f1(self):print("C") class D(C,B):pass obj D() obj.bar() # 創建了類A、B、C、D&#xff1b; # D繼承了C和B&#xff0c;B繼承了A&#xff0c;…

Python File 介紹

Open() 方法 Python open() 方法用于打開一個文件&#xff0c;并返回文件對象&#xff0c;在對文件進行處理過程都需要使用到這個函數&#xff0c;如果該文件無法被打開&#xff0c;會拋出 OSError。 注意&#xff1a;使用 open() 方法一定要保證關閉文件對象&#xff0c;即調用…

H5開發中常用的js方法

2019獨角獸企業重金招聘Python工程師標準>>> h5和app之間的webview交互 這是常用的交互方法之一&#xff0c;iOS可以使用WKWebView,安卓可以使用JsBridge,完成常見的交互效果。function webViewHandler(iosCallback, adrCallback) {if (getMobileOperatingSystem() …

【前端優化】

如何進行前端優化 &#xff08;1&#xff09; 減少http 請求次數&#xff1a;css spirit&#xff08;多張小圖放一個大圖上&#xff0c;用定位選擇不同小圖&#xff09;,data uri&#xff08;壓縮圖片大小&#xff09;&#xff0c; 圖片大小控制合適&#xff1b;網頁Gzip&#…

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;我們無需禁用它。因為如果…

dom4j-2.1.1 jaxen-1.1.6 讀取xml數據源

<?xml version"1.0" encoding"UTF-8"?> <data><row><id>1</id><name>JackieChen</name></row><row><id>2</id><name>TomLee</name></row> </data> package…

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 、溫馨提示 想獲取更多…

吐血整理:C#順序、選擇、循環結構用法與案例,這一篇就夠了!

C#語言中用于結構化程序設計的三種基本結構是:順序結構、選擇結構、循環結構。本文詳細整理了以上三種結構的用法,案例。 文章目錄 4.1 順序結構4.1.1 賦值語句4.1.2 輸入語句4.1.3 輸出語句4.1.4 復合語句4.1.5 應用實例4.2 選擇結構4.2.1 if條件語句4.2.2 switch結構4.3 循…

java.lang.NoSuchFieldError: EMPTY_ORDERED_ITERATOR起因及解決辦法

java.lang.NoSuchFieldError: EMPTY_ORDERED_ITERATOR 最近這個錯誤遇到了好多次&#xff0c;不過都很輕松的解決了&#xff0c;問題的起因是多了一個collection包&#xff0c;如下圖 看到了&#xff0c;只要把其中的一個刪除掉&#xff0c;更新啟動Tomcat就行了。 本文轉自suc…

由ASP.NET Core根據路徑下載文件異常引發的探究

前言最近在開發新的項目&#xff0c;使用的是ASP.NET Core6.0版本的框架。由于項目中存在文件下載功能&#xff0c;沒有使用類似MinIO或OSS之類的分布式文件系統&#xff0c;而是下載本地文件&#xff0c;也就是根據本地文件路徑進行下載。這其中遇到了一個問題&#xff0c;是關…

[轉]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…

XidianOJ 1019 自然數的秘密

題目描述 題意&#xff1a; 已知&#xff1a;N&#xff01;N*(N-1)*...*2*1 找到最小自然數 N, 使N!末尾有連續 M個零. 例如, 5! 的結尾包含1個零. 輸入 第一行輸入一個整數T,表示有T組測試數據。 對于每組測試數據&#xff0c;輸入一個整數M&#xff0c;表示包含M個零。&#…

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…