總結前段時間在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.相關參考文章
javascript腳本中定義的參數數組,如何在VC++中訪問
作者:peterzb(個人開發歷程知識庫 -博客園)
出處:http://peterzb.cnblogs.com/
文章版權歸本人所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。