用 WinUI 3 開發了一個摸魚應用

1. 開發了一個摸魚 App

我做了一個簡單的 App:摸魚。

如上圖所示,這個 App 就只有一個按鈕,點擊後假裝開始 Windows Update,然後用戶就可以光明正大地摸魚了。

不要小看摸魚,所有天才的點子都不是敲鍵盤時激發的。在工作遇到阻滯時,越是投入工作越是找不到解決方案,這時候把目光從屏幕挪開,說不定在一邊洗澡一邊玩着小黃鴨時,一邊發獃一邊看着窗外時,一邊睡覺一邊扣肚子時,解決問題的靈感突然就掉進了腦海里。

所以我恬不知恥地將這個 App 發佈到了 高效工作 分類,微軟還通過了,現在可以在這裡下載到這個應用:

//www.microsoft.com/zh-cn/p/loaf-a-winui3-app/9ndj3q12nrrm

當然,如標題所說,這是個 WinUI 3 App。

2. 什麼是 WinUI 3

WinUI 3 是隨 Windows App SDK 提供的適用於 Windows 桌面應用程序和 UWP 應用程序的本機用戶體驗 (UX) 框架。簡單來說,WinUI 3 將 UWP 的 UI 層分離出來給 Win32 Windows App 使用。為了更好地理解 WinUI 3 可以參考下面的鏈接:

Windows UI 庫 (WinUI) – Windows apps

Windows UI 庫 (WinUI) 3 – Windows apps

通過 Windows 應用 SDK 生成桌面 Windows 應用 – Windows apps

Windows 應用 SDK 的穩定通道發行說明 – Windows apps

microsoft_microsoft-ui-xaml_ Windows UI Library_ the latest Windows 10 native controls and Fluent styles for your applications

microsoft-ui-xaml_roadmap

WinUI 3 試玩報告

WinUI 3 Preview 3 發佈了,再一次試試它的性能

經過長久的等待,最近,WinUI 3 好像悄悄地發佈了正式版。既沒有大型的宣傳,又沒有集成在剛剛發佈的 Visual Studio 2022 里,甚至沒看到像樣的郵件或新聞、博客,查文檔的話它好像和 Windows App SDK 一起發佈了,總之現在 WinUI 3 的 1.0 版本能用了。在把玩了一番後我覺得暫時不能把自己的 App 遷移到 WinUI 3,雖然我已經期待了很久很久。因為不能對現有應用動手,又為了更深入嘗試 WinUI 3,我做了「摸魚」這個小應用。

3. 開發過程

下面來說說開發過程。總體來說挺好玩,但也有很多挑戰。

首先,如果要使用 Visual Studio 2022 開發 WinUI 3 的 C# App,需要下載 Visual Studio 2022 的擴展:WindowsAppSDK.Cs.Extension.Dev17.Standalone.vsix。安裝擴展後才可以創建 WinUI 3 項目。

C++ 或 Visual Studio 2019 的擴展可以在以下文檔找到各自的下載鏈接:

Windows 應用 SDK 的穩定通道發行說明 – Windows apps

創建好項目後就會發現 WinUI 3 沒有設計視圖(以後應該也不會有),所以這時候最好還是再創建一個 UWP 項目,在 UWP 項目中把 XAML 設計好再複製到 WinUI 3 項目。

遷移過程中需要將大部分 Windows.* 命名空間替換成 Microsoft.*。不過 Win2D 里還在用 Windows.* 命名空間,所以搞得有些混亂。

然後就是引用各種包,微軟自己管理的 UWP 最常用的包大致上都有對應的 WinUI 版本,例如 Microsoft.Toolkit.Uwp.UI 替換為 CommunityToolkit.WinUI.UI,而 Win2D.uwp 替換為 Microsoft.Graphics.Win2D

UWP 大部分開發經驗都可以用在 WinUI 3 上,在 摸魚 這個小 App 里遇到最大的問題是 Window 管理。可能 WinUI 3 的 Window Api 還沒想好,導致連修改標題都很麻煩,需要用到好幾行代碼:

namespace SampleApp
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainWindow : Window
    {
        private AppWindow m_appWindow;

        public MainWindow()
        {
            this.InitializeComponent();
            // Get the AppWindow for our XAML Window
            m_appWindow = GetAppWindowForCurrentWindow();
            if (m_appWindow != null)
            {
                // You now have an AppWindow object and can call its methods to manipulate the window.
                // Just to do something here, let's change the title of the window...
                m_appWindow.Title = "WinUI ❤️ AppWindow";
            }
        }

        private AppWindow GetAppWindowForCurrentWindow()
        {
            IntPtr hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
            WindowId myWndId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
            return AppWindow.GetFromWindowId(myWndId);
        }
   }
}

進入全屏的代碼也和 UWP 不一樣:

///進入全屏
m_appWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
///退出全屏
m_appWindow.SetPresenter(AppWindowPresenterKind.Default);

而且全屏和 UWP 還不一樣,沒法按 Esc 鍵退出全屏,也沒有了屏幕頂部隱藏的標題欄。所以要自己捕獲全局的 Esc 鍵事件再調用代碼退出全屏(至於平板狀態怎麼退出全屏我就不知道了)。

還有一點,WinUI 3 和 UWP 的樣式有些不一樣,例如 ProgressRing 的樣式就不是 Windows 8 以來那個幾個點轉圈圈的樣式。幸好可以把 UWP 的 Style 複製過來,只需簡單修改一下。

雖然開發過程遇到很多問題,對這個小 App 來說還算輕鬆愉快。有趣的是,當遇到 WinUI 3 沒提供想要的 API 的時候可以直接調用 Win32 API 實現需求。更有趣的是,這些 Win32 API 有些有效,有些無效。

所有代碼完成後,最後一步是發佈到商店,幸好發佈流程和 UWP 的基本一致,現在已經可以在商店下載這款 App。

4. 遇到的問題

沒有設計視圖,這是個很嚴重的問題。我自己倒是還可以接受,因為起碼還有熱重載可用,但對入門不友好。

文檔混亂,幾乎所有 UWP 和 Windows App SDK 的文檔合併了,這就要命了,真的要命,例如 WinUI 3 的文檔有指向 Mica 的導航,明明 WinUI 3 都不支持 Mica。現在在 //docs.microsoft.com/en-us/windows/apps/ 頁面里甚至找不到 UWP 的入口,總之無論 UWP 還是 Windows App SDK 的文檔都一片混沌。

Demo 沒用,給我 UWP 的 Demo 就算了,連 Windows 8 的 Demo 都給我端上來就過分了。

Windows App SDK 這個名字本身就不好,所有引擎搜出來一大堆 Windows 的東西,但不是 Windows App SDK 的。

沒有 Background acrylic 和 RevealBoraderBrush,Win2D 也缺了 CanvasAnimatedControl,這些東西的缺失提高了從 UWP 遷移到 WinUI 3 的難度。

從開發到發佈一路上遇上各種一言難盡的 Bug 和小問題。

5. 最後

我記得當年 WinForms、WPF、Silverlight 的入門都相當輕鬆,後面微軟的各個 UI 越來越難,而 WinUI 3 更是最難的一個。比起 UWP,WinUI 3 本應該有巨大的優勢,但現在我建議暫時還是再等等新版本。玩玩小應用可以,生產環境要謹慎。

倒是 WinUI 2 好像越來越好玩,或者我們可以一邊玩 WinUI 2 一邊等 WinUI 3 的新版本。

6. 源碼

//github.com/DinoChan/Loaf

Tags: