当前位置: 首页 > news >正文

windows C++- C++/WinRT和COM组件(下)

 一个精简 Direct2D 应用程序的完整源代码列表

有关设置 Visual Studio 以进行 C++/WinRT 部署的信息,包括安装和使用 C++/WinRT Visual Studio 扩展 (VSIX) 和 NuGet 包(两者共同提供项目模板,并生成支持)的信息。

如果要生成和运行此源代码示例,请先安装(或更新)C++/WinRT Visual Studio 扩展 (VSIX) 的最新版本;请参阅上述说明。 然后,在 Visual Studio 中,新建 Core App (C++/WinRT)。 Direct2D 是项目的合理名称,但你可以指定任意名称。 面向 Windows SDK 的最新正式发布(非预览)版本。

/*
步骤 1: 编辑 pch.h
打开 pch.h,并在包含 windows.h 后立即添加 #include <unknwn.h>。 这是因为我们使用的是 winrt::get_unknown。 在使用 winrt::get_unknown 时,即使该头文件已包含在另一个头文件中,显式执行 #include <unknwn.h> 仍是不错的做法。如果省略此步骤,你将看到生成错误“'get_unknown':找不到标识符”。
*//*步骤 2: 编辑 App.cpp
打开 App.cpp,删除其整个内容,然后粘贴以下列表。以下代码会尽量使用 winrt::com_ptr::capture 函数。 WINRT_ASSERT 是宏定义,并且扩展到 _ASSERTE。
*/#include "pch.h"
#include <d2d1_1.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <winrt/Windows.Graphics.Display.h>using namespace winrt;using namespace Windows;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::UI;
using namespace Windows::UI::Core;
using namespace Windows::Graphics::Display;namespace
{winrt::com_ptr<ID2D1Factory1> CreateFactory(){D2D1_FACTORY_OPTIONS options{};#ifdef _DEBUGoptions.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endifwinrt::com_ptr<ID2D1Factory1> factory;winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,options,factory.put()));return factory;}HRESULT CreateDevice(D3D_DRIVER_TYPE const type, winrt::com_ptr<ID3D11Device>& device){WINRT_ASSERT(!device);return D3D11CreateDevice(nullptr,type,nullptr,D3D11_CREATE_DEVICE_BGRA_SUPPORT,nullptr, 0,D3D11_SDK_VERSION,device.put(),nullptr,nullptr);}winrt::com_ptr<ID3D11Device> CreateDevice(){winrt::com_ptr<ID3D11Device> device;HRESULT hr{ CreateDevice(D3D_DRIVER_TYPE_HARDWARE, device) };if (DXGI_ERROR_UNSUPPORTED == hr){hr = CreateDevice(D3D_DRIVER_TYPE_WARP, device);}winrt::check_hresult(hr);return device;}winrt::com_ptr<ID2D1DeviceContext> CreateRenderTarget(winrt::com_ptr<ID2D1Factory1> const& factory,winrt::com_ptr<ID3D11Device> const& device){WINRT_ASSERT(factory);WINRT_ASSERT(device);winrt::com_ptr<IDXGIDevice> const dxdevice{ device.as<IDXGIDevice>() };winrt::com_ptr<ID2D1Device> d2device;winrt::check_hresult(factory->CreateDevice(dxdevice.get(), d2device.put()));winrt::com_ptr<ID2D1DeviceContext> target;winrt::check_hresult(d2device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, target.put()));return target;}winrt::com_ptr<IDXGIFactory2> GetDxgiFactory(winrt::com_ptr<ID3D11Device> const& device){WINRT_ASSERT(device);winrt::com_ptr<IDXGIDevice> const dxdevice{ device.as<IDXGIDevice>() };winrt::com_ptr<IDXGIAdapter> adapter;winrt::check_hresult(dxdevice->GetAdapter(adapter.put()));winrt::com_ptr<IDXGIFactory2> factory;factory.capture(adapter, &IDXGIAdapter::GetParent);return factory;}void CreateDeviceSwapChainBitmap(winrt::com_ptr<IDXGISwapChain1> const& swapchain,winrt::com_ptr<ID2D1DeviceContext> const& target){WINRT_ASSERT(swapchain);WINRT_ASSERT(target);winrt::com_ptr<IDXGISurface> surface;surface.capture(swapchain, &IDXGISwapChain1::GetBuffer, 0);D2D1_BITMAP_PROPERTIES1 const props{ D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE)) };winrt::com_ptr<ID2D1Bitmap1> bitmap;winrt::check_hresult(target->CreateBitmapFromDxgiSurface(surface.get(),props,bitmap.put()));target->SetTarget(bitmap.get());}winrt::com_ptr<IDXGISwapChain1> CreateSwapChainForCoreWindow(winrt::com_ptr<ID3D11Device> const& device){WINRT_ASSERT(device);winrt::com_ptr<IDXGIFactory2> const factory{ GetDxgiFactory(device) };DXGI_SWAP_CHAIN_DESC1 props{};props.Format = DXGI_FORMAT_B8G8R8A8_UNORM;props.SampleDesc.Count = 1;props.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;props.BufferCount = 2;props.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;winrt::com_ptr<IDXGISwapChain1> swapChain;winrt::check_hresult(factory->CreateSwapChainForCoreWindow(device.get(),winrt::get_unknown(CoreWindow::GetForCurrentThread()),&props,nullptr, // all or nothingswapChain.put()));return swapChain;}constexpr D2D1_COLOR_F color_white{ 1.0f,  1.0f,  1.0f,  1.0f };constexpr D2D1_COLOR_F color_orange{ 0.92f,  0.38f,  0.208f,  1.0f };
}struct App : implements<App, IFrameworkViewSource, IFrameworkView>
{winrt::com_ptr<ID2D1Factory1> m_factory;winrt::com_ptr<ID2D1DeviceContext> m_target;winrt::com_ptr<IDXGISwapChain1> m_swapChain;winrt::com_ptr<ID2D1SolidColorBrush> m_brush;float m_dpi{};IFrameworkView CreateView(){return *this;}void Initialize(CoreApplicationView const&){}void Load(hstring const&){CoreWindow const window{ CoreWindow::GetForCurrentThread() };window.SizeChanged([&](auto&&...){if (m_target){ResizeSwapChainBitmap();Render();}});DisplayInformation const display{ DisplayInformation::GetForCurrentView() };m_dpi = display.LogicalDpi();display.DpiChanged([&](DisplayInformation const& display, IInspectable const&){if (m_target){m_dpi = display.LogicalDpi();m_target->SetDpi(m_dpi, m_dpi);CreateDeviceSizeResources();Render();}});m_factory = CreateFactory();CreateDeviceIndependentResources();}void Uninitialize(){}void Run(){CoreWindow const window{ CoreWindow::GetForCurrentThread() };window.Activate();Render();CoreDispatcher const dispatcher{ window.Dispatcher() };dispatcher.ProcessEvents(CoreProcessEventsOption::ProcessUntilQuit);}void SetWindow(CoreWindow const&) {}void Draw(){m_target->Clear(color_white);D2D1_SIZE_F const size{ m_target->GetSize() };D2D1_RECT_F const rect{ 100.0f, 100.0f, size.width - 100.0f, size.height - 100.0f };m_target->DrawRectangle(rect, m_brush.get(), 100.0f);char buffer[1024];(void)snprintf(buffer, sizeof(buffer), "Draw %.2f x %.2f @ %.2f\n", size.width, size.height, m_dpi);::OutputDebugStringA(buffer);}void Render(){if (!m_target){winrt::com_ptr<ID3D11Device> const device{ CreateDevice() };m_target = CreateRenderTarget(m_factory, device);m_swapChain = CreateSwapChainForCoreWindow(device);CreateDeviceSwapChainBitmap(m_swapChain, m_target);m_target->SetDpi(m_dpi, m_dpi);CreateDeviceResources();CreateDeviceSizeResources();}m_target->BeginDraw();Draw();m_target->EndDraw();HRESULT const hr{ m_swapChain->Present(1, 0) };if (S_OK != hr && DXGI_STATUS_OCCLUDED != hr){ReleaseDevice();}}void ReleaseDevice(){m_target = nullptr;m_swapChain = nullptr;ReleaseDeviceResources();}void ResizeSwapChainBitmap(){WINRT_ASSERT(m_target);WINRT_ASSERT(m_swapChain);m_target->SetTarget(nullptr);if (S_OK == m_swapChain->ResizeBuffers(0, // all buffers0, 0, // client areaDXGI_FORMAT_UNKNOWN, // preserve format0)) // flags{CreateDeviceSwapChainBitmap(m_swapChain, m_target);CreateDeviceSizeResources();}else{ReleaseDevice();}}void CreateDeviceIndependentResources(){}void CreateDeviceResources(){winrt::check_hresult(m_target->CreateSolidColorBrush(color_orange,D2D1::BrushProperties(0.8f),m_brush.put()));}void CreateDeviceSizeResources(){}void ReleaseDeviceResources(){m_brush = nullptr;}
};int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{CoreApplication::Run(winrt::make<App>());
}
 使用 BSTR 和 VARIANT 等 COM 类型

可以看到,C++/WinRT 支持实现和调用 COM 接口。 若要使用 BSTR 和 VARIANT 等 COM 类型,我们建议使用 Windows 实现库 (WIL) 提供的包装器,例如 wil::unique_bstr 和 wil::unique_variant(用于管理资源生存期)。

WIL 取代了活动模板库 (ATL) 等框架,以及 Visual C++ 编译器的 COM 支持。 我们建议覆盖你自己的包装器,或者按原始格式使用 BSTR 和 VARIANT 等 COM 类型(结合相应的 API)。

避免命名空间冲突

正如本主题中列出的代码所示,在 C++/WinRT 中,常见的做法是大量使用 using 指令。 但在某些情况下,这可能导致将冲突名称导入全局命名空间这种问题。 下面是一个示例。

C++/WinRT 包含名为 winrt::Windows::Foundation::IUnknown 的类型,而 COM 则定义名为 ::IUnknown 的类型。 那么,我们考虑一下,在使用 COM 标头的 C++/WinRT 项目中使用以下代码会出现什么情况:

using namespace winrt::Windows::Foundation;
...
void MyFunction(IUnknown*); // error C2872:  'IUnknown': ambiguous symbol

未限定的名称 IUnknown 在全局命名空间中发生冲突,因此会出现符号不明确编译器错误。 可以改将 C++/WinRT 版名称隔离到 winrt 命名空间中,如下所示。 

namespace winrt
{using namespace Windows::Foundation;
}
...
void MyFunctionA(IUnknown*); // Ok.
void MyFunctionB(winrt::IUnknown const&); // Ok.

或者,如果你希望利用 using namespace winrt,那么就可以那样做。 只需对全局版 IUnknown 进行限定即可,如下所示。

using namespace winrt;
namespace winrt
{using namespace Windows::Foundation;
}
...
void MyFunctionA(::IUnknown*); // Ok.
void MyFunctionB(winrt::IUnknown const&); // Ok.

自然,这适用于任何 C++/WinRT 命名空间。

namespace winrt
{using namespace Windows::Storage;using namespace Windows::System;
}

然后,你可以引用 winrt::Windows::Storage::StorageFile。例如,直接以 winrt::StorageFile 形式引用。 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python编写Word文档
  • css-定位
  • 【Linux】——进程概念(万字解读)
  • 【嵌入式linux开发】智能家居入门6:最新ONENET,物联网开放平台(QT、微信小程序、MQTT协议、ONENET云平台、旭日x3派)
  • Linux环境下运行介绍
  • 51单片机学习
  • 第八季完美童模全球总冠军·韩嘉潞 破浪扬帆写就传奇
  • INSTALLMENT MORTGAGE
  • Mac升级系统文件都丢了怎么办?Mac更新后资料找不到了怎么恢复
  • 【ARM 芯片 安全与攻击 6 -- ARM 中的 PAC 是什么?】
  • 2024年电赛H题全开源
  • 深度学习(YOLO、DETR) 十折交叉验证
  • 一个简单的Rtmp推流客户端(QT录音,OpenCV摄像,FFmpeg编码推流)
  • 模糊Smith智能控制方法的研究 及其单片机实现
  • 打造聊天流式回复效果:Spring Boot+WebSocket + JS实战
  • crontab执行失败的多种原因
  • interface和setter,getter
  • iOS小技巧之UIImagePickerController实现头像选择
  • Java Agent 学习笔记
  • mysql_config not found
  • SQL 难点解决:记录的引用
  • vue总结
  • Windows Containers 大冒险: 容器网络
  • 动态规划入门(以爬楼梯为例)
  • 对象管理器(defineProperty)学习笔记
  • 机器学习学习笔记一
  • 近期前端发展计划
  • 利用jquery编写加法运算验证码
  • 批量截取pdf文件
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 文本多行溢出显示...之最后一行不到行尾的解决
  • 小程序01:wepy框架整合iview webapp UI
  • 异步
  • 与 ConTeXt MkIV 官方文档的接驳
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • (BFS)hdoj2377-Bus Pass
  • (DFS + 剪枝)【洛谷P1731】 [NOI1999] 生日蛋糕
  • (Java入门)抽象类,接口,内部类
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (算法)硬币问题
  • (一)Dubbo快速入门、介绍、使用
  • (转)h264中avc和flv数据的解析
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .cfg\.dat\.mak(持续补充)
  • .gitignore文件—git忽略文件
  • .gitignore文件设置了忽略但不生效
  • .NET CORE 3.1 集成JWT鉴权和授权2
  • .NET 中创建支持集合初始化器的类型
  • .NetCore发布到IIS
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .Net面试题4
  • .NET中GET与SET的用法
  • /etc/shadow字段详解