我的目标
希望能够熟悉 WinUI 3 窗口的基本使用方式,了解可能出现的问题 。
WinUI 3 支持三种窗口模式,分别为:常规窗口模式、画中画模式、全屏模式。
窗口模式:常规
即我们最常见的普通窗口。
支持:显示最大化按钮、最小化按钮、关闭按钮、标题栏、手动调整窗口尺寸、代码调整窗口尺寸、模态对话框、条件性支持窗口透明。
=> 窗口设置:
var overlappedPresenter = Microsoft.UI.Windowing.OverlappedPresenter.Create();
AppWindow.SetPresenter(overlappedPresenter);
=> 设置最大化:
if (AppWindow.Presenter is OverlappedPresenter presenter)
{
presenter.IsMaximizable = true;
presenter.Maximize();
}
=> 设置最小化:
presenter.IsMinimizable = true;
presenter.Minimize();
=> 设置标题栏:
presenter.SetBorderAndTitleBar(true, true);
Title = "测试标题";
=> 调整窗口尺寸:
AppWindow.Resize(new Windows.Graphics.SizeInt32(320, 240));
=> 模态对话框:
var presenter = Microsoft.UI.Windowing.OverlappedPresenter.CreateForDialog();
var win = new Window();
var mainWindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
var dialogHandle = WinRT.Interop.WindowNative.GetWindowHandle(win);
SetWindowLongPtr(dialogHandle, GWLP_HWNDPARENT, mainWindowHandle);
win.AppWindow.SetPresenter(presenter);
presenter.IsModal = true;
win.Activate();
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
=> 窗口透明:
//MainWindow2 是一个透明窗口,具体参见下文
new MainWindow2().AppWindow.Show();
窗口模式:画中画
这与 winform 和 wpf 的 TopMost 比较像,一直显示在上层。
支持:代码调整窗口尺寸、和隐藏标题栏
不支持:显示最大化按钮、最小化按钮、隐藏关闭按钮(可能需要其他比较复杂的方式隐藏)、 模态对话框、窗口透明。
=> 窗口设置:
var compactPresenter = Microsoft.UI.Windowing.CompactOverlayPresenter.Create();
AppWindow.SetPresenter(compactPresenter);
=> 隐藏标题栏:
ExtendsContentIntoTitleBar = true;
窗口模式:全屏
即铺满整个窗口。
支持:模态对话框、条件性支持窗口透明
不支持:显示标题栏、最大化按钮、最小化按钮、关闭按钮、调整窗口尺寸
=> 窗口设置:
var fullScreenPresenter = Microsoft.UI.Windowing.FullScreenPresenter.Create();
AppWindow.SetPresenter(fullScreenPresenter);
=> 窗口透明:
//MainWindow2 是一个透明窗口,具体参见下文
new MainWindow2().AppWindow.Show();
=> 模态对话框(变相支持):
var presenter = Microsoft.UI.Windowing.FullScreenPresenter.Create();
var win = new Window();
var mainWindowHandle = WinRT.Interop.WindowNative.GetWindowHandle(this);
var dialogHandle = WinRT.Interop.WindowNative.GetWindowHandle(win);
SetWindowLongPtr(dialogHandle, GWLP_HWNDPARENT, mainWindowHandle);
win.AppWindow.SetPresenter(presenter);
win.Activate();
它本身就会占据整个屏幕,不支持真正的模态对话框。所以作为 “变相支持”,效果是类似的。
限制性支持:窗口透明
WinUI 3 默认不支持真正的窗口透明度控制,无法通过简单的属性设置实现窗口透明,
因此找到了一个第三方的实现方式,它的实现控制代码有一万多行: https://github.com/castorix/WinUI3_SwapChainPanel_Layered
它的主要原理是:
SetLayeredWindowAttributes控制透明度 + UpdateLayeredWindow 更新窗口内容 + Direct2D 和 DXGI 硬件加速渲染 + SwapChain双缓冲渲染。
但是,这个透明的效果是有局限性的,仅在指定系统版本有效:
比对效果如下:
在项目属性中,设置为:
因此在使用透明窗口相关功能的时候,一定要非常的谨慎,很有可能开发出来对系统的兼容性非常差。
整体感受
WinUI 3 对窗口的类型进行了更细的分类,与 winform, WPF 相比,功能上差异并不是很大,但是使用起来比它们要麻烦好多;而且,对透明的支持受限制非常多。
因此,如果进行传统的桌面程序开发,我可能仍然会考虑 winform 和 wpf。
期待后续的探索,从这些独特设计的窗口分类中,希望能够看到让我惊艳的特性和性能,才能不负我如此艰辛