如何正确使用Windows API中的抽象类与接口?
正确使用Windows COM接口(如IPropertyStorage)
你的代码存在两个核心问题:
PropertyStorage ips();是C++典型的"最令人头疼的解析"场景——这不是创建对象,而是声明了一个返回PropertyStorage类型的函数。- 更关键的是:Windows API中以
I开头的这类接口是COM接口,不需要你自己子类化并重写方法。COM接口的实现由系统或第三方组件提供,你只需要通过COM标准机制获取实例并调用方法即可。
核心使用流程
COM接口的使用遵循固定步骤:
- 初始化COM库:程序启动时调用
CoInitializeEx,退出时调用CoUninitialize。 - 通过专用API获取接口实例:比如从复合文件获取
IStorage,再通过QueryInterface或专用方法获取IPropertyStorage。 - 调用接口方法完成操作,最后调用
Release()释放接口(遵循COM引用计数规则)。
示例代码
#include <iostream> #include <propidl.h> #include <objidl.h> #include <propkey.h> int main(int argc, char* argv[]) { // 初始化COM库,指定Apartment线程模型 HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); if (FAILED(hr)) { std::cout << "COM初始化失败,错误码: " << hr << std::endl; return 1; } IStorage* pStorage = nullptr; // 创建或打开复合文件,获取IStorage接口实例 hr = StgCreateDocfile(L"test_prop_store", STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStorage); if (FAILED(hr)) { std::cout << "创建复合文件失败,错误码: " << hr << std::endl; CoUninitialize(); return 1; } IPropertyStorage* pPropStorage = nullptr; // 从IStorage创建并获取IPropertyStorage接口 hr = pStorage->CreatePropertySet(FMTID_UserDefinedProperties, nullptr, PROPSETFLAG_DEFAULT, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pPropStorage); if (FAILED(hr)) { std::cout << "创建属性集失败,错误码: " << hr << std::endl; pStorage->Release(); CoUninitialize(); return 1; } // 示例:写入属性 PROPVARIANT propVar; PropVariantInit(&propVar); propVar.vt = VT_LPWSTR; propVar.pwszVal = const_cast<LPWSTR>(L"测试内容"); hr = pPropStorage->WriteMultiple(1, &PKEY_Title, &propVar, PID_FIRST_USABLE); if (SUCCEEDED(hr)) { std::cout << "属性写入成功" << std::endl; } else { std::cout << "属性写入失败,错误码: " << hr << std::endl; } PropVariantClear(&propVar); // 按逆序释放接口:先释放子接口,再释放父接口 pPropStorage->Release(); pStorage->Release(); // 关闭COM库 CoUninitialize(); return 0; }
关键注意事项
- 引用计数规则:所有COM接口都实现了
AddRef()和Release(),每次获取接口时计数+1,调用Release()时计数-1,计数为0时对象自动销毁。必须确保所有获取的接口都被正确释放,避免内存泄漏。 - 不要自行子类化COM接口:这些接口的具体实现由系统提供,你不需要重写任何方法,直接调用接口暴露的方法即可。
- 错误处理:COM函数返回
HRESULT类型,务必用SUCCEEDED()或FAILED()宏判断执行结果,及时处理错误。
内容的提问来源于stack exchange,提问作者Eliazar
相关产品推荐
相关产品推荐

