如何将ActiveX实现从Qt迁移到wxWidgets并获取接口文档
问题:从Qt QAxWidget迁移至wxWidgets wxActiveXContainer连接ActiveX并获取接口文档
原本使用Qt的QAxWidget访问ActiveX控件,现需迁移至wxWidgets的wxActiveXContainer,但在VS2019 C++环境中参考示例后仍无法成功连接。核心需求是:用wxWidgets连接任意ActiveX并获取其接口文档。
Qt实现代码
#include "sc_samlight_client_ctrl_type_lib.h" QAxWidget actX(this); actX.setVisible(false); actX.setControl(QUuid(__uuidof(ScSamlightClientCtrl)).toString()); QString str = actX.generateDocumentation();
wxWidgets尝试代码
#include <wx/wx.h> #include "wx/msw/ole/activex.h" #include "wx/msw/ole/automtn.h" #include "sc_samlight_client_ctrl_type_lib.h" wxWindow* parent; // from caller... // 似乎能连接到对象... wxAutomationObject ao; ao.CreateInstance(wxS("SCAPS.ScSamlightClientCtrl")); // 这里无法工作...不知道第三个参数传什么,甚至不确定第二个参数是否正确... wxActiveXContainer* m_pAX; m_pAX = new wxActiveXContainer(parent, __uuidof(ScSamlightClientCtrl), NULL);
注:sc_samlight_client_ctrl_type_lib.h为待控制设备/程序提供的接口文件。
解决方案
1. 无界面自动化场景(对应Qt隐藏控件的需求)
如果不需要显示ActiveX控件,仅需调用其接口,使用wxAutomationObject即可,无需wxActiveXContainer。wx没有直接对应QtgenerateDocumentation()的方法,需通过OLE原生接口提取文档信息:
#include <wx/wx.h> #include "wx/msw/ole/automtn.h" #include "sc_samlight_client_ctrl_type_lib.h" #include <oleauto.h> void GetActiveXDocumentation(wxWindow* parent) { wxAutomationObject ao; // 两种创建方式:用ProgID字符串,或直接传CLSID bool created = ao.CreateInstance(wxS("SCAPS.ScSamlightClientCtrl")); // 或者用CLSID:created = ao.CreateInstance(__uuidof(ScSamlightClientCtrl)); if (!created) { wxMessageBox(wxT("创建ActiveX实例失败")); return; } IDispatch* disp = ao.GetDispatch(); if (!disp) { wxMessageBox(wxT("获取Dispatch接口失败")); return; } ITypeInfo* typeInfo = nullptr; HRESULT hr = disp->GetTypeInfo(0, LOCALE_USER_DEFAULT, &typeInfo); if (FAILED(hr) || !typeInfo) { wxMessageBox(wxT("获取类型信息失败")); disp->Release(); return; } // 提取类型文档 BSTR docBstr = nullptr; hr = typeInfo->GetDocumentation(MEMBERID_NIL, nullptr, &docBstr, nullptr, nullptr); if (SUCCEEDED(hr) && docBstr) { wxString docStr(docBstr, wxConvUTF16); // 这里可以处理文档内容,比如输出到日志或弹窗 wxMessageBox(docStr, wxT("ActiveX接口文档")); SysFreeString(docBstr); } // 释放资源 typeInfo->Release(); disp->Release(); }
2. 可视化ActiveX容器场景
如果需要显示ActiveX控件,正确初始化wxActiveXContainer的方式如下:
#include <wx/wx.h> #include "wx/msw/ole/activex.h" #include "wx/msw/ole/automtn.h" #include "sc_samlight_client_ctrl_type_lib.h" void CreateActiveXContainer(wxWindow* parent) { // 构造函数参数:父窗口、控件ID、ProgID/CLSID、位置、大小、样式 // 推荐用ProgID字符串,比直接传CLSID更直观 wxActiveXContainer* axContainer = new wxActiveXContainer( parent, wxID_ANY, wxS("SCAPS.ScSamlightClientCtrl"), wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL ); // 检查控件是否创建成功 if (!axContainer->CreateControl()) { wxMessageBox(wxT("创建ActiveX容器失败")); delete axContainer; return; } // 若需调用自动化接口,从容器中获取Dispatch对象 wxAutomationObject ao; ao.AttachDispatch(axContainer->GetDispatch()); // 后续提取文档的代码和无界面场景一致 IDispatch* disp = ao.GetDispatch(); // ...(省略提取文档的重复代码) }
关键说明
wxAutomationObject对应Qt QAxWidget的无界面自动化场景,无需创建可视化容器wxActiveXContainer用于需要显示ActiveX控件的场景,构造时第三个参数可直接传入ProgID字符串(如wxS("SCAPS.ScSamlightClientCtrl")),无需手动处理CLSID的转换- wxWidgets没有封装类似Qt
generateDocumentation()的方法,需通过OLE的ITypeInfo接口手动遍历提取接口文档,这部分逻辑和Qt内部实现原理一致
内容的提问来源于stack exchange,提问作者MHelene Lavoie
相关产品推荐
相关产品推荐

