用Win32的方式解读WIN10 UWP应用

1. UWP简介

UWP即Windows 10中的Universal Windows Platform简称。即Windows通用应用平台,在Windows 10 Mobile/Surface(Windows平板电脑)/PC/Xbox/HoloLens等平台上运行,uwp不同于传统pc上的exe应用,也跟只适用于手机端的app有本质区别。它并不是为某一个终端而设计,而是可以在所有Windows10设备上运行。

UWP应用可以在所有Windows10设备上运行的本质在于打包时对多个平台进行适配。原生UWP在Windows10电脑客户端中是看不到.exe的痕迹的。这不代表它不是以常规窗口(即WIN32窗口)创建、运作、销毁的机理运行。UWP依旧具有很多特殊的特质,比如使用DirectX进行GPU加速等。
在UWP中,可以通过 CoreApplicationView 的实例,然后设置 TitleBar 的各种属性来扩展或自定义标题栏。关键代码如下:

// lang = visual csharp
//扩展标题栏
var applicationView = CoreApplication.GetCurrentView();
applicationView.TitleBar.ExtendViewIntoTitleBar = true;
//自定义标题栏
var titleBar = ApplicationView.GetForCurrentView().TitleBar;
titleBar.BackgroundColor = Colors.Khaki;
titleBar.ButtonBackgroundColor = Colors.Transparent;
  • 更多关于uwp扩展或自定义标题栏可以访问此网站官网,来了解该主题的内容。

在Win32中,扩展或自定义标题栏不是一个简单的事情,它将涉及一系列关于Non-client区和client区的设置问题,有些时候需要引入Dwmapi来辅助完成。处理不恰当时,可能出现一些各种奇怪的问题,例如不响应WM_NCPAINT时的边框圆角问题;去除WS_CAPTION后,无法响应win键+上下左右的快捷键等。
UWP却可以在能自定义标题栏得情况下,同时拥有系统配置给普通窗口的处理。下面就对uwp的结构,以win32的方式进行初步解读。

2. 以Win32方式解读UWP应用窗口

通过使用spy++,对windows内置的“设置”进行查看。
可以发现,UWP应用主要包含五个窗口句柄,分别是名为ApplicationFrameWindow的主窗口,两个名为ApplicationFrameTitleBarWindow的childwindow,一个Windows.UI.Core.CoreWindow子窗口和ApplicationFrameInputSinkWindow子窗口。
具体信息如下所示:

注册时的窗口类名风格扩展风格窗口矩形客户区矩形
ApplicationFrameWindowappFrameWndStyleappFrameWndStyleEx[[51,11],[1267,952]][[8,0],[1208,933]]
ApplicationFrameTitleBarWindowappFrameTitleBarWndStylechildWndStyleEx[[59,12],[107,44]][[0,0],[48,32]]
ApplicationFrameTitleBarWindowappFrameTitleBarWndStylechildWndStyleEx[[1071,12],[1259,44]][[0,0],[188,32]]
Windows.UI.Core.CoreWindowcoreWndStylechildWndStyleEx[[59,12],[1259,944]][[0,0],[1200,932]]
ApplicationFrameInputSinkWindowappFrameInputSinkWndStylechildWndStyleEx[[59,44],[1259,944]][[0,0],[1200,900]]

表中:

// lang = visual cpp
// wndStyle
auto appFrameWndStyle = WS_CAPTION | WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | 
                        WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
auto appFrameTitleBarWndStyle = WS_CHILDWINDOW | WS_VISIBLE | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
auto coreWndStyle = WS_CHILDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS;
auto appFrameInputSinkWndStyle = WS_CHILDWINDOW | WS_VISIBLE;
// wndStyleEx
auto appFrameWndStyleEx = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | 
                          WS_EX_WINDOWEDGE | WS_EX_NOREDIRECTIONBITMAP;
auto childWndStyleEx = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | 
                       WS_EX_LAYERED | WS_EX_NOREDIRECTIONBITMAP;

下面给出窗口矩形示意:
UWP窗口矩形 1920×1080

  • 图中可以看出,主窗口的win32标题栏大小为0,但依旧保留左右和下方的8px非客户区,猜测可能重写了WM_NCCALCSIZE 消息回调,将原有标题栏设为0;由于上方非客户区消失,因此还需重写部分的WM_NCHITTEST 消息回调(可能不是在主窗口中实现,而在CoreWindow中实现)。由于其保留近乎完整的非客户区,所以可以响应窗口吸附和win键操作等。
  • 两个子窗口ApplicationFrameTitleBarWindow分别分布于窗口两侧。表内第一个TitleBarWindow是返回键区,(不包含文字“设置”的区域),这个子窗口有时窗口矩形为0(即回到主页面时,按钮消失);第二个则是windows窗口功能按钮区,呈现的按钮区大于三个按钮宽度之和,应该是为了给其他按钮(比如问号/帮助按钮)留的位置。
  • 子窗口Windows.UI.Core.CoreWindow是负责整个窗口人机交互逻辑,也就是C#中的CoreWindow实例;由于对UWP了解不深,猜测亚克力效果可能就是由CoreWindow向系统(或显卡)获取桌面显存,然后使用D2D 在GPU中再次加工合成的。对比InputSinkWindow,CoreWindow比其要高32px,这也就是模拟标题栏的高度。由于UWP标题栏是自己绘制的,所以很容易实现神奇的特性,比如 Microsoft To Do 里同步to do list的进度条动画就是在“标题栏”上方。
  • InputSinkWindow 暂时不太了解其存在的缘由,名字翻译为 应用程序框架输入接收器窗口 。它存在的意义可能和UWP窗口调度CoreDispatcher有关。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值