• 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文件


  • 相关阅读:
    mysql/mariadb学习记录——查询2
    mysql/mariadb学习记录——查询
    touchSwipe 上下左右滑动,二指缩放 效果不好。
    c# 调用c++ 使用指针传递的时候
    c# 调用 matlab 引发初始化错误 异常
    创建非主键唯一约束
    sql 中 如果添加 时间戳 字段 timestamp
    JS frame 跨域 传值
    VS 附加进程调试
    Aspose.words 替换字符 操作
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049251.html
Copyright © 2020-2023  润新知