gpt4 book ai didi

c++ - C++ Builder 中是否有 COM 事件处理的工作示例?

转载 作者:搜寻专家 更新时间:2023-10-31 02:18:22 28 4
gpt4 key购买 nike

我正在尝试将 C++ Builder 应用与 .NET 服务应用连接,并希望 .NET 服务应用能够将事件发送回 C++ Builder 应用。

是否有可以处理 COM 事件的 C++ Builder 应用程序的工作示例?

最佳答案

DocWiki 中存在关于处理 COM 事件的错误。搜集了一些各地的例子,放在一起供大家引用。

.NET 应用程序具有以下内容:

using System;
using System.IO;
using System.Runtime.InteropServices;

namespace IPractLib01
{
//
// GUID's to use for the COM objects.
[Guid("ACD03FE3-E506-4D87-BF8B-CC1F52E1FF0C")]
public interface IManagedInterface
{
int SendMessage(
string message
);
}


// Source interface with "event handlers" for COM objects to implement
[Guid("1ACAB463-55A3-4B3F-BE10-6252CDD93CE8")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] // use InterfaceIsDual to get callbacks by other than InvokeEvent()
public interface IIntelliPractEvents
{
[DispId(1)] void MessageReceived();

[DispId(2)] void MessageTextReceived(string message);
}

// Delegates for the events
public delegate void MessageReceivedEventHandler();
public delegate void MessageTextReceivedEventHandler(string message);

[Guid("1F4A7EDA-EE2A-4EA3-B213-A1911C5F766E")]
[ComSourceInterfaces(typeof(IIntelliPractEvents))]
public class IPractLib01Class : IManagedInterface
{
public event MessageReceivedEventHandler MessageReceived;
public event MessageTextReceivedEventHandler MessageTextReceived;

public int SendMessage(string message)
{
if (MessageReceived != null)
{
MessageReceived();
}
if (MessageTextReceived != null)
{
int len = message.Length;
string newMessage = "The message is '" + message + "', and the length of the message is " + len;
MessageTextReceived(newMessage);
}
return 0;
}
}
}

C++ Builder 应用程序包含:

#include "Unit1.h"
#include "IPractLib01_TLB.h" // created with Component/Import Component/Import a Type Library

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------

// to register the assembly dll:
// regasm IPractLib01.dll /tlb /verbose
// Need to run regasm as administrator, due to need to modify registry. If a regular user login was used to map drives, the mappings are not normally seen by the administrator login. Use "net use" in the administrator login to map them for the administrator

static TCOM_IPractLib01Class iplClass;

// The DocWiki does not take the address of the DIID_, but that does not compile
class MyEventSinkClass : public TEventDispatcher<MyEventSinkClass, &DIID_IIntelliPractEvents>
{
public:
MyEventSinkClass(IUnknown* sourceClass);
~MyEventSinkClass();
// declare the methods of DIID_IIntelliPractEvents here
void __fastcall MessageReceived();
void __fastcall MessageTextReceived(BSTR message/*[in]*/);
virtual HRESULT InvokeEvent(DISPID id, TVariant* params = 0);

IUnknown* theSource_;
};

static MyEventSinkClass* theEventSink = NULL;

static void ConnectNetHandler(void)
{
if (!iplClass)
iplClass = CoIPractLib01Class::Create();

if (!theEventSink) {
theEventSink = new MyEventSinkClass(iplClass);
}

}

// All of the events come through InvokeEvent -- change the interface to InterfaceIsDual if you want events through the other routines
HRESULT MyEventSinkClass::InvokeEvent(DISPID id, TVariant* params)
{
ShowMessage("got InvokeEvent with DISPID " + String(id));
// params would need better handling in a real app
if (params) {
String st = params->operator WideString();
ShowMessage("String is " + st);
}
return 0;
}

MyEventSinkClass::MyEventSinkClass(IUnknown* sourceClass)
{
theSource_ = sourceClass;
ConnectEvents(sourceClass);
}

MyEventSinkClass::~MyEventSinkClass()
{
DisconnectEvents(theSource_);
}


// These two routines do not get called with InterfaceIsDispatch; change that to InterfaceIsDual for these routines to be called.
void __fastcall MyEventSinkClass::MessageReceived()
{
ShowMessage("Message handler received");
}

void __fastcall MyEventSinkClass::MessageTextReceived(BSTR message/*[in]*/)
{
ShowMessage(String("Message handler received with message: ") + message);
}

void __fastcall TForm1::Button1Click(TObject *Sender)
{
ConnectNetHandler();

long result = -1;
TCOMIManagedInterface mif = iplClass;
if (!mif) {
ShowMessage("Unable to connect to interface");
return;
}

String theMessage = "the message";
mif->SendMessage(WideString(theMessage).c_bstr(), &result);

// check the IErrorInfo
// (Microsoft: Making a COM call that goes through a proxy-stub will clear any existing error object for the calling thread)

IErrorInfo *pperrinfo = NULL;
HRESULT hr = GetErrorInfo(0, &pperrinfo);
if (SUCCEEDED(hr) && pperrinfo) {

WideString wideStringMessage, wideStringDescription; // WideString is a wrapper for BSTR
pperrinfo->GetSource(&wideStringMessage);
pperrinfo->GetDescription(&wideStringDescription);
ShowMessage("Got error from " + String(wideStringMessage) + "; error description: " + String(wideStringDescription));
}

.NET代码创建的DLL必须在regasm/tlb注册生成类型库,才能让C++ Builder创建实现COM的单元。但是,一旦创建了应用程序,就不需要在部署它的系统上调用 regasm。

关于c++ - C++ Builder 中是否有 COM 事件处理的工作示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34563863/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com