珞珈山水BBS电脑网络程序人生 → 单文区文章阅读

单文区文章阅读 [返回]
发信人: fgynew (fgynew), 信区: Programm
标  题: Com Event Step By Step
发信站: BBS 珞珈山水站 (Fri Sep 22 10:15:18 2006)


The com event is similar with the delegate event in C#. But it’s more complic
ated and more incomprehensible. After I learnt many theories about it and wrot
e some projects I found that only following several steps can make it work. No
w I wrote it down and you can follow my step to learn com event. If any questi
ons or any mistakes, please contact me.

First Step ----- Build up the com event source:
1 Create an ATL project. I named it “StepByStep”. Now open the file StepBySt
ep.idl in studio.net and you will found the file is like this:
import "oaidl.idl";
import "ocidl.idl";
[
    uuid(EBA72123-3D41-473C-9A9C-216D73809AA8),
    version(1.0),
    helpstring("StepByStep 1.0 Type Library")
]
library StepByStepLib
{
    importlib("stdole2.tlb");
};
Now my com library is SteyByStepLib and it has no interfaces nor coclasses.

2 Add an ATL simple class “SourceEvent” to this project and in the “Option”
 of the “ATL Simple Object Wizard” please choose “Connection points”. Clic
k “Finish” of this dialog and several new files will be added to you project
. Now open the file StepByStep.idl and it may like this:
import "oaidl.idl";
import "ocidl.idl";
[
    object,
    uuid(FE8B032E-E923-4415-A29C-3ECFA0930D59),
    dual,
    nonextensible,
    helpstring("ISourceEvent Interface"),
    pointer_default(unique)
]
interface ISourceEvent : IDispatch{
};
[
    uuid(EBA72123-3D41-473C-9A9C-216D73809AA8),
    version(1.0),
    helpstring("StepByStep 1.0 Type Library")
]
library StepByStepLib
{
    importlib("stdole2.tlb");
    [
        uuid(41035159-DDE1-4C27-BD15-936628E79763),
        helpstring("_ISourceEventEvents Interface")
    ]
    dispinterface _ISourceEventEvents
    {
        properties:
        methods:
    };
    [
        uuid(EEC59666-F958-4731-B3F0-60C7500AF27F),
        helpstring("SourceEvent Class")
    ]
    coclass SourceEvent
    {
        [default] interface ISourceEvent;
        [default, source] dispinterface _ISourceEventEvents;
    };
};
Now the coclass has the implement the interface ISourceEvent and the event dis
pinterface _ISourceEventEvents. But the both interfaces have no method.

3 Add methods to the two interfaces. After that, the idl is like this:

interface ISourceEvent : IDispatch{
    [id(1), helpstring("method SubTract")] HRESULT SubTract([in] LONG NumberOn
e, LONG NumberTwo, LONG* Value);
};

dispinterface _ISourceEventEvents
{
    properties:
    methods:
        [id(1), helpstring("method GetValue")] HRESULT GetValue(LONG value);
};
4 Add connection point to the class CSourceEvent. In class view of visual stud
io.net, right click on the class CSourceEvent and choss “Add”, then choose “
Add connection point…”. In the poped out dialog, add _ISourceEventEvents to 
this class’s impletion. After you do that, the wizard will add a function “F
ire_GetValue(LONG value)” to the class CProxy_ISourceEventEvents.
5 In the fuction SubTract call the event method.
STDMETHODIMP CSourceEvent::SubTract(LONG NumberOne, LONG NumberTwo, LONG* Valu
e)
{
    *Value = NumberOne - NumberTwo;
    
    Fire_GetValue(*Value);
    return S_OK;
}

Now the source coclass is bulit up and now it has four UIDS. They are IID_ISou
rceEvent, LIBID_StepByStepLib, DIID__ISourceEventEvents, CID_SourceEven.
Now build the project and then the dll file StepByStep.dll will be generated. 
It’s the file that client need.

Second Step ----- Build up the client.
1 Create a MFC dialog base object and add a button to the resource file. Add f
ollowing codes to the end of the file Stdafx.h.
#import "..\Debug\StepByStep.dll" raw_interfaces_only no_namespace named_guids

#include <atlbase.h>
#include <atlcom.h>

2 Add a sink class to this project. The class is just like this.
static _ATL_FUNC_INFO infor =
{
    CC_STDCALL, //the call type
    VT_EMPTY, //the return value
    1,          //the number of the params. Only have one
    {VT_I4}      //the params' type. The only one is LONG
};
class EventHandler : public IDispEventImpl<1, EventHandler, &DIID__ISourceEven
tEvents, &LIBID_StepByStepLib>
{
public:
    EventHandler(){};
    ~EventHandler(){};

    HRESULT __stdcall GetSubValue(LONG lValue)
    {
        CString str;
        str.Format(_T("The value is %d"), lValue);
        AfxMessageBox(str);
        return S_OK;
    }

    BEGIN_SINK_MAP(EventHandler)
        SINK_ENTRY_INFO(1, DIID__ISourceEventEvents, 1, GetSubValue, &infor)
    END_SINK_MAP()
};
The class EventHandler is just a sink class which realizes the event interface
.

3 Connect the sink class instance to the source object. Add hander to the adde
d button. 
void CClientDialogDlg::OnBnClickedButton2()
{
    ISourceEventPtr pSource;
    pSource.CreateInstance(__uuidof(SourceEvent));

    if(NULL != pSource)
    {
        EventHandler *pHandler = new EventHandler();
        pHandler->DispEventAdvise(pSource, &DIID__ISourceEventEvents);

        LONG Value;
        pSource->SubTract(100, 20, &Value);

        pHandler->DispEventUnadvise(pSource, &DIID__ISourceEventEvents);
        delete pHandler;
    }
}
When the call pSource->SubTract(100, 20, &Value) a dialog will pop out. Which 
is generated form the client. Now all steps are over and you will find it easy
.

--

※ 来源:·珞珈山水BBS站 http://bbs.whu.edu.cn·[FROM: 210.22.79.*]
[返回单文区目录]

武汉大学BBS 珞珈山水站 All rights reserved.
wForum , 页面执行时间:13.951毫秒