MFC下连接点编程

http://www.ms-news.net/f3295/mfc-event-fired-vbulletin-app-2526796.html

 

This question is similar to some others I've seen, but I've never seen a
good answer yet.

I'm adding Event support to an existing Automation .EXE that uses MFC (and
hence Dispatch interfaces).

I want to add a ConnectionPoint to the executable to fire an event when a
selection changes. The problem is, I'm not sure what magic is needed
(probably in the MIDL) to tie a VB application sink into the MFC connection
point. I've declared a variable within VB of the notification class type,
and implemented a handler but no go.

The details:

I've added the connection point within the existing code like (CTable is an
existing automation object):

static const IID IID_INotifySel =

{ 0xa9544120, 0x9965, 0x11d3, { 0xa0, 0xfd, 0x0, 0x60, 0x97, 0x3c, 0xf2,
CLSID_5S } };

BEGIN_CONNECTION_MAP(CTable, CCmdTarget)

CONNECTION_PART(CTable, IID_INotifySel, NotifySelCP)

END_CONNECTION_MAP ()

Where the declaration in the .h file is:

BEGIN_CONNECTION_PART(CTable, NotifySelCP)

CONNECTION_IID(IID_INotifySel)

END_CONNECTION_PART(NotifySelCP)

DECLARE_CONNECTION_MAP()

Within the CTable constructor, I have:

EnableConnections();

I'll spare you the INotifySel implementation, but it has one event called
"NewSel". Within my ODL file I've got the

following for INotifySel

[ uuid(A9544120-9965-11D3-A0FD-CLSID_5), hidden ]

dispinterface INotifySel

{

properties:

// NOTE - ClassWizard will maintain property information here.

// Use extreme caution when editing this section.

//{{AFX_ODL_PROP(XNotifySelCP)

//}}AFX_ODL_PROP

methods:

// NOTE - ClassWizard will maintain method information here.

// Use extreme caution when editing this section.

//{{AFX_ODL_METHOD(XNotifySelCP)

[id(1)] void NewSel(long rownum);

//}}AFX_ODL_METHOD

};

// Class information for NotifySel

[ uuid(A9544121-9965-11D4-A0FD-CLSID_5) ]

coclass NotifySel

{

[default, source] dispinterface INotifySel;

};



I added the CLSID for the INotifySel DISPINTERFACE to the Interface section
of the Registry.

Within VB, I've got

Dim MyNotify As App.NotifySel

Dim MyTab As Table

Set MyTab = App.GetTable

Private Sub Table_NewSel(Row As Long)

{

Do Something

}

The big question is how do I get the VB Sink to know about the Table
object's source ? Thanks very much.

 

========================================

 

in the ODL file, add a new outgoing interface like this:

// - Added following interface
[ uuid(62D28AE0-05F5-11d6-8871-000102C677B1) ]
dispinterface _HybridEvents
{
properties:
// Event interface has no properties

methods:
[id(1)] void OnTestEvent();
}

// Class information for CHybridDoc

[ uuid(73A4D503-05DA-11D6-8871-000102C677B1) ]
coclass Document
{
[default] dispinterface IHybrid;
// -- Added following line
[default, source] dispinterface _HybridEvents;
};

In the constructor for your document class add the following call:
EnableConnections();

Add this near the top of the document's .H file:

// {62D28AE0-05F5-11d6-8871-000102C677B1}
static const IID IID_IHybridEvents =
{ 0x62d28ae0, 0x5f5, 0x11d6, { 0x88, 0x71, 0x0, 0x1, 0x2, 0xc6, 0x77,
0xb1 } };

Add this in a protected section of the .H file (near the top of
protected):

BEGIN_CONNECTION_PART(CHybridDoc, TestEvent)
CONNECTION_IID(IID_IHybridEvents)
END_CONNECTION_PART(TestEvent)

void FireTestEvent();

Add this near the end of the document class in the .H file:
DECLARE_CONNECTION_MAP()

Add this just before your interface map in the .CPP file and add the
outgoing interface to the map too as follows:

BEGIN_CONNECTION_MAP(CHybridDoc, CDocument)

// - The following line will create the nested object m_xTestEvent in
the document class... add more as needed.

CONNECTION_PART(CHybridDoc, IID_IHybridEvents, TestEvent)
END_CONNECTION_MAP()

BEGIN_INTERFACE_MAP(CHybridDoc, CDocument)
INTERFACE_PART(CHybridDoc, IID_IHybrid, Dispatch)
INTERFACE_PART(CHybridDoc, IID_IConnectionPointContainer,
ConnPtContainer)
END_INTERFACE_MAP()

Finally, here is the code that fires the simple event:

void CHybridDoc::FireTestEvent()
{
// Retrieve the array of connected interfaces
int p;
const CPtrArray* pConnections = m_xTestEvent.GetConnections();

// Iterate through array, calling OnTestEvent on each
interface
for (p = 0; p < pConnections->GetSize(); p++) {
IDispatch * pDispatch =
(IDispatch*)pConnections->GetAt(p);
if (pDispatch != NULL) {
DISPPARAMS disp = { NULL, NULL, 0, 0 };
pDispatch->Invoke(0x1, IID_NULL,
LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
}
}
}

Here is the VB code I used to test this:

Option Explicit

Private WithEvents oHybrid As Hybrid.Document

Private Sub Command1_Click()
oHybrid.MyMethod
End Sub

Private Sub Form_Load()
Set oHybrid = New Hybrid.Document
End Sub

Private Sub Form_Unload(Cancel As Integer)
Set oHybrid = Nothing
End Sub

Private Sub oHybrid_OnTestEvent()
MsgBox "The event Fired!"
End Sub

You must set a reference to the .TLB and run the EXE once standalone
in order to register it.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值