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

windows C++-通过 C++/WinRT 创作 COM 组件(四)

如何测试示例应用程序

生成应用程序,然后至少以管理员身份运行一次,以便使注册(和其他设置)代码运行。 执行此操作的一种方法是以管理员身份运行 Visual Studio,然后从 Visual Studio 运行应用。 在任务栏中右键单击 Visual Studio 以显示跳转列表,在跳转列表右键单击 Visual Studio,然后单击“以管理员身份运行”。 同意提示,然后打开项目。 运行应用程序时,会显示一条消息,指出是否在以管理员身份运行应用程序。 如果不是,则注册和其他设置不会运行。 该注册和其他设置必须至少运行一次,才能使应用程序正常工作。

无论是否在以管理员身份运行应用程序,按“T”使 toast 显示。 然后可以直接从弹出的 toast 通知或是从操作中心单击“回调 ToastAndCallback”按钮,这样会启动应用程序,实例化组件类并执行 INotificationActivationCallback::Activate 方法。

进程内 COM 服务器

上面的 ToastAndCallback 示例应用可充当本地(或进程外)COM 服务器。 这由 LocalServer32 Windows 注册表项进行指示,该项用于注册其组件类的 CLSID。 本地 COM 服务器在可执行二进制文件 (.exe) 中承载其组件类。

或者(并且可能更有可能),可以选择在动态链接库 (.dll) 中承载组件类。 采用 DLL 形式的 COM 服务器称为进程内 COM 服务器,由使用 InprocServer32 Windows 注册表项注册 CLSID 进行指示。

创建动态链接库 (DLL) 项目

可以通过在 Microsoft Visual Studio 中创建新项目,来开始创建进程内 COM 服务器的任务。 创建“Visual C++”>“Windows 桌面”>“动态链接库(DLL)”项目。

若要向新项目添加 C++/WinRT 支持,请执行修改 Windows 桌面应用程序项目以添加 C++/WinRT 支持中所述的步骤。

实现组件类、类工厂和进程内服务器导出

打开 dllmain.cpp,并向其添加如下所示的代码清单。

如果已具有一个实现 C++WinRT Windows 运行时类的 DLL,则表示已具有如下所示的 DllCanUnloadNow 函数。 如果要将组件类添加到该 DLL,则可以添加 DllGetClassObject 函数。

如果没有要保持与之兼容的现有 Windows 运行时 C++ 模板库 (WRL) 代码,则可以从显示的代码中删除 WRL 部分。

// dllmain.cppstruct MyCoclass : winrt::implements<MyCoclass, IPersist>
{HRESULT STDMETHODCALLTYPE GetClassID(CLSID* id) noexcept override{*id = IID_IPersist; // Doesn't matter what we return, for this example.return S_OK;}
};struct __declspec(uuid("85d6672d-0606-4389-a50a-356ce7bded09"))MyCoclassFactory : winrt::implements<MyCoclassFactory, IClassFactory>
{HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) noexcept override{try{return winrt::make<MyCoclass>()->QueryInterface(riid, ppvObject);}catch (...){return winrt::to_hresult();}}HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) noexcept override{// ...return S_OK;}// ...
};HRESULT __stdcall DllCanUnloadNow()
{
#ifdef _WRL_MODULE_H_if (!::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().Terminate()){return S_FALSE;}
#endifif (winrt::get_module_lock()){return S_FALSE;}winrt::clear_factory_cache();return S_OK;
}HRESULT __stdcall DllGetClassObject(GUID const& clsid, GUID const& iid, void** result)
{try{*result = nullptr;if (clsid == __uuidof(MyCoclassFactory)){return winrt::make<MyCoclassFactory>()->QueryInterface(iid, result);}#ifdef _WRL_MODULE_H_return ::Microsoft::WRL::Module<::Microsoft::WRL::InProc>::GetModule().GetClassObject(clsid, iid, result);
#elsereturn winrt::hresult_class_not_available().to_abi();
#endif}catch (...){return winrt::to_hresult();}
}
对弱引用的支持

如果类型实现 IInspectable或任何派生自 IInspectable 的接口,则 C++/WinRT,具体而言,winrt::implements 基结构模板,会实现 IWeakReferenceSource。

这是因为 IWeakReferenceSource 和 IWeakReference 旨在用于 Windows 运行时类型。 因此,只需通过向实现添加 winrt::Windows::Foundation::IInspectable(或派生自 IInspectable 的接口),即可为组件类启用弱引用支持。

实现从另一个接口派生的 COM 接口

接口派生是经典 COM 的一项功能(Windows 运行时中刻意不提供此功能)。 下例展示了接口派生的显示效果。 

IFileSystemBindData2 : public IFileSystemBindData { /* ... */  };

如果要编写需要实现的类,例如 IFileSystemBindData 和 IFileSystemBindData2,则表达的第一步是声明仅实现派生接口,如下所示。 

// pch.h
#pragma once
#include <Shobjidl.h>
...// main.cpp
...
struct MyFileSystemBindData :implements<MyFileSystemBindData,IFileSystemBindData2>
{// IFileSystemBindDataIFACEMETHOD(SetFindData)(const WIN32_FIND_DATAW* pfd) override { /* ... */ return S_OK; };IFACEMETHOD(GetFindData)(WIN32_FIND_DATAW* pfd) override { /* ... */ return S_OK; };// IFileSystemBindData2IFACEMETHOD(SetFileID)(LARGE_INTEGER liFileID) override { /* ... */ return S_OK; };IFACEMETHOD(GetFileID)(LARGE_INTEGER* pliFileID) override { /* ... */ return S_OK; };IFACEMETHOD(SetJunctionCLSID)(REFCLSID clsid) override { /* ... */ return S_OK; };IFACEMETHOD(GetJunctionCLSID)(CLSID* pclsid) override { /* ... */ return S_OK; };
};
...
int main()
...

下一步是在针对 MyFileSystemBindData 示例对 IID_IFileSystemBindData(基接口)直接或间接调用 QueryInterface 时,确保 QueryInterface 成功 。 为此,需要为 winrt::is_guid_of 函数模板提供专用化。

winrt::is_guid_of 是可变参数,因此可以为其提供接口列表。 下面介绍如何提供专用化,以使对 IFileSystemBindData2 的检查还包括对 IFileSystemBindData 的测试 。

// pch.h
...
namespace winrt
{template<>inline bool is_guid_of<IFileSystemBindData2>(guid const& id) noexcept{return is_guid_of<IFileSystemBindData2, IFileSystemBindData>(id);}
}// main.cpp
...
int main()
{...auto mfsbd{ winrt::make<MyFileSystemBindData>() };auto a{ mfsbd.as<IFileSystemBindData2>() }; // Would succeed even without the **is_guid_of** specialization.auto b{ mfsbd.as<IFileSystemBindData>() }; // Needs the **is_guid_of** specialization in order to succeed.
}

winrt::is_guid_of 的专用化在项目的所有文件中必须相同,并且在 winrt::implements 或 winrt::delegate 模板使用接口时可见 。 通常会将该内容放在一个通用头文件中。 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【二分查找】--- 进阶题目赏析
  • C#MVC返回DataTable到前端展示。
  • Ubuntu+QT编译QTXlsx库
  • 机器学习:knn算法实现图像识别
  • Spring Cloud全解析:配置中心之springCloudConfig配置存储
  • Linux系统-系统信息网络目录文件的相关命令
  • 微服务基础知识
  • 8.19Qt作业
  • C语言内存操作函数
  • 力扣第 411 场周赛题解
  • 西安旅游系统--论文pf
  • 每日快讯 | 京东健康:2024年上半年营收283亿元
  • vue+fastadmin跨域请求问题
  • 【Docker】宿主机上装个ES和使用docker装个ES有啥不一样
  • 【gitlab】gitlab-ce:17.3.0-ce.0 之2:配置
  • 【css3】浏览器内核及其兼容性
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 【译】理解JavaScript:new 关键字
  • Linux gpio口使用方法
  • Odoo domain写法及运用
  • React 快速上手 - 07 前端路由 react-router
  • spring-boot List转Page
  • storm drpc实例
  • vue 配置sass、scss全局变量
  • 创建一个Struts2项目maven 方式
  • 从输入URL到页面加载发生了什么
  • 回流、重绘及其优化
  • 技术攻略】php设计模式(一):简介及创建型模式
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 人脸识别最新开发经验demo
  • 如何编写一个可升级的智能合约
  • 小程序开发中的那些坑
  • 一道闭包题引发的思考
  • 一些css基础学习笔记
  • ​zookeeper集群配置与启动
  • #### go map 底层结构 ####
  • #Z0458. 树的中心2
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • (4)STL算法之比较
  • (day18) leetcode 204.计数质数
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (Matalb回归预测)PSO-BP粒子群算法优化BP神经网络的多维回归预测
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (六)Hibernate的二级缓存
  • (三分钟)速览传统边缘检测算子
  • (学习日记)2024.01.19
  • (转)http协议
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • (最简单,详细,直接上手)uniapp/vue中英文多语言切换
  • .desktop 桌面快捷_Linux桌面环境那么多,这几款优秀的任你选
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .NET 4.0网络开发入门之旅-- 我在“网” 中央(下)
  • .NET 中使用 Mutex 进行跨越进程边界的同步