VC6下使用MFC开发视频监控控件

  总结前段时间在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
=% 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, 0000, 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, 0000, SWP_NOMOVE | SWP_NOSIZE | WS_EX_TOPMOST); 
                    current
->ModifyStyle(WS_CHILD, WS_POPUP);
                    
//移动窗口
                    current->MoveWindow(00, 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文件

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值