?
1、MFC單文檔多文檔程序 不讓MFC來更新菜單
1 在CMainFrame::CMainFrame中添加 2 3 m_bAutoMenuEnable = FALSE;
標題欄圖標的更改
1 // cuihao, 標題欄圖標; 2 CCameraMonitorApp *pApp = (CCameraMonitorApp* )AfxGetApp(); 3 HICON hIcon = pApp-> LoadIcon(IDI_ICON3); 4 SetIcon(hIcon, TRUE); 5 SetIcon(hIcon, FALSE);
?
?------------------------------------------------------------------------------------------------------------------------
使菜單可用/不可用,?通過菜單項的位置來讓菜單可用或不可用
1 GetMenu()->GetSubMenu( 2 )->EnableMenuItem( 1 , MF_BYPOSITION | MF_GRAYED | MF_DISABLED); 2 3 GetMenu()->GetSubMenu( 3 )->EnableMenuItem( 2 , MF_BYPOSITION | MF_ENABLED);
?
?
更改菜單項的Caption或者ID
如果只想要修改菜單的文字則ID要和原來的一樣,原來的菜單ID也為ID_OF_MENUITEM, 修改后的caption為strNewStringCaption
1 GetMenu()->GetSubMenu( 1 )->ModifyMenu( 2 , MF_BYPOSITION | MF_STRING, ID_OF_MENUITEM, strNewStringCaption);
?
??------------------------------------------------------------------------------------------------------------------------
?修改MFC單文檔多文檔的窗口標題欄
1 BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) 2 { 3 if ( ! CFrameWnd::PreCreateWindow(cs) ) 4 return FALSE; 5 // TODO: 在此處通過修改 6 // cuihao, CREATESTRUCT cs 來修改窗口類或樣式 7 cs.style &= ~ FWS_ADDTOTITLE; 8 cs.lpszName = _T( " 視頻監控 " ); 9 10 return TRUE; 11 } 12 13
?
MFC單文檔多文檔,讓程序一開始最大化運行
1 void CMainFrame::ActivateFrame( int nCmdShow) 2 { 3 // TODO: 在此添加專用代碼和/或調用基類; 4 5 nCmdShow = SW_SHOWMAXIMIZED; // cuihao,最大化運行; 6 7 CFrameWnd::ActivateFrame(nCmdShow); 8 }
?
??------------------------------------------------------------------------------------------------------------------------
?
?
?如果MFC文檔有多個view類,那么獲取當前有焦點的view類
1 CView* CFrameWnd::GetActiveView( ) const ;
?
如果要獲取指定的view類的指針,那么可以:先獲得該view類的句柄,然后通過句柄獲得指針
1
CWnd* FromHandle(HWND hWnd);
?
如果要遍歷所有view類,如下
1 virtual POSITION GetFirstViewPosition() const ; 2 virtual CView* GetNextView(POSITION& rPosition) const ;
?
??------------------------------------------------------------------------------------------------------------------------
?改變窗口的位置、大小,Z序
SetWindowPos
eg. ?
//最大化視頻;
1 void CMainFrame::OnMenuMaxvideo() 2 { 3 // TODO: 在此添加命令處理程序代碼; 4 5 static bool bModify[MAX_CAMERAS_NUM] = { false }; 6 7 int nCode = CCameraMonitorView::m_nCurrentCode; 8 9 CCameraMonitorView* pView = NULL; 10 pView = (CCameraMonitorView* )FromHandle(CCameraMonitorView::m_hWndCameraMonitor); 11 if (NULL == pView) 12 { 13 AfxMessageBox(_T( " pView is NULL, CMainFrame::OnMenuMaxvideo " )); 14 return ; 15 } 16 17 // 最大化; 18 if ( false == bModify[nCode]) 19 { 20 CRect rectMax; 21 pView->GetWindowRect(& rectMax); 22 int x = rectMax.TopLeft().x; 23 int y = rectMax.TopLeft().y; 24 int cx = rectMax.Width(); 25 int cy = rectMax.Height(); 26 BOOL ret = pView->GetDlgItem(videoPicturesCtrl[nCode])->SetWindowPos(&wndTopMost, 0 , 0 , cx, cy, SWP_SHOWWINDOW | SWP_NOZORDER); 27 28 HideAllNonActiveWindows(nCode, true ); // 隱藏其他視頻窗口,如果不隱藏則最大化視頻顯示時其他視頻窗口會被刷出來,很難看; 29 30 } 31 32 // 還原; 33 else 34 { 35 int x = CCameraMonitorView::m_rectVideos[nCode].left; 36 int y = CCameraMonitorView::m_rectVideos[nCode].top; 37 int cx = CCameraMonitorView::m_rectVideos[nCode].Width(); 38 int cy = CCameraMonitorView::m_rectVideos[nCode].Height(); 39 BOOL ret = pView->GetDlgItem(videoPicturesCtrl[nCode])->SetWindowPos(NULL, x, y, cx, cy, SWP_NOZORDER | SWP_SHOWWINDOW); 40 41 HideAllNonActiveWindows(nCode, false ); 42 } 43 44 bModify[nCode] = ! bModify[nCode]; 45 Invalidate(TRUE); // 刷新窗口; 46 47 }
?
??------------------------------------------------------------------------------------------------------------------------
?Windows自定義消息函數
afx_msg LRESULT OnUpdateMenuCommand(WPARAM wParam, LPARAM lParam);
?
其中WPARAM為unsigned int, ?LPARAM為long
與之前相關的給窗口發送消息的函數為SendMessage
SendMessage( HWND hWnd, // 目的窗口句柄 UINT nMessageID, // 消息 WPARAM wParam, // unsigned int 參數 LPARAM lParam // long類型參數 )
?
其中nMessageID的定義為: #define MY_MESSAGE ?WM_USER + ?一個數字
WM_USER的定義為: #define ?WM_USER ?0X0400, 加上一個數字就能避免和系統消息沖突
?
添加消息映射
ON_MESSAGE(UPDATEUI_MESSAGE, CMainFrame::OnUpdateMenuCommand)
?
?
?有時候在不同的情況下要讓目的窗口發生不同的變化,這個時候可以使用wParam和lParam這兩個參數來傳遞給目的窗口不同的參數,
這里有個實例就是讓wParam中的某些位的區別 以及 lParam的區別來區分不同的消息類型,從而讓目的窗口發生不同的變化
eg.
1 ///////////////////////////////////////////////////////////////////////////////////////////// 2 // 3 // 說明:::SendMessage(窗口句柄, 消息, wParam, lParam) 4 // wParam == 0 :線程失敗,沒有進入實質的采集過程; 5 // wParam == 0x****0001, lParam == 0x0000 00001 :線程成功,進入實質的采集過程; 6 // wParam == 0x****0001, lParam == 0x0000 0000 :線程成功,進入實質采集過程,但是創建視頻文件寫入器失敗 7 // wParam == 0x****0001, lParam == 0x0000 00002 :線程成功,寫視頻異常; 8 // wParam == 0x****0002, lParam == 0x0000 00000 : 9 // 0x**** == code 10 ///////////////////////////////////////////////////////////////////////////////////////////// 11 12 13 if ( false == camera.OpenCamera(code, false , width, height)) 14 { 15 wParam = (code << 16 ) & 0xffff0000 ; 16 wParam |= 0x00000000 ; 17 18 ::SendMessage(hViewWnd, UPDATEUI_MESSAGE, wParam, 0 ); // 失敗,發送消息給主線程; 19 ::SendMessage(hWndMainFrame, UPDATEUI_MESSAGE, wParam, 0 ); 20 21 g_bIsRunningArr[min(code, MAX_CAMERAS_NUM)] = false ; 22 CString strInfo(_T( " 打開攝像頭 " )); 23 strInfo += chCode; 24 strInfo += _T( " 失敗! " ); 25 MessageBox(NULL, strInfo, _T( " 提示信息 " ), MB_OKCANCEL); 26 return 0 ; 27 } 28 29 30 31 32 33 34 35 36 LRESULT CMainFrame::OnUpdateMenuCommand( WPARAM wParam, LPARAM lParam ) 37 { 38 ///////////////////////////////////////////////////////////////////////////////////////////// 39 // 40 // 說明:::SendMessage(窗口句柄, 消息, wParam, lParam) 41 // wParam == 0 :線程失敗,沒有進入實質的采集過程; 42 // wParam == 0x****0001, lParam == 0x0000 00001 :線程成功,進入實質的采集過程; 43 // wParam == 0x****0001, lParam == 0x0000 0000 :線程成功,進入實質采集過程,但是創建視頻文件寫入器失敗 44 // wParam == 0x****0001, lParam == 0x0000 00002 :線程成功,寫視頻異常; 45 // wParam == 0x****0002, lParam == 0x0000 00000 :線程退出 46 // 0x**** == code 47 // wParam == 111(十進制), lParam == 0 :開始采集按鈕事件 出錯; 48 ///////////////////////////////////////////////////////////////////////////////////////////// 49 50 WORD wLowState = 0 ; // 狀態代碼; 51 WORD wHICode = 0 ; // 攝像頭ID; 52 53 wLowState = wParam & 0x0000ffff ; // 取低位兩個字節; 54 wHICode = (wParam >> 16 ) & 0x0000ffff ; // 取高位兩個字節; 55 56 const WCHAR strStartCapture[] = _T( " 開始采集 " ); 57 const WCHAR strEndCapture[] = _T( " 停止采集 " ); 58 const WCHAR strStartRecord[] = _T( " 開始錄像 " ); 59 const WCHAR strEndRecord[] = _T( " 停止錄像 " ); 60 61 int nCode = CCameraMonitorView::m_nCurrentCode; // 獲得當前攝像頭code; 62 63 // 獲得【視頻】菜單; 64 CMenu *pMenuVideo = NULL; 65 pMenuVideo = GetMenu()->GetSubMenu( 2 ); 66 if (pMenuVideo == NULL) 67 { 68 AfxMessageBox(_T( " pMenuVideo is NULL, CMainFrame::OnUpdateMenuCommand " )); 69 return - 1 ; 70 } 71 // 如果當前攝像頭code == 返回的攝像頭code,則立即更新UI 72 if (nCode == wHICode && nCode != 0 ) 73 { 74 // 線程在進入采集while之前失敗; 75 if ( 0 == wParam && 0 == lParam) 76 { 77 // 【開始采集】按鈕可用,caption為【開始采集】,【開始錄像】按鈕不可用; 78 pMenuVideo->ModifyMenu( 0 , MF_BYPOSITION, ID_MENU_STARTCAPTURE, strStartCapture); 79 pMenuVideo->EnableMenuItem( 0 , MF_BYPOSITION | MF_ENABLED); 80 81 pMenuVideo->EnableMenuItem( 1 , MF_BYPOSITION | MF_GRAYED | MF_DISABLED); 82 } 83 84 // 線程進入實質的采集過程; 85 else if ( 1 == wLowState && 1 == lParam) 86 { 87 // 【開始采集】按鈕可用,caption為【停止采集】,【開始錄像】按鈕可用,caption為【開始錄像】; 88 89 pMenuVideo->ModifyMenu( 0 , MF_BYPOSITION | MF_STRING, ID_MENU_STARTCAPTURE, strEndCapture); 90 pMenuVideo->EnableMenuItem( 0 , MF_BYPOSITION | MF_ENABLED); 91 92 pMenuVideo->ModifyMenu( 1 , MF_BYPOSITION | MF_STRING, ID_MENU_RECORD, strStartRecord); 93 pMenuVideo->EnableMenuItem( 1 , MF_BYPOSITION | MF_ENABLED); 94 95 } 96 97 // 進入實質采集過程,但是創建視頻寫入器失敗; 98 else if ( 1 == wLowState && 0 == lParam) 99 { 100 // 【開始采集】按鈕不變, 【開始錄像】按鈕caption變為【開始錄像】,可用; 101 pMenuVideo->ModifyMenu( 1 , MF_BYPOSITION | MF_STRING, ID_MENU_RECORD, strStartRecord); 102 pMenuVideo->EnableMenuItem( 1 , MF_ENABLED); 103 } 104 105 // 進入實質采集過程,寫視頻文件異常; 106 else if ( 1 == wLowState && 2 == lParam) 107 { 108 // 【開始采集】按鈕不變, 【開始錄像】按鈕caption變為【開始錄像】,可用; 109 pMenuVideo->ModifyMenu( 1 , MF_BYPOSITION | MF_STRING, ID_MENU_RECORD, strStartRecord); 110 pMenuVideo->EnableMenuItem( 1 , MF_ENABLED); 111 } 112 113 // 線程退出; 114 else if ( 2 == wLowState && 0 == lParam) 115 { 116 // 【開始采集】按鈕變味【開始采集】, 【開始錄像】不可用; 122 } 123 124 } 125 126 // 開始采集 出錯; 127 if ( 111 == wParam && 0 == lParam) 128 { 129 // 【開始采集】可用; 130 pMenuVideo->EnableMenuItem( 0 , MF_BYPOSITION | MF_ENABLED); 131 } 132 else if ( 112 == wParam && 0 == lParam) 133 { 134 // GetDlgItem(IDC_BTN_RECORD)->EnableWindow(TRUE); 135 // SetDlgItemText(IDC_BTN_RECORD, _T("停止錄像")); 136 pMenuVideo->EnableMenuItem( 1 , MF_ENABLED); 137 pMenuVideo->ModifyMenu( 1 , MF_BYPOSITION | MF_STRING, ID_MENU_RECORD, strEndRecord); 138 } 139 else if ( 113 == wParam && 0 == lParam) 140 { 141 153 } 154 else if ( 114 == wParam && 0 == lParam) 155 {
} 166 else if ( 115 == wParam && 0 == lParam) 167 {
} 171 else if ( 116 == wParam && 0 == lParam) 172 {
} 176 else if ( 117 == wParam && 0 == lParam) 177 { 179 } 181 182 return 0 ; 183 }
?
?
?
??------------------------------------------------------------------------------------------------------------------------
?
?------------------------------------------------------------------------------------------------------------------------
?【打開文件】對話框
GetModuleFileName : ?獲得包含路徑的全文件名稱
PathRemoveFileSpec: 獲得去掉文加名及后綴的文件路徑
上面這兩個函數可能需要頭文件<shlapi.h>
?
?
1 void CMainFrame::OnMenuOpenfile() 2 { 3 // TODO: 在此添加命令處理程序代碼; 4 5 static TCHAR szPath[MAX_PATH - 1 ] = { 0 }; 6 static bool bOnlyOnce = false ; 7 if ( false == bOnlyOnce) 8 { 9 bOnlyOnce = true ; 10 GetModuleFileName(NULL, szPath, sizeof (szPath)); 11 PathRemoveFileSpec(szPath); 12 } 13 14 CString strFileName; 15 16 CFileDialog dlg(TRUE); 17 dlg.m_ofn.lpstrTitle = _T( " 打開avi視頻文件 " ); 18 dlg.m_ofn.lpstrFilter = _T( " Avi Files(*.avi)\0 *.avi\0All Files(*.*)\0 *.*\0\0 " ); // 文件過濾器 19 dlg.m_ofn.lpstrInitialDir = szPath; 20 21 if (IDOK == dlg.DoModal()) 22 { 23 strFileName = dlg.GetPathName(); 24 25 // CString 2 TCHAR* 26 int iLen = strFileName.GetLength(); 27 memset(szPath, 0 , sizeof (szPath)); 28 lstrcpy(szPath, strFileName.GetBuffer(iLen)); // 得到szPath; 29 strFileName.ReleaseBuffer(); 30 31 // CString 2 char* 32 char * pVideoFileName = ( char *)malloc((iLen * 2 + 1 ) * sizeof ( char )); // CString的長度中漢字算一個長度; 33 memset(pVideoFileName, 0 , 2 * iLen + 1 ); 34 USES_CONVERSION; 35 strcpy((LPSTR)pVideoFileName,OLE2A(strFileName.LockBuffer())); // 得到pVideoFileName; 36 37 if (NULL == pVideoFileName) 38 { 39 assert(pVideoFileName != NULL); 40 AfxMessageBox(_T( " 視頻文件打開失敗! " )); 41 return ; 42 } 43 else 44 { 45 PalyVideo(pVideoFileName); // 播放視頻; 46 free(pVideoFileName); 47 } 48 49 50 PathRemoveFileSpec(szPath); // 去掉文件名只保留路徑; 51 } 52 }
?
?
?------------------------------------------------------------------------------------------------------------------------
?MFC靜態控件默認不響應鍵盤鼠標事件,需要激活SS_NOTIFY,可在控件屬性里或者用該代碼如下
//使Picture控件響應鼠標事件
GetDlgItem(IDC_VIDEO0)->ModifyStyle( 0 , SS_NOTIFY); GetDlgItem(IDC_VIDEO1) ->ModifyStyle( 0 , SS_NOTIFY); GetDlgItem(IDC_VIDEO2) ->ModifyStyle( 0 , SS_NOTIFY);
?
??
?------------------------------------------------------------------------------------------------------------------------
?獲得桌面坐標 GetWindowRect和 客戶區坐標GetClientRect
兩者的區別僅僅是起點不同,桌面坐標的起點根據實際情況來,客戶區的坐標起點是(0, 0),
他們之間通過ClientToScreen和ScreenToClient互相轉換
?
?
?------------------------------------------------------------------------------------------------------------------------
?開啟子線程_begingthreadex
函數原型
函數原型:
unsigned long _beginthreadex( void * security, unsigned stack_size, unsigned ( __stdcall *start_address )( void * ), void *arglist, /* 這個就是傳給線程函數的參數的指針 */ unsigned initflag, unsigned *thrdaddr );
?
線程函數
UINT __stdcall ShowThread(
void
*p)
?
eg.
1 UINT retValue = _beginthreadex(NULL, 2 0 , 3 ShowThread, // 線程函數 4 pParams, // 參數 5 0 , 6 &nThreadID // 線程ID 7 ); 8 9 10 if (INVALID_HANDLE_VALUE == (HANDLE)retValue) 11 { 12 MessageBox(_T( " 線程創建可能失敗!INVALID_HANDLE_VALUE " )); 13 delete pParams; 14 pParams = NULL; 15 return false ; 16 } 17 else if (NULL == (HANDLE)retValue) 18 { 19 MessageBox(_T( " 線程創建可能失敗!NULL " )); 20 delete pParams; 21 pParams = NULL; 22 return false ; 23 } 24 25 return true ;
?
?
?------------------------------------------------------------------------------------------------------------------------
?TreeView的使用
MFC單文檔程序中:選擇資源管理器風格, VIEW類的父類選擇CTreeView,則生成的程序中有個CLeftView,
CLeftView在程序中動態生成,因此取得該控件的方法是 ?CTreeCtrl& treeCtrl = GetTreeCtrl();
eg.
?
1 void CLeftView::UpdateCameraList() 2 { 3 m_hWndLeftView = m_hWnd; 4 5 CTreeCtrl& treeCtrl = GetTreeCtrl(); 6 7 treeCtrl.DeleteAllItems(); 8 9 CImageList Cil1, Cil2; 10 CCameraMonitorApp *pApp = (CCameraMonitorApp* )AfxGetApp(); 11 Cil1.Create( 16 , 16 , ILC_COLOR, 2 , 2 ); 12 Cil1.Add(pApp-> LoadIcon(IDI_ICON1)); 13 Cil1.Add(pApp-> LoadIcon(IDI_ICON2)); 14 15 treeCtrl.SetImageList(& Cil1, TVSIL_NORMAL); 16 17 DWORD dwStyles = GetWindowLong(m_hWnd, GWL_STYLE); 18 dwStyles |= TVS_EDITLABELS | TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT; 19 SetWindowLong(m_hWnd, GWL_STYLE, dwStyles); 20 21 TCHAR* arrFather[] = {_T( " A棟 " ), _T( " B棟 " ), _T( " C棟 " ), _T( " D棟 " ), _T( " E棟 " ), _T( " F棟 " ), _T( " G棟 " ), _T( " H棟 " ), _T( " I棟 " )}; 22 TCHAR* arrSon[ 3 ][ 2 ] = {{_T( " 11 " ), _T( " 12 " )}, {_T( " 21 " ), _T( " 22 " )}, {_T( " 31 " ), _T( " 32 " )}}; 25 26 int i = 0 ; 27 int j = 0 ; 28 29 HTREEITEM hRoot, hCur; 30 TV_INSERTSTRUCT TCItem; 31 TCItem.hParent = TVI_ROOT; 32 TCItem.hInsertAfter = TVI_LAST; 33 TCItem.item.pszText = _T( " 攝像頭列表 " ); 34 TCItem.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE; 35 TCItem.item.lParam = 0 ; 36 TCItem.item.iImage = 0 ; 37 TCItem.item.iSelectedImage = 1 ; 38 39 hRoot = treeCtrl.InsertItem(&TCItem); // 根節點; 40 41 CCamerasInfo::GetCameraCountNames(); // 獲得攝像頭數量和名字; 42 WCHAR wcName[ 512 ] = { 0 }; 43 44 for (i = 0 ; i < CCamerasInfo::s_nCameraCount; ++ i) 45 { 46 TCItem.hParent = hRoot; 47 TCItem.item.pszText = arrFather[i]; 48 TCItem.item.lParam = (i + 1 ) * 10 ; 49 hCur = treeCtrl.InsertItem(& TCItem); 50 for (j = 0 ; j < 1 ; ++ j) 51 { 52 TCItem.hParent = hCur; 53 54 // char* 轉 wchar_t* 55 MultiByteToWideChar(CP_ACP, 0 , (LPCSTR)CCamerasInfo::s_chCameraNameArray[i], 56 sizeof (CCamerasInfo::s_chCameraNameArray[i]), wcName, sizeof (wcName)); 57 58 TCItem.item.pszText = wcName; 59 TCItem.item.lParam = (i + 1 ) * 10 + (j + 1 ); 60 treeCtrl.InsertItem(& TCItem); 61 } 62 63 treeCtrl.Expand(hCur, TVE_EXPAND); 64 } 65 treeCtrl.Expand(hRoot, TVE_EXPAND); 66 67 }
?
?
?------------------------------------------------------------------------------------------------------------------------
?
屏幕坐標至客戶區域坐標
1 // Picture0控件雙擊事件; 2 void CCameraMonitorView::OnStnDblclickVideo0() 3 { 4 // TODO: 在此添加控件通知處理程序代碼; 5 6 CRect rect; 7 GetDlgItem(IDC_VIDEO0)->GetWindowRect(& rect); 8 ScreenToClient (& rect);; 9 10 11 CRect rect2; 12 GetDlgItem(IDC_VIDEO0)->GetClientRect(& rect2); 13 GetDlgItem(IDC_VIDEO0)-> MapWindowPoints (FromHandle(m_hWnd), rect2); 14 15 16 }
?
?
?
?
??
?
??
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
