本文使用 DraftDepot稿仓 https://github.com/xland/DraftDepot编辑并发布DraftDepot 可以把一篇文章一键发布到多个平台。建立 WinRT 消息分发队列应用启动时首先要创建 WinRT 消息分发队列DispatcherQueueOptions options{sizeof(DispatcherQueueOptions),DQTYPE_THREAD_CURRENT,DQTAT_COM_NONE};staticwinrt::Windows::System::DispatcherQueueController controller{nullptr};autohrCreateDispatcherQueueController(options,reinterpret_castABI::Windows::System::IDispatcherQueueController**(winrt::put_abi(controller)));if(FAILED(hr)){MessageBox(NULL,L无法创建DispatcherQueueController,L系统提示,MB_OK);ExitProcess(-1);}这段代码在当前线程创建 DispatcherQueueController变量名 controller用于建立 WinRT 消息分发队列并管理其生命周期。它是使用 Windows UI Composition 等异步 API 的前提为后续创建合成器Compositor及构建视觉树提供必要的消息循环基础。桥接原生窗口与 WinRT 合成器这个任务完成后就可以创建窗口了如下代码所示// winrt::Windows::UI::Composition::Compositor compositor{ nullptr };compositorComposition::Compositor();autohInsGetModuleHandle(nullptr);autoclsgetWinClsName(hIns);hwndCreateWindowEx(WS_EX_NOREDIRECTIONBITMAP|exStyle,cls.data(),title.data(),style,x,y,(float)w,(float)h,NULL,NULL,hIns,NULL);SetWindowLongPtr(hwnd,GWLP_USERDATA,reinterpret_castLONG_PTR(this));autointeropcompositor.asABI::Windows::UI::Composition::Desktop::ICompositorDesktopInterop();// winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget winTarget{ nullptr };autorreinterpret_castABI::Windows::UI::Composition::Desktop::IDesktopWindowTarget**(winrt::put_abi(winTarget));interop-CreateDesktopWindowTarget(hwnd,false,r);// winrt::Windows::UI::Composition::SpriteVisual visual{ nullptr };visualcompositor.CreateSpriteVisual();winTarget.Root(visual);这段代码在 DispatcherQueue 就绪后负责创建原生窗口并将其与 WinRT 合成器桥接创建合成器首先实例化 Compositor 对象它是整个 Windows UI Composition 视觉系统的工厂和入口。创建透明窗口通过 CreateWindowEx 创建窗口其中 WS_EX_NOREDIRECTIONBITMAP 标志至关重要它禁用了传统的 GDI/DWM 重定向表面使窗口成为仅由 DirectComposition 驱动的纯合成器窗口。这种窗口天生支持背景半透明效果。关联上下文使用 SetWindowLongPtr 将当前对象指针存入窗口的用户数据区以便在窗口过程WndProc中访问类实例。这部分代码不是本文的重点我没有给出。桥接 HWND 与合成器利用 ICompositorDesktopInterop 接口调用 CreateDesktopWindowTarget将原生窗口句柄注册为合成器的桌面渲染目标winTarget这一步打通了 Win32 窗口与 WinRT Composition 视觉树之间的通道使后续创建的 Visual 能够正确呈现到该窗口上。建立视觉树根节点创建一个 SpriteVisual 作为根视觉对象并将其设置为 winTarget 的 Root。此后所有子 Visual 都挂载在该根节点下最终通过合成器呈现到窗口上。绘制元素如果你想调整窗口的背景色可以使用如下方法修改 visual 的颜色winrt::Windows::UI::Color colorwinrt::Windows::UI::ColorHelper::FromArgb(a,r,g,b);visual.Brush(win-compositor.CreateColorBrush(color));如你所见颜色支持透明通道可以设置透明颜色。如果你想增加子元素可以用如下代码auto childVisualcompositor.CreateSpriteVisual();visual.Children().InsertAtTop(childVisual);//移除子元素的代码//visual.Children().Remove(borderVisual);如果你想设置元素的位置和尺寸可以用如下方式visual.Offset({x,y,0.0f});visual.Size({w,h});可以通过如下方式控制元素的显隐visual.IsVisible(false);visual.IsVisible(true);所有绘图操作都是直接完成的你不需要通过类似这样的方法刷新窗口InvalidateRect(hwnd,nullptr,FALSE);通过这种方式编译的程序可以单exe执行不需要分发一大堆dll单exe的体积小于1M如果大家感兴趣的话可以点赞、关注。点赞的人多的话后面我再介绍如何做布局、圆角、滚动条、渲染文本、画布、字体图标等一系列的知识。甚至可以介绍如何让这个技术与FaceBook的Yoga布局引擎整合开发GUI框架我做过验证了