【问题标题】:Implement IDispatch Interface for MFC automation为 MFC 自动化实现 IDispatch 接口
【发布时间】:2021-04-12 09:32:15
【问题描述】:

我有一个不支持 MFC 的 COM 项目,需要通过 MFC 接口与另一个 App 通信。 我不能直接在 MFC 接口中使用我的 COM 项目,因为它不是 MFC 项目。

一个解决方案是为 MFC 接口创建一个自动化接口,我可以将其用作我的 COM 项目可以与 MFC 项目通信的层。

据我了解,自动化应用程序将在不同的线程中运行。我的 COM 项目将从自动化接口调用方法来调用 MFC 接口。

Automation 项目及其 IDL 文件已提供给我,并为我提供了一个 Pure Dispinterface。

在将 IDispatch 接口的实现集成到我的 COM 项目之前,我决定创建一个新的 C++ 控制台项目,以便专注于简单地使用自动化接口。 使用 microsoft (https://docs.microsoft.com/en-us/previous-versions/windows/desktop/automat/implementing-the-idispatch-interface) 提供的文档,我实现了 IDispatch 接口,如下所示:

#include "TTAutomate.h"

HRESULT hresult;
DISPID dispid;
DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0 };
EXCEPINFO excepinfo;
UINT nArgErr;
ClassFromIDL* m_ClassFromIDL;
_DTTAutomateEvents* m_DTTAutomateEvents;
_DTTAutomate* m_DTTAutomate;


hresult = OleInitialize(NULL);

// OLE function CoCreateInstance starts application using GUID.
hresult = CoCreateInstance(CLSID_TTfromIDL, NULL, CLSCTX_INPROC_SERVER, DIID__DTTAutomateEvents, (LPVOID*)m_Automate);


// Call QueryInterface to see if object supports IDispatch.
hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL, (LPVOID*)pdisp);

// Retrieve the dispatch identifier for the SayHello method.
// Use defaults where possible.
OLECHAR* szMember = "SayHello";
DISPID dispid_Item;
hresult = pdisp->GetIDsOfNames(
    IID_NULL,
    &szFunction,
    1,
    LOCALE_USER_DEFAULT,
    &dispid_Item);

首先,实现与文档中的实现有点不同,因为有一行:

hresult = CoCreateInstance(CLSID_Hello, NULL, CLSCTX_SERVER, IID_IUnknown, (void **)&punk);

我会收到一个错误“amp undefined”。

使用上面的代码,我目前收到一条错误消息,指出 const char * 无法初始化 OLECHAR *。

在我的 COM 项目中,我有一行:

LPOLESTR szFunction = OLESTR("SayHello");

编译但我的测试项目中的同一行不起作用。

我是否错过了一些要添加的内容? 我没有创建正确的测试项目吗?

【问题讨论】:

  • 测试项目没问题。但是,如果您使用 ATL 和 CComPtr 或 IDispatchPtr 或 CComDispatchDriver 或 COleDispatchDriver 会更容易。搜索其中一些术语,尤其是最后两个。它们使驱动服务器对象变得更容易。
  • @JosephWillcoxson,你的意思是我需要一个 ATL 项目吗?因为这里我有一个简单的控制台应用程序。我正在研究您建议的其他条款。
  • 所以我对该代码进行了一些修复,现在它可以编译了,但是在运行时我在调用CoCreateInstance 时得到了一个REGDB_E_CLASSNOTREG Class not registered。我所做的修复是:IDispatch* m_Automatehresult = CoCreateInstance(CLSID_TTfromIDL, NULL, CLSCTX_INPROC_SERVER, DIID__DTTAutomateEvents, (void**)&m_Automate);; hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL, (void**)&pdisp); 并将函数名称声明为 wchar_t*
  • 为什么不简单地与 Windows 消息进行通信?它比自动化更容易
  • @Landstalker,自动化代码是提供给我的,所以我并没有真正选择使用自动化。然而我是 Windows 编程的新手,什么是 Windows 消息?有什么有趣的链接可以分享吗?

标签: c++ automation mfc com idispatch


【解决方案1】:

所以我找到了一种方法来修复我的代码,以便它可以编译,但不确定它是否是一个正确的解决方案:

#include "TTAutomate.h"
#include <string>

HRESULT hresult;
DISPID dispid;
DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0 };
EXCEPINFO excepinfo;
UINT nArgErr;
ClassFromIDL* m_ClassFromIDL;
IDispatch* m_Automate; // fixed


hresult = OleInitialize(NULL);

// OLE function CoCreateInstance starts application using GUID.
hresult = CoCreateInstance(CLSID_TTfromIDL, NULL, CLSCTX_INPROC_SERVER, DIID__DTTAutomateEvents, (void**)&m_Automate); // fixed


// Call QueryInterface to see if object supports IDispatch.
hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL, (void**)&pdisp); // fixed

// Retrieve the dispatch identifier for the SayHello method.
// Use defaults where possible.

// here I create a wchar_t* variable as LPOESTR is casted from that.
std::string functionName = "SayHello";
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, functionName.c_str(), -1, NULL, 0);
wchar_t* wstr = new wchar_t[wchars_num];

LPOLESTR szMember = wstr;
DISPID dispid_Item;
hresult = pdisp->GetIDsOfNames(
IID_NULL,
&szFunction,
1,
LOCALE_USER_DEFAULT,
&dispid_Item);

我现在得到一个 E_NOINTERFACE 不支持这样的接口,但它可能与这个主题无关。

【讨论】:

    猜你喜欢
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 2011-09-29
    • 2011-05-05
    • 2011-07-03
    • 2016-11-30
    • 1970-01-01
    相关资源
    最近更新 更多