[WinUI3]如何设置亚克力窗口?-创新互联

接触WinUI3是我第一次知道原来微软有这么多前端技术:Winforms、WPF、UWP、MAUI、WinUI3、Win32 API、WinRT。前五个都是Visual Studio提供的模板,Win32是Windows底层的C/C++API接口,WinRT是Windows提供的一种跨平台运行时API接口。
WinUI3是新推出的一些列的Windows UI平台组件(根据我的理解也就是一堆UI组件了,基本上啥高级封装都没有),功能实现基本上是靠Win32和WinRT实现。

成都创新互联公司专注于企业营销型网站建设、网站重做改版、乐东黎族网站定制设计、自适应品牌网站建设、html5购物商城网站建设、集团公司官网建设、成都外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为乐东黎族等各大城市提供网站开发制作服务。

实现步骤可以参照:Example: Use Mica in a Windows AppSDK/WinUI 3 app
或者WinUI-Gallery

踩坑过程记录

首先,必须明确WinUI3是通过WinRT中的DesktopAcrylicController类提供了为COM组件设置亚克力笔刷的方法,所以先创建对象,然后指定COM组件

DesktopAcrylicController m_acrylicController = new();
m_acrylicController.AddSystemBackdropTarget(m_Window.As());

非常理论,非常正确。运行会抛出一个不知所云的C++异常
在这里插入图片描述
然后如果仔细查看AddSystemBackdropTarget的文档,会发现该方法必须要通过线程调度队列(DispatcherQueue)去调用
这里有个坑,开始我以为这个DispatcherQueue是指Window的队列(Microsoft.UI.Dispatching.DispatcherQueue),但实际上指的是由WinRT创建的DispatcherQueue(Windows.System.DispatcherQueue)
详细可以看我在Stackoverflow上的提问:How to set the acrylic style to window?
对于这一部分,需要通过CreateDispatcherQueueController()函数来实现。参考MS的示例,可以通过创建WindowsSystemDispatcherQueueHelper去实现
首先引入函数,根据官方文档对CreateDispatcherQueueController和DispatcherQueueOptions的描述,需要对参数中的结构体DispatcherQueueOptions做映射

struct DispatcherQueueOptions
{internal int dwSize;
	internal int threadType;
	internal int apartmentType;
}

之后引入函数

[DllImport("CoreMessaging.dll")]
private static extern int CreateDispatcherQueueController(
	[In] DispatcherQueueOptions options,
	[In, out, MarshalAs(UnmanagedType.IUnknow)] ref object dispatcherQueueController // MarshalAs指示应该将这个object参数封装成IUnknown类型传递给C++函数
)

最后检查并确保调度线程控制器存在

object m_dispatcherQueueController = null;

public void EnsureWindowsSystemDispatcherQueueController()
{if (DispatcherQueue.GetForCurrentThread() != null)
    {return;
    }

    if (m_dispatcherQueueController == null)
    {DispatcherQueueOptions options;
        options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
        options.threadType = 2;
        options.apartmentType = 2;
        CreateDispatcherQueueController(options, ref m_dispatcherQueueController);
    }
}

之后在调用AddSystemBackdropTarget()函数前先确保WinRT显示层的调度线程存在再运行

WindowsSystemDispatcherQueueHelper m_wsdqHelper = new();
m_wsdqHelper.EnsureWindowsSystemDispatcherQueueController();

DesktopAcrylicController m_backdropController = new();
m_backdropController.AddSystemBackdropTarget(m_window.As());

运行发现程序没有报错并成功启动,但是并没有实现亚克力的效果。通过看MS的示例我发现我没有为acrylicController设置SystemBackdropConfiguration。所以实例化一个SystemBackdropConfiguration对象然后为acrylicController配置上就解决了。
ps:看了一下SystemBackdropConfiguration的源码,不太理解这个函数在实例化时注册和初始化了一些什么东西。
最终成功代码如下:

WindowsSystemDispatcherQueueHelper m_wsdqHelper = new();
m_wsdqHelper.EnsureWindowsSystemDispatcherQueueController();

SystemBackdropConfiguration m_configurationSource = new();
// m_configurationSource.IsInputActive = true;
DesktopAcrylicController m_backdropController = new();
m_backdropController.AddSystemBackdropTarget(m_window.As());
m_backdropController.SetSystemBackdropConfiguration(m_configurationSource);

但是他有个问题:窗口在失去焦点时不会更新背景,我看WinUI-Gallery的处理办法好像是让失去焦点的窗口暂时不启用亚克力效果,不知道有没有更好的解决办法,欢迎分享。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧

新闻标题:[WinUI3]如何设置亚克力窗口?-创新互联
本文来源:https://www.cdcxhl.com/article2/ccshoc.html

成都网站建设公司_创新互联,为您提供静态网站网站建设外贸建站响应式网站手机网站建设网站收录

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

成都网站建设