【WinUI 3】实现自定义标题栏交互控件捕获输入

Windows App SDK支持同UWP类似的标题栏自定义功能,但当在标题栏中添加交互控件后却发现不能捕获鼠标输入。通过AppWindow相关接口,我们可以自定义标题栏拖曳区域从而解决此问题。
摘要由CSDN通过智能技术生成

问题背景描述

Windows为每个窗口提供默认标题栏,并允许自定义它以匹配应用的个性。 默认标题栏附带一些标准组件和核心功能,例如拖动和调整窗口大小。
WinUI 3 中的窗口功能是通过基于 Win32 HWND 模型的 Microsoft.UI.Xaml.Window 类。 Window 类包含 API,可用于将标准标题栏替换为自己的自定义内容。
WinUI 3 也是Windows 应用 SDK的一部分,因此 Windows 类和 AppWindow 类都可用于自定义标题栏。 可以将 XAML 窗口的窗口句柄传递给 AppWindow 对象,并将 AppWindow 功能与窗口 API 结合使用, (查看Windows 应用 SDK选项卡) 。 但是,仅Windows 11支持 AppWindow 的标题栏自定义。
(摘自:微软文档

众所周知,Windows App SDK支持同UWP类似的标题栏自定义功能,以支持在标题栏加入更多设计与功能。从UWP类比,我们甚至可以在标题栏加入交互式内容,使标题栏既美观又实用。

在这里插入图片描述
但,根据微软文档,WinUI 3并不建议添加交互元素,因为标题栏将默认接管鼠标输入:

传递给 SetTitleBar 的元素支持与标准标题栏相同的系统交互,包括拖动、双击以调整大小,并右键单击以显示窗口上下文菜单。 因此,所有指针输入 (鼠标、触摸、笔等) 由系统处理。 标题栏元素及其子元素不再识别它。 标题栏元素占用的矩形区域充当用于指针目的的标题栏,即使元素被另一个元素阻止,或者该元素是透明的。 但是,可以识别键盘输入,子元素可以接收键盘焦点。
这意味着,除了通过键盘输入和焦点,你不能与标题栏区域中的元素进行交互。 我们不建议这样做,因为它提供了可发现性和辅助功能问题。

致使加入交互控件后,当用户尝试与其交互,只会触发标准的标题栏事件——右键显示窗口命令,按住拖曳窗口。

问题分析

分析问题,发现其根本原因在于:整个标题栏包括自定义的内容控件,都会被定义为拖曳区域,从而被接管鼠标输入,致使无法交互。
(拖曳区域:在窗口标题栏中被定义的区域,根据微软文档,该区域的鼠标输入会被接管,实现与标准标题栏相同的系统交互。)

不过,根据文档在“Windows应用SDK”栏中给出的代码,我们得到了另一种思路——AppWindow.TitleBar中给出了方法:public void SetDragRectangles(RectInt32[] value);。根据原型,我们可以使用该方法自定义标题栏的若干个矩形拖曳区域,从而使交互控件被排除在拖曳区域外。

则如图,我们可以把标题栏分为三部分看:
标题栏分区图示
①包含Icon、Title与空白区域,无需鼠标输入;
②包含定义交互控件,需要鼠标输入;
③包含窗口按钮与空白区域,无需鼠标输入(窗口按钮区域须排除)。

目标很明确,我们要计算①、③区域对应的矩形位置,并将其定义为拖曳区域,使②成功接收鼠标输入。
算法非常简单:①的宽度即②的横坐标、高度即标题栏高度、坐标为(0, 0);③的横坐标即(②的横坐标 + ②的宽度)、③的高度即标题栏高度、③的宽度即(标题栏宽度 - ②的横坐标 - ②的宽度 - 按钮区域宽度)。此时,我们已经基本解决问题了,只需加一行代码将两个矩形区域定义为拖曳区域,然后注意窗口初始化时窗口尺寸改变时都需要重新计算并定义拖曳区域。

但,须注意到一个问题——Win32API无视了HiDpi下的屏幕缩放。即当200%缩放时,计算出来的区域尺寸仅是实际区域尺寸的四分之一。所以,我们仍需要编写方法适应HiDpi情境,计算屏幕缩放,并在区域高宽的计算中加入缩放系数。

解决方案

刷新标题栏拖曳区域方法,须注册到窗口尺寸改变时、窗口载入完成时:

		private void UpdateDragRects()
        {
   
            // 标题栏尺寸。
            var totalWidth = 
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值