最近在搞视频监控项目,需要在网页上显示实时视频,于是网上找了很多资料研究如何在网页上播放视频,一种实现方式就是开发activex控件嵌入到网页中。

如下我将介绍如何开发一个可以分屏播放视频的activex控件 (部分内容也是从网上抄的,感谢各位劳动人民:))

1.      创建ActiveX工程(使用VS2008)

1.选择“文件”菜单,然后选择“新建”->“项目”。

2.在“新建项目”对话框中,如下图1所示,选择“VisualC++”分类下的“MFC”。然后选择“MFC ActiveX控件”作为项目模板。 

3.将新项目命名为“TVWallAX”,然后选择项目的保存目录,最后点击“确定”按钮,关闭“新项目”对话框,进入“MFC ActiveX控件”向导。

4.在“MFC ActiveX控件”向导中,如下图2所示,选择左侧的“控件设置”,进入控件参数设置页面。

5.在“Create control based on”下拉列表中选择“STATIC”。这表示我们使用的是一个静态控件,因为我们仅仅是显示输出而不接收输入。

6.在下面的“Additional features”的所有选项中,我们确认选中“Activates when visible”和“Flicker-free activation”这两个选项,同时确认“Has an About box dialog”选项没有被选中。

视频监控网页ActiveX视频分屏播放控件开发 _多画面播放

7.点击“Finish”按钮关闭整个“MFC ActiveX控件向导”对话框,然后向导就会为我们创建整个项目的源代码。默认情况下,向导创建的项目是使用共享MFC DLL的,这里我们需要改变这一设置。因为如果目标机器上没有安装MFC DLL,那么ActiveX控件就不会运行。我们常常看到一些网页上的ActiveX控件被显示为红色的叉叉,很多都是这个原因造成的。为了解决这个问题,我们使用静态的MFC DLL。从Visual Studio的菜单中选择“项目”->“属性”,然后切换到“配置属性”->“普通”,在配置页面中的“Use of MFC ”下拉列表中,将“use MFC in a shared DLL”切换成“Use MFC in a Static Library”就可以了。

以上步骤就完成了控件的基本框架。


2.      设计分屏控件

    接下来我们需要编写一个可以16分屏的控件,用户可以选择1分屏、4分屏、6分屏、9分屏、16分屏。如下:

视频监控网页ActiveX视频分屏播放控件开发 _视频控件_02


    设计3个类CPlayerItemCPlayerCPlayerGroup


视频监控网页ActiveX视频分屏播放控件开发 _网页播放视频_03


    CPlayerItem放在CPlayer上面,主要用来显示视频。CPlayerItem是CPlayer的子控件,比CPlayer尺寸小4个像素。

        CPlayer放在CPlayerGroup上面,主要用来显示鼠标选中播放视频窗口(CPlayer)后的矩形框。

视频监控网页ActiveX视频分屏播放控件开发 _视频控件_04

    CPlayerGroup主要用来管理16个CPlayer。


   CPlayerItem实现OnEraseBkgnd消息显示黑色背景

    BOOL CPlayerItem::OnEraseBkgnd(CDC* pDC) 

    {

        CRect rcWindow;

        GetWindowRect(&rcWindow);

        rcWindow.OffsetRect(-rcWindow.TopLeft());

        pDC->FillSolidRect(&rcWindow,RGB(0,0,0));

        return TRUE;

    }


    CPlayer实现OnEraseBkgnd消息显示用户选择当前播放窗口后的焦点框

    BOOL CPlayer::OnEraseBkgnd(CDC* pDC) 

    {

        CRect rt;

        GetClientRect(rt);

        pDC->FillSolidRect(rt,RGB(0,0,0));

        DrawEdge(pDC);

        return TRUE;

    }


    void CPlayer::DrawEdge(CDC *dc)

    {

        CRect rcWindow;

        CRect rcTemp;

        GetWindowRect(&rcWindow);

        rcWindow.OffsetRect(-rcWindow.left,-rcWindow.top);

        rcTemp=rcWindow;

        // Draw edge

        CPen cpEdge(PS_SOLID,1,m_clrEdge);

        CPen *cpTemp;

        cpTemp=dc->SelectObject(&cpEdge);

        rcTemp.DeflateRect(1,1);

        dc->Draw3dRect(&rcTemp,m_clrEdge,m_clrEdge);

        dc->SelectObject(cpTemp);

    }


3.      CPlayerGroup分屏实现

    CPlayerGroup中定义16个CPlayer,需要实现如下功能:

    1.      按用户选择的画面数显示对应个数的CPlayer

    2.      正确布局当前所有CPlayer。

    3.      当窗口尺寸变化是调整CPlayer位置及尺寸。

    4.      把用户当前鼠标操作反馈给主界面,如用户点选视频播放窗口、用户最大化视频播放窗口等。


    用户选择对应的画面数目就需要对各个CPlayer重新布局即重新计算在CPlayerGroup中对应的坐标位置。

    

    voidCPlayerGroup::RecalWndPos()

    {

       CRectrcWindow;

       GetClientRect(rcWindow);

       intnWidth;

       intnHeight;

       intnPos;

       //清空所有CRect

       for(nPos=0;nPos<PlayWinow;nPos++)

       {

              m_rcWnd[nPos]=CRect(0,0,0,0);

              m_player[nPos].rcWnd=CRect(0,0,0,0);

       }

      

       //得到最大化CRect

       m_rcWndMax=rcWindow;

 

       //计算各个显示数量时的CRect

       if(m_nCount==PlayCount1)

       {

              rcWindow.InflateRect(0,0,0,0);

              m_rcWnd[0]=rcWindow;

             

       }

       elseif(m_nCount==PlayCount4)

       {

              nWidth    =rcWindow.Width()/2;

              nHeight   =rcWindow.Height()/2;

              m_rcWnd[0]=CRect(0,0,nWidth,nHeight);

              m_rcWnd[1]=CRect(nWidth,0,rcWindow.Width(),nHeight);

              m_rcWnd[2]=CRect(0,nHeight,nWidth,rcWindow.Height());

              m_rcWnd[3]=CRect(nWidth,nHeight,rcWindow.Width(),rcWindow.Height());

       }

       elseif(m_nCount==PlayCount6)

       {

              nWidth    =rcWindow.Width()       /3;

              nHeight   =rcWindow.Height()      /3;

              m_rcWnd[0]=CRect(0,0,nWidth*2,nHeight*2);

              m_rcWnd[1]=CRect(nWidth*2,0,rcWindow.Width(),nHeight);

              m_rcWnd[2]=CRect(nWidth*2,nHeight,rcWindow.Width(),nHeight*2);

              m_rcWnd[3]=CRect(nWidth*2,nHeight*2,rcWindow.Width(),rcWindow.Height());

              m_rcWnd[4]=CRect(0,nHeight*2,nWidth,rcWindow.Height());

              m_rcWnd[5]=CRect(nWidth,nHeight*2,nWidth*2,rcWindow.Height());

             

       }

       elseif(m_nCount==PlayCount8)

       {

              nWidth    =rcWindow.Width()       /4;

              nHeight   =rcWindow.Height()      /4;

              m_rcWnd[0]=CRect(0,0,nWidth*3,nHeight*3);

              m_rcWnd[1]=CRect(nWidth*3,0,rcWindow.Width(),nHeight);

              m_rcWnd[2]=CRect(nWidth*3,nHeight,rcWindow.Width(),nHeight*2);

              m_rcWnd[3]=CRect(nWidth*3,nHeight*2,rcWindow.Width(),nHeight*3);

              m_rcWnd[4]=CRect(nWidth*3,nHeight*3,rcWindow.Width(),rcWindow.Height());

              m_rcWnd[5]=CRect(0,nHeight*3,nWidth,rcWindow.Height());

              m_rcWnd[6]=CRect(nWidth,nHeight*3,nWidth*2,rcWindow.Height());

              m_rcWnd[7]=CRect(nWidth*2,nHeight*3,nWidth*3,rcWindow.Height());

       }

       elseif(m_nCount==PlayCount9)

       {

              nWidth    =rcWindow.Width()       /3;

              nHeight   =rcWindow.Height()      /3;

              intx,y;

              for(y=0;y<3;y++)

              {

                     for(x=0;x<3;x++)

                     {

                            if(y==2)

                            {

                                   if(x==2)

                                   {    

                                         m_rcWnd[x+3*y]=CRect(x*nWidth,y*nHeight,

                                                    rcWindow.Width(),rcWindow.Height());

                                   }

                                   else

                                   {

                                          m_rcWnd[x+3*y]=CRect(x*nWidth,

                                                y*nHeight(x+1)*nWidth,rcWindow.Height());

                                   }

                            }

                            else

                            {

                                   if(x==2)

                                   {

                                          m_rcWnd[x+3*y]=CRect(x*nWidth,y*nHeight,

                                                    rcWindow.Width(),(y+1)*nHeight);

                                   }

                                   else

                                   {

                                          m_rcWnd[x+3*y]=CRect(x*nWidth,

                                                y*nHeight(x+1)*nWidth,(y+1)*nHeight);

                                   }

                            }

                     }

              }

       }

       elseif(m_nCount==PlayCount16)

       {

              nWidth    =rcWindow.Width()       /4;

              nHeight   =rcWindow.Height()      /4;

              intx,y;

              for(y=0;y<4;y++)

              {

                     for(x=0;x<4;x++)

                     {

                            if(y==3)

                            {

                                   if(x==3)

                                   {

                                          m_rcWnd[x+4*y]=CRect(x*nWidth,y*nHeight,

                                                       rcWindow.Width(),rcWindow.Height());

                                   }

                                   else

                                   {

                                          m_rcWnd[x+4*y]=CRect(x*nWidth,

                                                y*nHeight(x+1)*nWidth,rcWindow.Height());

                                   }

                            }

                            else

                            {

                                   if(x==3)

                                   {

                                          m_rcWnd[x+4*y]=CRect(x*nWidth,y*nHeight,

                                                         rcWindow.Width(),(y+1)*nHeight);

                                   }

                                   else

                                   {

                                          m_rcWnd[x+4*y]=CRect(x*nWidth,

                                                    y*nHeight(x+1)*nWidth,(y+1)*nHeight);

                                   }

                            }

                     }

              }

             

       }


    我们还需要重写CPlayerGroup 对应的OnSize(UINT nType, int cx, int cy)消息处理函数,当窗口尺寸改变后需要重新对CPlayer布局。

    最后把CPlayerGroup 类放到CTVWallAXCtrl上就完成分屏控件了。

视频监控网页ActiveX视频分屏播放控件开发 _多画面播放_05