李国帅 2009
使用连接点添加com控件事件的例子
1、控件类声明
// CTopseePlayer.h : 由 Microsoft Visual C++ 创建的 ActiveX 控件包装类的声明 #pragma once ///// // CTopseePlayer class CTopseePlayer : public CWnd { protected: DECLARE_DYNCREATE( CTopseePlayer ) //IMPLEMENT_DYNCREATE(CTopseePlayer, CWnd) public: CLSID const& GetClsid() { static CLSID const clsid = { 0x2C8548DD, 0x829D, 0x473C, { 0x9C, 0xF4, 0xBB, 0xA2, 0x3E, 0x12, 0xA6, 0x2B } }; return clsid; } virtual BOOL Create( LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL ) { return CreateControl( GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID ); } BOOL Create( LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CFile* pPersist = NULL, BOOL bStorage = FALSE, BSTR bstrLicKey = NULL ) { return CreateControl( GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID, pPersist, bStorage, bstrLicKey ); } // 操作 public: void Play() { InvokeHelper( 0x1, DISPATCH_METHOD, VT_EMPTY, NULL, NULL ); } void Stop() { InvokeHelper( 0x2, DISPATCH_METHOD, VT_EMPTY, NULL, NULL ); } CString GetURL() { CString result; InvokeHelper( 0x3, DISPATCH_PROPERTYGET, VT_BSTR, ( void* )&result, NULL ); return result; } void PutURL( LPCTSTR newValue ) { static BYTE parms[] = VTS_BSTR ; InvokeHelper( 0x3, DISPATCH_PROPERTYPUT, VT_EMPTY, NULL, parms, newValue ); } ... void MonitorChange() { InvokeHelper(0x32, DISPATCH_METHOD, VT_EMPTY, NULL, NULL); } BOOL CheckFullScreen() { BOOL result; InvokeHelper(0x33, DISPATCH_METHOD, VT_BOOL, (void*)&result, NULL); return result; } public: int PointInRect( POINT pt, CRect &rect ); void DrawWhiteRect( CRect rect ); void DrawRedRect( CRect rect ); DECLARE_MESSAGE_MAP() virtual BOOL PreTranslateMessage( MSG* pMsg ); CTopseePlayer(); // 属性 public: BOOL m_bQuery; //是否按下查询录象 //static BOOL m_bFullScreen; //视频显示整个屏幕 static BOOL m_bLogin; //static BOOL m_bDraw; BOOL m_bLock; }; |
2、控件事件头文件
#pragma once #include "oaidl.h" class CEventSink : public IDispatch { public: CEventSink(CWnd* pParent = NULL); ~CEventSink(void); CWnd* m_pParent; public: //void SetResultWnd(CEdit * pEdit); // IUnknown STDMETHOD(QueryInterface)(const struct _GUID &iid,void ** ppv); ULONG __stdcall AddRef(void); ULONG __stdcall Release(void); // IDispatch STDMETHOD(GetTypeInfoCount)(unsigned int *); STDMETHOD(GetTypeInfo)(unsigned int,unsigned long,struct ITypeInfo ** ); STDMETHOD(GetIDsOfNames)(const IID &,LPOLESTR *,UINT,LCID,DISPID *); STDMETHOD(Invoke)(long dispID,const struct _GUID &,unsigned long,unsigned short,struct tagDISPPARAMS * pParams,struct tagVARIANT *,struct tagEXCEPINFO *,unsigned int *); }; |
3、控件事件定义文件
#include "StdAfx.h" #include ".\eventsink.h" //#include "MultiViewer.h" //class CMainFrame; CEventSink::CEventSink(CWnd* pParent){ m_pParent = pParent;} CEventSink::~CEventSink(void){} // STDMETHODIMP 是宏,等价于 long __stdcall STDMETHODIMP CEventSink::QueryInterface(const struct _GUID &iid,void ** ppv) { *ppv = this; return S_OK; } ULONG __stdcall CEventSink::AddRef(void){ return 1; } // 做个假的就可以,因为反正这个对象在程序结束前是不会退出的 ULONG __stdcall CEventSink::Release(void){ return 0; } // 做个假的就可以,因为反正这个对象在程序结束前是不会退出的 STDMETHODIMP CEventSink::GetTypeInfoCount(unsigned int *){ return E_NOTIMPL; } // 不用实现,反正也不用 STDMETHODIMP CEventSink::GetTypeInfo(unsigned int,unsigned long,struct ITypeInfo ** ){ return E_NOTIMPL; } // 不用实现,反正也不用 STDMETHODIMP CEventSink::GetIDsOfNames(const IID &,LPOLESTR *,UINT,LCID,DISPID *){ return E_NOTIMPL; } // 不用实现,反正也不用 STDMETHODIMP CEventSink::Invoke( long dispID, const struct _GUID &, unsigned long, unsigned short, struct tagDISPPARAMS * pParams, struct tagVARIANT *, struct tagEXCEPINFO *, unsigned int *) { // 只需要实现这个就足够啦 // CMainFrame* pMainFrame = (CMainFrame*)m_pParent; // CWorkStat* pStat = (CWorkStat*)m_pParent; switch(dispID)//获取事件的id号,回调其他类的处理函数进行处理 { case 1: //Alarm //if (pParams[0].cArgs != 3) // TRACE0("Arg Num is Error\n"); //TRACE3("Channel %d, Sub %d, Alarm Type %d\n", pParams->rgvarg[2].lVal, pParams->rgvarg[1].lVal, pParams->rgvarg[0].lVal); //pStat->OnAlarm(pParams->rgvarg[2].lVal, pParams->rgvarg[1].lVal, pParams->rgvarg[0].lVal); break; case 2: // PlayBegin(LONG Channel, LONG SubChannel) TRACE1("channel %d play begin\n", pParams->rgvarg[1].lVal); //pStat->OnPlayBegin(pParams->rgvarg[1].lVal, pParams->rgvarg[0].lVal); //((CWorkStat*)m_pParent)->m_Info[pParams->rgvarg[1].lVal].SetPlayStat(TRUE); break; case 3: // PlayStop(LONG Channel, LONG SubChannel) TRACE1("channel %d play stop\n", pParams->rgvarg[1].lVal); //pStat->OnPlayStop(pParams->rgvarg[1].lVal, pParams->rgvarg[0].lVal); //((CWorkStat*)m_pParent)->m_Info[pParams->rgvarg[1].lVal].SetPlayStat(FALSE); break; case 4: // SaveBegin(LONG Channel, LONG SubChannel) //pStat->OnSaveBegin(pParams->rgvarg[1].lVal, pParams->rgvarg[0].lVal); //((CWorkStat*)m_pParent)->m_Info[pParams->rgvarg[1].lVal].SetSaveStat(TRUE); break; case 5: // SaveStop(LONG Channel, LONG SubChannel) //pStat->OnSaveStop(pParams->rgvarg[1].lVal, pParams->rgvarg[0].lVal); // ((CWorkStat*)m_pParent)->m_Info[pParams->rgvarg[1].lVal].SetSaveStat(FALSE); break; ..... default: TRACE0( "怎么可能,根本就没有这个号码的函数呀\n" ); break; } return S_OK; } |
4、控件调用头文件
// MainFrm.h : CMainFrame 类的接口 #pragma once #include "CTopseePlayer.h" #include "EventSink.h" class CMainFrame : public CFrameWnd { public: CMainFrame(); protected: DECLARE_DYNAMIC(CMainFrame) // 重写 public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); // 实现 public: virtual ~CMainFrame(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif // 属性 public: public:// CChildView m_wndView; CTopseePlayer *pDisplay; CEventSink* pEvent; IConnectionPoint* m_pConPoint; DWORD m_dwAdvise; // 生成的消息映射函数 protected: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnSetFocus(CWnd *pOldWnd); DECLARE_MESSAGE_MAP() public: afx_msg void OnMove(int x, int y); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnOpenFile(); afx_msg void OnOpenUrl(); }; |
5、事件的具体调用
// // MainFrm.cpp : CMainFrame 类的实现 #include "stdafx.h" #include "TSPlayer.h" #include "MainFrm.h" #include ".\mainfrm.h" #include "openurldlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CMainFrame IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd) BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_WM_SETFOCUS() ON_WM_MOVE() ON_WM_SIZE() ON_COMMAND(ID_OPEN_FILE, OnOpenFile) ON_COMMAND(ID_OPEN_URL, OnOpenUrl) END_MESSAGE_MAP() // CMainFrame 构造/析构 CMainFrame::CMainFrame() { // TODO: 在此添加成员初始化代码 pDisplay = new CTopseePlayer(); //pEvent = new CEventSink(); } CMainFrame::~CMainFrame() { if (pEvent != NULL) delete pEvent; if (pDisplay != NULL) delete pDisplay; } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; RECT rcClient; GetClientRect(&rcClient); if (!pDisplay->Create(_T(""), WS_VISIBLE|WS_CHILD, CRect(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom), this, 100)) { MessageBox(_T("Display control initialize failed, program exit now!")); PostMessage(WM_CLOSE); return FALSE; } pDisplay->PutRunMode(0); pDisplay->PutShowControls(true); m_pConPoint = NULL; pEvent = new CEventSink(this); IConnectionPointContainer * pContainer; IUnknown* pDisplayUnk = ((CMainFrame*)theApp.GetMainWnd())->pDisplay->GetControlUnknown(); GUID IID_ITopseePlayerEvents = { 0x22143EA9, 0x10C5, 0x43A6, 0xA0, 0x6C, 0x20, 0xE7, 0x87, 0x8B, 0x1C, 0xB8 }; if (pDisplayUnk) { pDisplayUnk->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pContainer); pDisplayUnk->Release(); if (pContainer) { pContainer->FindConnectionPoint(IID_ITopseePlayerEvents, &m_pConPoint); pContainer->Release(); if (m_pConPoint) { m_pConPoint->Advise(pEvent, &m_dwAdvise); } } } return 0; } BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { if( !CFrameWnd::PreCreateWindow(cs) ) return FALSE; // TODO: 在此处通过修改 CREATESTRUCT cs 来修改窗口类或 // 样式 cs.cx = 360; cs.cy = 360; //cs.dwExStyle &= ~WS_EX_CLIENTEDGE; //cs.lpszClass = AfxRegisterWndClass(0); return TRUE; } // CMainFrame 诊断 #ifdef _DEBUG void CMainFrame::AssertValid() const { CFrameWnd::AssertValid(); } void CMainFrame::Dump(CDumpContext& dc) const { CFrameWnd::Dump(dc); } #endif //_DEBUG // CMainFrame 消息处理程序 void CMainFrame::OnSetFocus(CWnd* /*pOldWnd*/) { // 将焦点前移到视图窗口 // m_wndView.SetFocus(); if (pDisplay != NULL) pDisplay->SetFocus(); } BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // 让视图第一次尝试该命令 // if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) // return TRUE; // 否则,执行默认处理 return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); } void CMainFrame::OnMove(int x, int y) { CFrameWnd::OnMove(x, y); CRect rtRect; GetClientRect(&rtRect); if (pDisplay != NULL) pDisplay->MoveWindow(&rtRect); } void CMainFrame::OnSize(UINT nType, int cx, int cy) { CFrameWnd::OnSize(nType, cx, cy); CRect rtRect; GetClientRect(&rtRect); if (pDisplay != NULL) pDisplay->MoveWindow(&rtRect); } void CMainFrame::OnOpenFile() { TCHAR resultFile[MAX_PATH] = {'\0'}; OPENFILENAME fileName; ZeroMemory(&fileName, sizeof(OPENFILENAME)); fileName.lStructSize = sizeof(OPENFILENAME); fileName.hwndOwner = m_hWnd; //fileName.hInstance = 0; // ZeroMemory does the work. fileName.lpstrFilter = _T("All Files (*.asf)\0*.asf\0\0"); fileName.lpstrCustomFilter = NULL; //fileName.nMaxCustFilter = 0; // ZeroMemory does the work. fileName.nFilterIndex = -1; fileName.lpstrFile = resultFile; fileName.nMaxFile = MAX_PATH; fileName.lpstrInitialDir = NULL; fileName.lpstrTitle = _T("Select Open File"); fileName.Flags = OFN_EXPLORER + OFN_ENABLESIZING + OFN_HIDEREADONLY;// | extraFlags; if (GetSaveFileName(&fileName)) { pDisplay->PutRunMode(2); pDisplay->PutFileName(resultFile); pDisplay->PlayFile(); } } void CMainFrame::OnOpenUrl() { COpenUrlDlg dlg; if (dlg.DoModal() == IDOK) { if (dlg.m_Url.GetLength() == 0) return; pDisplay->PutRunMode(0); pDisplay->PutURL(dlg.m_Url); if (dlg.m_User.GetLength() != 0) pDisplay->PutUserName(dlg.m_User); if (dlg.m_Passwd.GetLength() != 0) pDisplay->PutPasswd(dlg.m_Passwd); pDisplay->Play(); } } |