用 WinUI 3 开发了一个摸鱼应用
1. 开发了一个摸鱼 App
我做了一个简单的 App:摸鱼。


如上图所示,这个 App 就只有一个按钮,点击后假装开始 Windows Update,然后用户就可以光明正大地摸鱼了。
不要小看摸鱼,所有天才的点子都不是敲键盘时激发的。在工作遇到阻滞时,越是投入工作越是找不到解决方案,这时候把目光从屏幕挪开,说不定在一边洗澡一边玩着小黄鸭时,一边发呆一边看着窗外时,一边睡觉一边扣肚子时,解决问题的灵感突然就掉进了脑海里。
所以我恬不知耻地将这个 App 发布到了 高效工作 分类,微软还通过了,现在可以在这里下载到这个应用:
https://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
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。现在在 https://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. 源码
https://github.com/DinoChan/Loaf
用 WinUI 3 开发了一个摸鱼应用的更多相关文章
- 模仿写了一个摸鱼APP解决原作者的问题
前几天见到微博里有人提到摸鱼APP,发现需要在windows store下载才可以使用,文件约100多M左右的样子,自已没有登录微软Store的习惯.想想只有一个介面,没有必要这么大,于是,自已动手写 ...
- 【转】让Chrome化身成为摸鱼神器,利用Chorme运行布卡漫画以及其他安卓APK应用教程
下周就是十一了,无论是学生党还是工作党,大家的大概都会有点心不在焉,为了让大家更好的心不在焉,更好的在十一前最后一周愉快的摸鱼,今天就写一个如何让Chrome(google浏览器)运行安卓APK应用的 ...
- 春节前“摸鱼”指南——SCA命令行工具助你快速构建FaaS服务
春节将至,身在公司的你是不是已经完全丧失了工作的斗志? 但俗话说得好:"只要心中有沙,办公室也能是马尔代夫." 职场人如何才能做到最大效能地带薪"摸鱼",成为了 ...
- 删库吧,Bug浪——我们在同一家摸鱼的公司
那些口口声声, Bug越来越难写人的,应该盯着你们: 像我一样,我盯着你们,满眼恨意. IT积攒了几十年的漏洞, 所有的死机.溢出.404和超时, 像是专门为你们准备的礼物. 圈复杂度.魔鬼变量.内存 ...
- 老板防止我上班摸鱼,给我装了个chrome插件
<铁柱幻想的摸鱼生活> 9:30:到达公司,开开电脑,收拾一下办公桌 9:40:吃个早餐,接杯水(一定要多喝水,一个肾结石同事的出院后的衷心建议) 10:00:打开"技术网站&q ...
- 寒武纪加速平台(MLU200系列) 摸鱼指南(二)--- 模型移植-环境搭建
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- 寒武纪加速平台(MLU200系列) 摸鱼指南(四)--- 边缘端实例程序分析
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- 使用MyBatis拦截器后,摸鱼时间又长了。🐟
场景 在后端服务开发时,现在很流行的框架组合就是SSM(SpringBoot + Spring + MyBatis),在我们进行一些业务系统开发时,会有很多的业务数据表,而表中的信息从新插入开始,整个 ...
- 菜鸡学C语言之摸鱼村村长
题目描述 摸鱼村要选村长了! 选村长的规则是村里每个人进行一次投票,票数大于人数一半的成为村长. 然鹅摸鱼村的人都比较懒,你能帮他们写一个程序来找出谁当选村长吗? (每名村民的编号都是一个int范围内 ...
随机推荐
- mongodb(一)
文档是 MongoDB 的核心,类似于 SQLite 数据库(关系数据库)中的每一行数据.多个键及其关联的值放在一起就是文档.在 Mongodb 中使用一种类 json 的 bson 存储数据,bso ...
- linux安全 设置登录失败次数后,拒绝登录
设置登录失败3次后锁定用户300秒可以通过配合文件/etc/pam.d/sshd配置如下 在第一行 #%PAM-1.0 的下一行添加1a auth required pam_tally2.so den ...
- <C#任务导引教程>练习九
//75,异常情况using System;class Program{ public static void Main() { Console.Write("请输 ...
- [loj3285]Circus
将奶牛的状态用序列$\{a_{1},a_{2},...,a_{m}\}$来描述,其中$a_{i}$表示第$i$头奶牛的位置(奶牛数量为$m$) 下面,先来考虑对于某个特定的$m$如何处理: 对于一条简 ...
- [atAGC050E]Three Traffic Lights
原题意可能略微有一些复杂,这里给出简述的题意-- 给定$g_{i}$和$r_{i}$(其中$1\le i\le 3$),求有多少个整数$t$满足: $0\le t< \prod_{i=1}^{3 ...
- [bzoj5295]染色
将这张图化简,不断删掉度为1的点(类似于拓扑排序),构成了一张由环组成的图考虑一个连通块中,设点数为n,边数为m(已经删掉了度为1的点),那么一共只有三种情况:1.一个环($n=m$),一定为YES2 ...
- [bzoj4651]网格
考虑将最上中最左的跳蚤孤立,容易发现他的上面和左面没有跳蚤,因此只需要将他的右边和下边替换掉就可以了答案为-1有两种情况:1.c>=n*m-1;2.c=n*m-2且这两只跳蚤相邻对于其他情况,将 ...
- java实现自动化发布平台核心代码
1.搭建jenkins环境 (1)jenkins官网下载jenkins.war包 (2)将该war包放入到tomcat的webapp的目录下(前提条件需要配置tomcat的环境,详情请自行百度) (3 ...
- Codeforces 724G - Xor-matic Number of the Graph(线性基)
Codeforces 题目传送门 & 洛谷题目传送门 一道还算不套路的线性基罢-- 首先由于图不连通,并且不同连通块之间的点显然不可能产生贡献,因此考虑对每个连通块单独计算贡献.按照 P415 ...
- AT4168 [ARC100C] Or Plus Max
从\(whk\)回来了. 考虑我们需要维护一个子集的信息. 对于二进制的子集信息维护有一个很经典的操作: 高维前缀和. AT4168 [ARC100C] Or Plus Max // Problem: ...