在OCX中事件的传递
CMainDialog类:在OCX中新建的一个窗口类,只有一个Picture Control用于显示摄像头图像
COCX_KankanCtrl 类:和网页端进行交互的一些事情
当html5调用OCX控件时,通过触发网页端button,调用OCX控件的函数StartCameraEx,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//test.html <input type='button' onclick='javascript:Startcamera();' value='ClickCameraStart'> <script language="javascript" type="text/javascript"> var facedata = new Array(300); function Startcamera() { for (var i = 0; i < 300; i++) { facedata[i] = i; } alert("facedata:"+facedata[299] ); OCX_kankan.StartCameraEx(0); } </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//OCX_KankanCtrl.h class COCX_KankanCtrl : public COleControl{ ... // Dispatch and event IDs public: enum { dispidStartGatherEx = 8L, dispidStartCameraEx = 1L }; afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);//自己添加的函数 CMainDialog m_mainDialog; //CMainDialog m_Dialog; protected: LONG StartCameraEx(LONG camid); }; //OCX_KankanCtrl.cpp BEGIN_DISPATCH_MAP(COCX_KankanCtrl, COleControl) DISP_FUNCTION_ID(COCX_KankanCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE) DISP_FUNCTION_ID(COCX_KankanCtrl, "StartCameraEx", dispidStartCameraEx, StartCameraEx, VT_I4, VTS_I4) //DISP_FUNCTION_ID(COCX_KankanCtrl, "StartRecEx", dispidStartRecEx, StartRecEx, VT_I4, VTS_DISPATCH VTS_I4) END_DISPATCH_MAP() LONG COCX_KankanCtrl::StartCameraEx(LONG camid){ AFX_MANAGE_STATE(AfxGetStaticModuleState()); int ret = m_mainDialog.CamStartEx( camid ); return (LONG)ret; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
//MainDialog.cpp //开启摄像头,这个函数会被在OCX_KankanCtrl里面被用到 int CMainDialog::CamStartEx(int camid){ //是否需要判断摄像头依然开启? if ( m_CAMFLAG==true ) return -1;//Already Open else { //Binding camera if ( camid < 0 ) camid = 0; m_vids.open(camid); if ( !m_vids.isOpened() ) { m_vids.release(); return -2; } m_CAMFLAG = true; //If success m_GATHERFLAG = false; m_RECFLAG = false; m_pVisParam->pDlg = (CWnd*)this; //一般情况下,调用AfxBeginThread()来一次性地创建并启动一个线程 m_pThreadVIS = AfxBeginThread( DisplayVISCamera , (LPVOID)m_pVisParam ); } return 1; } //线程的入口函数,声明如下: UINT MyThreadFunction(LPVOID pParam),不能设置为NULL; UINT DisplayVISCamera( LPVOID pParam ){ THREADPARAM* Param = (THREADPARAM*)pParam; CMainDialog* pDlg = (CMainDialog*)Param->pDlg; //Insert Scan Line int cont = 0; //首先CamStartEx 开启摄像头 m_CAMFLAG=true; while(pDlg->m_CAMFLAG){ ... int facehandle = FaceLocatedEx( ...); //如果有识别标志,一般是在startRecEx里面置为true if ( pDlg->m_RECFLAG ){ //facehandle定位成功 if ( facehandle > 0 ){ double similarity = HJCalcDisC( mfeat1 , pDlg->m_facefeat , 300 ); if ( similarity > 0.6 ){ //该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。 //消息队列里的消息通过调用GetMessage和PeekMessage取得。 //BOOL WINAPI PostMessage(HWNDhWnd,UINTMsg,WPARAMwParam,LPARAMlParam); PostMessage( pDlg->m_hWnd , WM_MYRECMSG , 1 , 0 ); pDlg->m_RECFLAG = false; } } } else if ( pDlg->m_GATHERFLAG ){ if ( facehandle > 0 ){ memcpy( pDlg->m_facefeat , mfeat1 , 300*sizeof(float) ); PostMessage( pDlg->m_hWnd , WM_MYGATHERMSG , 1 , 0 );//在线程里不断的抛出消息 pDlg->m_GATHERFLAG = false; } } ... Sleep( 50 ); } // AfxEndThread(0); pDlg->m_GATHERFLAG = false; pDlg->m_RECFLAG = false; return -1; } |
注意:在线程中通过PostMessage不断的抛出消息,(时间很短,不影响线程。),这是一种异步消息的模式,不会受到线程的影响(比如线程卡死)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
MainDialog.h #define WM_MYGATHERMSG WM_USER+101 ////自定义消息,在WM_USER基础上增加,但是前100最好不用 #define WM_MYRECMSG WM_USER+102 class CMainDialog : public CDialogEx { DECLARE_DYNAMIC(CMainDialog) //OnMessage返回值必须为LRESULT,其形式为:afx_msg LRESULT OnMessage(WPARAM, LPARAM); afx_msg LRESULT OnGatherMessage( WPARAM wParam, LPARAM lParam ); afx_msg LRESULT OnRecMessage( WPARAM wParam, LPARAM lParam ); public: CWnd* pCtrl;//trick and hock; 钩子函数 pCtrl FaceRecCallback FaceRecCallbackFunc; FaceRecCallback FaceGatherCallbackFunc; } MainDialog.cpp //WPARAM 和 LPARAM,消息响应机制;wParam和lParam 这两个是Win16系统遗留下来的产物,在Win16API中WndProc有两个参数: //一个是WORD类型的16位整型变量;另一个是LONG类型的32位整型变量。因此根据匈牙利命名法,16位的变量就被命名为wParam, 32位的变量就被命名为lParam。 LRESULT CMainDialog::OnGatherMessage( WPARAM wParam, LPARAM lParam ){ FaceGatherCallbackFunc( wParam , pCtrl ); return 0; } LRESULT CMainDialog::OnRecMessage( WPARAM wParam, LPARAM lParam ){ FaceRecCallbackFunc( wParam , pCtrl); return 0; } |
回调函数是在COCX_KankanCtrl层,来传递消息。 消息异步执行,去触发回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class COCX_kankanCtrl : public COleControl{ public: friend void _stdcall hjRecCallback( long usrID , CWnd* pCtrl );//友元函数 friend void _stdcall hjGatherCallback( long usrID , CWnd* pCtrl ); // Dispatch and event IDs public: enum { dispidStopRoGEx = 9L, dispidStartGatherEx = 8L, dispidGetFaceFeatEx = 7L, eventidhjGatherEvent = 2L, eventidhjRecEvent = 1L, dispidRegCallBackFuncEx = 6L, dispidStartRecEx = 5L, dispidModifyDataTest = 4L, dispidReceiveDataTest = 3L, dispidStopCameraEx = 2L, dispidStartCameraEx = 1L }; protected: void hjRecEvent(LONG res){ FireEvent(eventidhjRecEvent, EVENT_PARAM(VTS_I4), res); } void hjGatherEvent(LONG res){ FireEvent(eventidhjGatherEvent, EVENT_PARAM(VTS_I4), res); } } //COCX_KankanCtrl.cpp // Event map BEGIN_EVENT_MAP(COCX_kankanCtrl, COleControl) EVENT_CUSTOM_ID("hjRecEvent", eventidhjRecEvent, hjRecEvent, VTS_I4) EVENT_CUSTOM_ID("hjGatherEvent", eventidhjGatherEvent, hjGatherEvent, VTS_I4) END_EVENT_MAP() |
我们在网页端去调用OCX的控件,然后OCX响应网页端的消息后进行识别,并传出消息返回给网页端,然后由网页端给出采集或者识别的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
//test.html <script language="Javascript" event="hjGatherEvent( res )" for="OCX_kankan"> egather( res ); </script> <script language="Javascript" event="hjRecEvent( res )" for="OCX_kankan"> erec( res ); </script> function egather(para1) { alert("event:" + para1); if (para1 > 0) { OCX_kankan.GetFaceFeatEx(facedata, 300); alert( "facedata:"+facedata[0]+facedata[1]+facedata[299] ); } } function erec(para1) { alert("event:" + para1); if (para1 > 0) { alert("Same Person!"); } } |
COCX_KankanCtrl层进行回调函数,把这两个事件的指针传入进来,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//COCX_KankanCtrl.cpp void _stdcall hjRecCallback( long usrID , CWnd* pCtrl ){ COCX_kankanCtrl* _pCtrl = (COCX_kankanCtrl*)pCtrl; _pCtrl->hjRecEvent(usrID);//消息事件 return; } void _stdcall hjGatherCallback( long usrID , CWnd* pCtrl ){ COCX_kankanCtrl* _pCtrl = (COCX_kankanCtrl*)pCtrl; _pCtrl->hjGatherEvent(usrID);//消息事件 return; } //注册回调函数 LONG COCX_kankanCtrl::RegCallBackFuncEx(void){ AFX_MANAGE_STATE(AfxGetStaticModuleState()); int _funAddr1 = (int)&hjRecCallback;//函数地址 int _funAddr2 = (int)&hjGatherCallback; m_mainDialog.pCtrl = (CWnd*)this; // TODO: Add your dispatch handler code here m_mainDialog.InitialCallBackFunctionEx( _funAddr1 , _funAddr2 );//回调函数 return 1; } //MainDialog.cpp void CMainDialog::InitialCallBackFunctionEx(int funcAddr1, int funcAddr2){ FaceRecCallbackFunc = (FaceRecCallback)funcAddr1; FaceGatherCallbackFunc = (FaceRecCallback)funcAddr2; } |