Step By Step 可连接对象与接受器实现

    技术2022-05-11  67

    一、创建源对象

    1、新建atl项目

     

     

     

     

     

     

     

     

     

     

     

     

     

    2、选择exe,确定

     

     

     

     

     

     

     

     

     

     

     

     

    3、在WorkSpace中右键点项目,在弹出菜单中选择NEW ATL OBJECT

     

     

     

     

     

     

     

    4、Category选ojbect,Objects选SimpleObject

     

     

     

     

     

     

     

    5、Names标签中的ShortName中输入Math

     

     

     

     

     

     

     

    6、Attributes标签中选上Support Connection Points

     

     

     

     

     

     

     

    7、在WorkSpace中鼠标右键点击IMath,选择Add Mathod

     

     

     

     

     

     

     

     

     

     

     

    8、按如下输入

     

     

     

     

     

     

     

     

    9、打开SourceObj.idl 加入 dispinterface _IMathEvents {  properties:  methods:  [id(1), helpstring("method Finished")] HRESULT OnSpeak([in] long lResult); };

    10、先build,然后鼠标右键点击CMath,选择Implement Connection Point

     

     

     

     

     

     

     

     

     

     

    再谈出的对话框中,选择_IMathEvents,然后按默认操作。

    12、然后

    STDMETHODIMP CMath::Speak(long time){ // TODO: Add your implementation code here Fire_OnSpeak(time); return S_OK;}然后再math.h中修改BEGIN_CONNECTION_POINT_MAP(CMath)CONNECTION_POINT_ENTRY(DIID__IMathEvents)END_CONNECTION_POINT_MAP()

    然后重新编译

    二、创建代理存根DLL1、在WorkSpace中右键点然后选择Insert Project into Workspace

     

     

     

     

     

    2、选择SourceObj.mk,

     

     

     

     

     

     

     

     

     

    3、选择sourceObj1项目的Project Setting按如下设置

     

     

     

     

     

     

     

     

     

     

     

     

    设置好后编译。

    4、选择菜单的register control

     

     

     

     

     

     

     

     

     

    三、创建接受器

    1、右键点击WorkSpace选择add new project

     

     

     

     

     

    2、接下来按照图1,图2设置生成新的项目,项目名为Sink

    3、修改Sink.cpp,代码如下

    // Sink.cpp : Implementation of WinMain

    // Note: Proxy/Stub Information//      To build a separate proxy/stub DLL, //      run nmake -f Sinkps.mk in the project directory.

    #include "stdafx.h"#include "resource.h"#include <initguid.h>#include "Sink.h"

    #include "Sink_i.c"

    #include "../SourceObj/SourceObj_i.c"#include "../SourceObj/SourceObj.h"#include <WINDOWS.H>

    static _ATL_FUNC_INFO OnSpeakInfo = {CC_STDCALL, VT_EMPTY, 1,{VT_I4}};static const int DISPID_ONSPEAK = 1;static const int SPEAK_EVENT_ID = 1;//任意

    class CSinkObj : public IDispEventSimpleImpl<SPEAK_EVENT_ID, CSinkObj, &__uuidof(_IMathEvents)>{public: CSinkObj() { }

    BEGIN_SINK_MAP(CSinkObj) //Make sure the Event Handlers have __stdcall calling convention SINK_ENTRY_INFO(SPEAK_EVENT_ID, __uuidof(_IMathEvents), DISPID_ONSPEAK, OnSpeak, &OnSpeakInfo)END_SINK_MAP()

     // Event handler  HRESULT __stdcall OnSpeak(long lResult) {  Beep(5000,lResult);  return S_OK; }};

     

     

    const DWORD dwTimeOut = 5000; // time for EXE to be idle before shutting downconst DWORD dwPause = 1000; // time to wait for threads to finish up

    // Passed to CreateThread to monitor the shutdown eventstatic DWORD WINAPI MonitorProc(void* pv){    CExeModule* p = (CExeModule*)pv;    p->MonitorShutdown();    return 0;}

    LONG CExeModule::Unlock(){    LONG l = CComModule::Unlock();    if (l == 0)    {        bActivity = true;        SetEvent(hEventShutdown); // tell monitor that we transitioned to zero    }    return l;}

    //Monitors the shutdown eventvoid CExeModule::MonitorShutdown(){    while (1)    {        WaitForSingleObject(hEventShutdown, INFINITE);        DWORD dwWait=0;        do        {            bActivity = false;            dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);        } while (dwWait == WAIT_OBJECT_0);        // timed out        if (!bActivity && m_nLockCnt == 0) // if no activity let's really bail        {#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)            CoSuspendClassObjects();            if (!bActivity && m_nLockCnt == 0)#endif                break;        }    }    CloseHandle(hEventShutdown);    PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);}

    bool CExeModule::StartMonitor(){    hEventShutdown = CreateEvent(NULL, false, false, NULL);    if (hEventShutdown == NULL)        return false;    DWORD dwThreadID;    HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);    return (h != NULL);}

    CExeModule _Module;

    BEGIN_OBJECT_MAP(ObjectMap)END_OBJECT_MAP()

    LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2){    while (p1 != NULL && *p1 != NULL)    {        LPCTSTR p = p2;        while (p != NULL && *p != NULL)        {            if (*p1 == *p)                return CharNext(p1);            p = CharNext(p);        }        p1 = CharNext(p1);    }    return NULL;}

    ///extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,     HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/){    lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT

    #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)    HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);#else    HRESULT hRes = CoInitialize(NULL);#endif    _ASSERTE(SUCCEEDED(hRes));    _Module.Init(ObjectMap, hInstance, &LIBID_SINKLib);    _Module.dwThreadID = GetCurrentThreadId();    TCHAR szTokens[] = _T("-/");

    /*    int nRet = 0;    BOOL bRun = TRUE;    LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);    while (lpszToken != NULL)    {        if (lstrcmpi(lpszToken, _T("UnregServer"))==0)        {            _Module.UpdateRegistryFromResource(IDR_Sink, FALSE);            nRet = _Module.UnregisterServer(TRUE);            bRun = FALSE;            break;        }        if (lstrcmpi(lpszToken, _T("RegServer"))==0)        {            _Module.UpdateRegistryFromResource(IDR_Sink, TRUE);            nRet = _Module.RegisterServer(TRUE);            bRun = FALSE;            break;        }        lpszToken = FindOneOf(lpszToken, szTokens);    }

        if (bRun)    {        _Module.StartMonitor();#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,             REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);        _ASSERTE(SUCCEEDED(hRes));        hRes = CoResumeClassObjects();#else        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,             REGCLS_MULTIPLEUSE);#endif        _ASSERTE(SUCCEEDED(hRes));

            MSG msg;        while (GetMessage(&msg, 0, 0, 0))            DispatchMessage(&msg);

            _Module.RevokeClassObjects();        Sleep(dwPause); //wait for any threads to finish    }*/ IMath *pMath; HRESULT hr=CoCreateInstance(CLSID_Math,NULL,CLSCTX_LOCAL_SERVER ,__uuidof(IMath),(void**)&pMath);

     if(SUCCEEDED(hr)) {  CSinkObj *pSink=NULL;  pSink=new CSinkObj;  pSink->DispEventAdvise(pMath);  pMath->Speak(2000);

      if(pSink)  {   if (pSink->m_dwEventCookie != 0xFEFEFEFE)    pSink->DispEventUnadvise(pMath);   delete pSink;  }   }

        _Module.Term();    CoUninitialize();    return 0;}

    四、程序流程

    Sink调用Source的Speak接口,Speak接口通知Sink,"I am On Speak"

    bluecrest.nease.net要代吗给我发邮件


    最新回复(0)