• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            COM callback notify HTML 的兩種方法

            Posted on 2009-09-11 14:25 S.l.e!ep.¢% 閱讀(693) 評論(0)  編輯 收藏 引用 所屬分類: COM

            COM callback notify HTML 的兩種方法

            方法1:
            1. Create ATL Project
            2. New ATL Object...
            3. Simple Object? -> Next
            4. Attributes --> choose? 'Support ISupportErrorInfo'?? == you can throw some exception in COM
            ??? Attributes --> choose 'Support Connection Points'
            5. RightClick? VC6 - IDE? Class Name? --> Implement Connection Point
            ??? Interfaces will display '_xxxxEvents'? <--- Choose it , Click OK
            6. VC6 IDE Will Create A New Class named 'CProxy_IxxxxxEvents'
            7. Add Your Methods

            // CSDN.idl : IDL source for CSDN.dll
            //

            // This file will be processed by the MIDL tool to
            // produce the type library (CSDN.tlb) and marshalling code.

            import "oaidl.idl";
            import "ocidl.idl";
            ?[
            ??object,
            ??uuid(2EE8F461-7200-4C13-A2FC-2552F8773089),
            ??dual,
            ??helpstring("IA Interface"),
            ??pointer_default(unique)
            ?]
            ?interface IA : IDispatch
            ?{

            ?[id(1), helpstring("method Init")] HRESULT Init();
            ?
            };

            ?[
            ??object,
            ??uuid(C5C88155-7CAB-4109-9610-234A6AD529DC),
            ??dual,
            ??helpstring("IEvent Interface"),
            ??pointer_default(unique)
            ?]

            ?interface IEvent :? IUnknown
            ?{
            ??[id(1), helpstring("method OnDataChanged")] HRESULT OnDataChanged();
            ?};

            [
            ?uuid(477B6435-238C-43AF-95DA-2F890256DF43),
            ?version(1.0),
            ?helpstring("CSDN 1.0 Type Library")
            ]
            library CSDNLib
            {
            ?importlib("stdole32.tlb");
            ?importlib("stdole2.tlb");

            ?[
            ??uuid(1FBB2F1E-E12E-4CE6-88EA-704E1CAE1091),
            ??helpstring("A Class")
            ?]
            ?coclass A
            ?{
            ??[default] interface IA;
            ??[source]? interface IEvent;
            ?
            };
            };//end


            ------

            其中紅色代碼為手工添加.IEvent UUID由GUIDGEN.EXE生成.IEvent 添加方法OnDataChanged.在客戶端調用時添加功能代碼,我們將在接口IEvent的Init方法中回調其方法。此處為Connection Point之精粹.在ActiveX中事件的實現方法也以此技術為基礎.

            3.編譯程序后,點擊COM對象Implement Connection Point...選項后,選中IEvent。則ATL向導將為我們生成新的實現聯接點的COM對象CA。

            class ATL_NO_VTABLE CA :
            ?public CComObjectRootEx<CComSingleThreadModel>,
            ?public CComCoClass<CA, &CLSID_A>,
            ?public IDispatchImpl<IA, &IID_IA, &LIBID_CSDNLib>,
            ?public CProxyIEvent< CA >,
            ?public IConnectionPointContainerImpl<CA>

            4.實現IA接口的Init方法

            STDMETHODIMP CA::Init()
            {
            ?AFX_MANAGE_STATE(AfxGetStaticModuleState())

            ?Fire_OnDataChanged();

            ?return S_OK;
            }

            編譯程序后,COM服務器的編碼寫成.

            COM客戶端實現:

            1.實現接收器類

            http://study.feloo.com/Event.h/default.htm

            class CEvent? : public IEvent
            {
            public:
            // IUnknown
            ?ULONG __stdcall AddRef();
            ?ULONG __stdcall Release();
            ?HRESULT __stdcall QueryInterface(REFIID iid, void** ppv);
            //IEvent
            public:
            ?STDMETHOD(OnDataChanged)();
            public:
            ?CEvent():m_cRef(0){}
            ?virtual ~CEvent(){}
            private:
            ?long m_cRef;
            };//end

            //Event.cpp

            ULONG CEvent::AddRef()

            {
            ?return InterlockedIncrement(&m_cRef);
            }

            ULONG CEvent::Release()
            {
            ?if (InterlockedDecrement(&m_cRef) != 0)
            ??return m_cRef;
            ?delete this;
            ?return 0;
            }

            HRESULT CEvent::QueryInterface(REFIID riid, void** ppv)
            {
            ?if (riid == IID_IUnknown)
            ?{
            ??*ppv = (IUnknown*)this;
            ?}
            ?else if (riid == IID_IEvent)
            ?{
            ??*ppv = (IEvent*)this;
            ?}
            ?else
            ?{
            ??*ppv = NULL;
            ??return E_NOINTERFACE;
            ?}
            ?AddRef();
            ?return S_OK;
            }

            STDMETHODIMP CEvent::OnDataChanged()
            {
            ?AfxMessageBox(_T("OnDataChanged!"));
            ?return S_OK;
            }

            //end

            在CEvent::OnDataChanged()中添加的實現將由接口IA的Init方法回調。

            2.客戶端實現代碼

            void CCSDNClientDlg::OnButton1()

            {

            ?CoInitialize(NULL);

            ?IA* pIA = NULL;
            ?CEvent* pEvent = NULL;
            ?HRESULT hr = CoCreateInstance(CLSID_A,NULL,
            ?????????CLSCTX_INPROC_SERVER,
            ?????????IID_IA,
            ?????????(void**)&pIA);


            ?if ( FAILED(hr) )
            ?{
            ??AfxMessageBox("Initalize com failed!");
            ??return ;
            ?} // if?????

            ?IConnectionPointContainer* pConnectionPointContainer = NULL;???
            ?IConnectionPoint* pConnectionPoint = NULL ;


            ?pEvent= new CEvent();
            ?pEvent->AddRef();

            ?DWORD dwCookie;

            ??? hr = pIA->QueryInterface(IID_IConnectionPointContainer, (void**)?? &pConnectionPointContainer);????
            ??? //IRecord->Release();
            ?ASSERT(SUCCEEDED(hr));

            ??hr = pConnectionPointContainer->FindConnectionPoint(IID_IEvent, &pConnectionPoint);

            ?ASSERT(SUCCEEDED(hr));
            ?ConnectionPoint->Advise((IUnknown*)pEvent, &dwCookie);????
            ?pConnectionPoint->Release();????


            ??hr = pIA->Init();//此處將激發事件OnDataChanged()

            ?ASSERT(SUCCEEDED(hr));

            ????? hr = pConnectionPointContainer->FindConnectionPoint(IID_IEvent, &pConnectionPoint);?

            ?ASSERT(SUCCEEDED(hr));
            ?pConnectionPoint->Unadvise(dwCookie);????
            pConnectionPoint->Release();

            ?pConnectionPointContainer->Release();
            ?pIA->Release();

            ?pEvent->Release();
            //?delete pEvent;

            ?CoUninitialize();
            }

            //end

            文筆不好,見諒了!

            完成 com? 之后,就可以在 html 加上

            <SCRIPT ID=EventHandler FOR="xxxx" EVENT="OnTest(a, b)">
            alert(a);??
            </SCRIPT>
            來響應了, 但這種方法只適用于

            <OBJECT style="display:none;" TYPE="application/x-oleobject" classid=clsid:91443C71-B7DD-49F5-9F86-A2D305CED76A CODEBASE="abc.cab#Version=1,0,0,001"></OBJECT>??

            如果在 HTML 是通過 new ActiveXObject 來創建 COM 的, 那么則需要用第二種方法
            ---------------------

            方法二:

            在htm中接受com控件發出的事件(VC/MFC ATL/ActiveX/COM


            我為客戶做了一個com控件有一些事件(如OnStateChange)發出,客戶要求用htm調用。
            一開始,一切正常htm中調用代碼如下:

            <OBJECT ID="DvdPlayCtl" CLASSID="CLSID:EE9626A3-976C-470C-8282-07AB2FE2F85F"></OBJECT>

            <SCRIPT language="JavaScript">

            DvdPlayCtl.
            attachEvent("OnStateChange", MyOnStateChange);

            function MyOnStateChange(state,info)
            {
            alert("state change to "+state+" ,"+info);
            }
            </script>
            則一旦com的狀態發生改變就發出OnStateChange事件,htm就可以正常接受并提示,但后來客戶要求用
            另一種方式聲明com控件,代碼如下:

            <SCRIPT language="JavaScript">
            var DvdPlayCtl = new ActiveXObject("DvdPlayCtl.DvdPlayCtl");
            </script>
            即動態生成此com控件,則運行htm時以前的代碼DvdPlayCtl.attachEvent部分出錯:“對象不支持此操作”


            1、在com中增加一個屬性OnStateChange,其類型為IDispatch *并為其添加put方法。

            2、在put方法的實現中將傳進的DISPATCH型指針賦給自己的成員變量IDispatch *m_pDispatch。

            STDMETHODIMP CDvdPlayCtl::put_OnStateChange(IDispatch *newVal)
            {
            // TODO: Add your implementation code here
            m_pDispatch = newVal;
            return S_OK;
            }

            3、定義成員函數void Send_Event(int state, TCHAR * info);在發送事件的函數中添加以下代碼:
            if (m_pDispatch != NULL)
            {
            CComVariant* pvars = new CComVariant[2];

            pvars[1] = state;//回調函數的第一個參數
            pvars[0] = info;//回調函數的第二個參數

            DISPPARAMS disp = { pvars, NULL, 2, 0 };
            HRESULT hr = m_pDispatch->Invoke(0, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, NULL, NULL, NULL);
            delete[] pvars;
            }
            注意:
            1、pvars的填充與函數參數順序是相反的
            4、在htm中如下調用
            <script language="JavaScript">

            var DvdPlayCtl = new ActiveXObject("DvdPlayCtl.DvdPlayCtl");

            DvdPlayCtl.OnStateChange = OnStateChange;
            DvdPlayCtl.OnError = OnError;

            function OnStateChange(state,info)
            {
            alert("state change to "+state+" ,"+info);
            }
            </script>



            ?

            久久黄色视频| 精品久久久久久久久中文字幕| 精品国产VA久久久久久久冰| 精品国产日韩久久亚洲| 大香网伊人久久综合网2020| 国产精品视频久久久| 久久亚洲精品国产精品| 亚洲欧美伊人久久综合一区二区| 久久精品国产免费观看| 亚洲午夜精品久久久久久app| 色偷偷88欧美精品久久久| 一级A毛片免费观看久久精品| 亚洲综合久久久| 亚洲美日韩Av中文字幕无码久久久妻妇 | 韩国免费A级毛片久久| 久久精品国产久精国产思思| 国产美女久久精品香蕉69| 97超级碰碰碰碰久久久久| 久久国产V一级毛多内射| 午夜精品久久久内射近拍高清 | 国产精品免费看久久久| 国产一区二区三区久久精品| 久久91精品国产91久久麻豆| 韩国三级中文字幕hd久久精品 | 久久久久久一区国产精品| 久久只这里是精品66| 久久精品中文騷妇女内射| 国产99久久久久久免费看| 亚洲午夜精品久久久久久浪潮| 亚洲欧美日韩中文久久| 一级做a爱片久久毛片| 国内精品伊人久久久久妇| 97精品久久天干天天天按摩 | 亚州日韩精品专区久久久| 久久久久亚洲av无码专区喷水| 一级做a爱片久久毛片| 午夜人妻久久久久久久久| 91性高湖久久久久| 亚洲av成人无码久久精品| 性做久久久久久久久| 久久福利片|