zoukankan      html  css  js  c++  java
  • VC6下使用MFC开发视频监控控件

    文章来源:http://blog.csdn.net/xiangyaquan/article/details/11579883

    总结前段时间在VC6下使用MFC开发视频监控控件过程中遇到的一些问题.

    1.获取控件当前所在路径,用于读取该目录下的INI配置文件

    char m_ConfigIni[512]; // 存放配置文件路径
    char szApp[512]; // 当前控件所在完整路径(带文件名)
        
    GetModuleFileName(AfxGetInstanceHandle(), szApp, MAX_PATH);//注意第一个参数,平常应用程序开发时候一般传NULL即可,ActiveX中不行,会获取不到准确的路径
    memcpy(m_ConfigIni, szApp, sizeof(szApp));
    m_ConfigIni[strrchr(m_ConfigIni, 0x5c) - m_ConfigIni+1] = 0; // 去除控件文件名    
    strcat(m_ConfigIni, "Config.ini");    
        
    char path[512];
    GetPrivateProfileString("StorePath", "RecordPath", "D:\DvrData", path, 512, m_ConfigIni);

    2.获取当前运行控件的电脑上的固定盘符列表,用于本地录像文件存放
    char m_cHardDriver[26];    // 盘符数组
    int     m_iDriverNum;         // 盘符个数  
    BOOL F_GetSystemInfo();    // 获取固定盘符列表的函数
    
    
    // 获取当前运行控件的电脑上的固定盘符列表
    BOOL CWebPlayerApp::F_GetSystemInfo()
    {
        DWORD dw=GetLogicalDriveStrings(0, NULL);
        LPTSTR pAllDrivers=new char[dw];
        ::GetLogicalDriveStrings(dw, pAllDrivers);
        LPTSTR pDriver=pAllDrivers;
        char tempDriver[26];
        DWORD DriverNum=0;
        while(pDriver[0] != 0)
        {
            tempDriver[DriverNum++] = *pDriver;
            pDriver = _tcschr(pDriver,0) + 1;    //定位到下一个盘符
        }
        
        //volume information
        TCHAR lpVolumeNameBuffer[200];
        DWORD dwVolumeSerialNumber, dwMaxComLength;
        DWORD dwFileSystemFlags;
        TCHAR lpFileSystemNameBuffer[50];
        
        DWORD HardNum=0;
        for(DWORD num=0; num < DriverNum; num++)
        {
            CString csRootPath;
            csRootPath.Format("%c%s", tempDriver[num], ":\");
            
            if(GetDriveType(csRootPath) == DRIVE_FIXED)
            {
                if(GetVolumeInformation(csRootPath,lpVolumeNameBuffer, sizeof(lpVolumeNameBuffer), &dwVolumeSerialNumber,
                    &dwMaxComLength, &dwFileSystemFlags, lpFileSystemNameBuffer, sizeof(lpFileSystemNameBuffer)))
                {            
                    this->m_cHardDriver[HardNum++]=tempDriver[num];
                }
            }        
        }
        m_iDriverNum=HardNum;    
        delete[] pAllDrivers;
    
        return TRUE;
    }

    3.视频1,4,9,16路画面切换显示

       较简单地实现,在窗体上拖16个STATIC控件(定义数组为panels),动态调整它们的位置大小即可,然后定义一个类如CPlayStatic去继承CStatic,每一个STATIC控件就由CPlayStatic管理;因为我们要在Static控件上添加鼠标,键盘事件处理,鼠标单击事件,选中该一播放面板时绘制绿色边框,可以很明显地看出当前是选中那一路视频播放窗体,同时恢复上一路选中边框为默认灰色边框;鼠标双击事件,实现视频浏览窗口的全屏功能(按多路预览-->单屏预览-->全屏-->单路浏览-->多路预览);右击菜单,对当前画面进行操作,如本地录像,语音对讲,抓图等操作;键盘事件处理,如该窗体当前正在预览按F2/F键进入全屏模式,按Esc退出全屏,恢复普通模式(需让该窗体获得焦点,处理KeyDown事件)

    void CRealPlayDlg::ArrangeWindow()
    {
            //channelNum当前需要的视频路数
        int i=0, j=0, k=-1;
        switch (channelNum)
        {
            case 1://DVR只有1个视频通道时候 只显示播放窗口1
                //show=GetDlgItem(IDC_S01);
                //show->MoveWindow(0,0,640,520);
                panels[0]->SetWindowPos(NULL,0,0,640,520,SWP_NOZORDER);
                panels[0]->ShowWindow(SW_SHOW);
                
                //隐藏其他通道播放面板
                for (i=1; i<16; i++)
                {
                    panels[i]->ShowWindow(SW_HIDE);
                }
                m_Expanded = true;
    
                break;
            case 4://DVR有4个视频通道
                panels[0]->MoveWindow(0,0,319,259);
                panels[0]->ShowWindow(SW_SHOW);
    
                panels[1]->MoveWindow(320,0,320,259);
                panels[1]->ShowWindow(SW_SHOW);
                
                panels[2]->MoveWindow(0,260,319,260);
                panels[2]->ShowWindow(SW_SHOW);
                
                panels[3]->MoveWindow(320,260,320,260);
                panels[3]->ShowWindow(SW_SHOW);
    
                for (i=4; i<16; i++)
                {
                    panels[i]->ShowWindow(SW_HIDE);
                }
                m_Expanded=false;
    
                break;
            case 9://DVR有9个视频通道
                for (i=0; i<10; i++)
                {
                    j = i % 3;
                    if (j == 0)
                    {
                        k++;
                    }
                    panels[i]->SetWindowPos(NULL,j * 214,k * 174,213,173,SWP_NOZORDER);
                    panels[i]->ShowWindow(SW_SHOW);
                }
                for (i=9; i<16; i++)
                {
                    panels[i]->ShowWindow(SW_HIDE);
                }
                m_Expanded=false;
    
                break;
            case 16://DVR有16个视频通道
                for (i=0; i<16; i++)
                {
                    j=i % 4;
                    if (j == 0)
                    {
                        k++;
                    }
                    panels[i]->SetWindowPos(NULL,j * 160,k * 130,159,129,SWP_NOZORDER);
                    panels[i]->ShowWindow(SW_SHOW);
                }
                m_Expanded=false;
    
                break;
        }
        Invalidate();//立即重绘窗体,显示效果
    }

    4.画面全屏显示 需注意播放窗口全屏后,就不能够通过GetDlgItem(int ctrlid)获取到该STATIC控件句柄了
    private:
        int         ActiveCtrlHandle;   // 当前活动播放面板的会话标识值(选中视频通道的控制句柄)
        CPlayStatic *panels[16];
            
        bool m_Expanded;                // 播放面板是否单路浏览
        bool m_enterFull;               // 是否进入全屏模式    
        BOOL m_bFullScreen;             // 全屏标记    
        WINDOWPLACEMENT _temppl;        // 全屏时保存原窗口信息,用来恢复窗口  window's placement
    
    //处理用户鼠标双击面板事件
    void CRealPlayDlg::DoDbClick(CWnd *current)
    {
        //如果已经全屏,则退出全屏模式
        if (m_bFullScreen)
        {
            //还原风格
            current->SetParent(this);
            current->ModifyStyle(WS_POPUP, WS_CHILD);
            ::SetWindowPos(current->GetSafeHwnd(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            //current->ModifyStyle(WS_CHILD, WS_CLIPSIBLINGS);//WS_CLIPCHILDREN
            //::SetWindowLong(current->m_hWnd, GWL_STYLE, style);
            //还原位置
            current->SetWindowPlacement(&_temppl);
            m_bFullScreen = FALSE;
        }
        else
        {
            //如果窗体已经进入单屏显示模式,则进入全屏模式
            if (m_Expanded)
            {
                //如果当前窗口已经打开了视频,则全屏;否则切换回到多屏显示模式
                if (ActiveCtrlHandle != -1)
                {
                    if (m_enterFull)
                    {
                        //全屏
                        //得到显示器分辨率
                        int cx=GetSystemMetrics(SM_CXSCREEN);
                        int cy=GetSystemMetrics(SM_CYSCREEN);
                        
                        //保存位置信息                    
                        current->GetWindowPlacement(&_temppl);
                        current->SetParent(NULL); // GetDesktopWindow()
                                            current->SetFocus();
                        //修改风格
                        current->SetWindowPos(&wndTopMost, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | WS_EX_TOPMOST); 
                        current->ModifyStyle(WS_CHILD, WS_POPUP);
                        //移动窗口
                        current->MoveWindow(0, 0, cx, cy);
                        
                        m_bFullScreen = TRUE;
                    }
                    else
                    {
                        ArrangeWindow();
                    }
                    m_enterFull = !m_enterFull;
                }
                else
                {
                    ArrangeWindow();
                }
            }
            else
            {
                //如果是多屏显示模式,则切换当前选中面板到单屏显示
                for (int i=0; i<16; i++)
                {
                    if (i != currentSel)
                    {
                        panels[i]->ShowWindow(SW_HIDE);
                    }
                    else
                    {
                        panels[i]->MoveWindow(0,0,640,520);    
                        m_Expanded=true;
                    }
                }
            }        
        }
        Invalidate();
    }

    5.如果ActiveX控件要使用其它第三方的ActiveX,需在InitInstance()方法中添加AfxEnableControlContainer(); 否则会造成第三方控件无法显示,控件创建出错

    6.ActiveX在网页中使用

      需使用object标签,其classid具体值可在odl文件中找到,一般在文件最后,不要弄错,否则将会造成控件无法成功创建; odl文件中包含了控件的所有属性,方法以及事件;使用如下

    <object id="ocx1" height="520" width="640" 
          classid="clsid:D55EFD59-8482-4486-9FDE-669EFAC4221B">
         </object>

    若JavaScript想调用控件的方法,可以这样ocx1.RealPlay();调用控件的RealPlay方法

     

    7.相关参考文章

    使用MFC开发ActiveX控件全过程

    ActiveX的设计

    在ActiveX控件中引入窗体技术

    如何将MFC ActiveX控件标记为安全

    将ActiveX控件标记为脚本安全和初始化安全

    ActiveX控件数字签名的实现

    ActiveX安全:改进和最佳实践[MSDN]

    JavaScript 响应 ActiveX 事件

    ActiveX组件与JavaScript交互 

    javascript脚本中定义的参数数组,如何在VC++中访问

    IExpress压缩CAB文件及制作安装程序所开发的小工具

    Web发布cab文件打包的ActiveX控件总结

    制作cab包,参考inf文件


  • 相关阅读:
    「UVA12293」 Box Game
    「CF803C」 Maximal GCD
    「CF525D」Arthur and Walls
    「CF442C」 Artem and Array
    LeetCode lcci 16.03 交点
    LeetCode 1305 两棵二叉搜索树中的所有元素
    LeetCode 1040 移动石子直到连续 II
    LeetCode 664 奇怪的打印机
    iOS UIPageViewController系统方法崩溃修复
    LeetCode 334 递增的三元子序列
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049251.html
Copyright © 2011-2022 走看看