MFC中用戶(hù)界面元素更新原理(UPDATE_COMMAND_UI)_第1頁(yè)
MFC中用戶(hù)界面元素更新原理(UPDATE_COMMAND_UI)_第2頁(yè)
MFC中用戶(hù)界面元素更新原理(UPDATE_COMMAND_UI)_第3頁(yè)
MFC中用戶(hù)界面元素更新原理(UPDATE_COMMAND_UI)_第4頁(yè)
MFC中用戶(hù)界面元素更新原理(UPDATE_COMMAND_UI)_第5頁(yè)
全文預(yù)覽已結(jié)束

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、大家在編程的過(guò)程中一定遇到過(guò)這種情況:需要根據(jù)某個(gè)變量的值來(lái)設(shè)定菜單項(xiàng)是否被選中,設(shè)置工具欄按鈕是否被按下或者在狀態(tài)欄中顯示一些信息。MFC提供了一種機(jī)制來(lái)幫助我們完成這項(xiàng)工作:只要用ClassWizard給相應(yīng)的菜單項(xiàng)或者工具欄按鈕添加一個(gè)UPDATE_COMMAND_UI處理函數(shù),在其中用CcmdUI:SetCheck等函數(shù)來(lái)設(shè)置這些用戶(hù)界面元素的狀態(tài)就可以了。但是MFC是怎么實(shí)現(xiàn)這個(gè)功能的呢?首先讓我們來(lái)看看菜單狀態(tài)更新的實(shí)現(xiàn)方法。首先要知道,當(dāng)你點(diǎn)現(xiàn)了一個(gè)有子菜單的菜單項(xiàng)時(shí)(比如菜單欄上的“文件”),系統(tǒng)會(huì)向擁有這個(gè)菜單的窗口發(fā)送一個(gè)WM_INITMENUPOPUP,下面是MFC對(duì)這個(gè)

2、消息的默認(rèn)處理:voidCFrameWnd:OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu) /為了說(shuō)明問(wèn)題,我省略了很多代碼CCmdUI state;state.m_pMenu = pMenu;state.m_nIndexMax = pMenu-GetMenuItemCount();for (state.m_nIndex = 0; state.m_nIndex GetMenuItemID(state.m_nIndex); if (state.m_nID = (UINT)-1)/m_nID=-1表示它下面還有popup menu

3、(就那種帶右箭頭的菜單項(xiàng)),/它是不會(huì)自動(dòng)deisable的elsestate.m_pSubMenu = NULL;state.DoUpdate(this, m_bAutoMenuEnable & state.m_nID OnCmdMsg(m_nID,CN_UPDATE_COMMAND_UI,this, NULL);if (bDisableIfNoHndler & !m_bEnableChanged)AFX_CMDHANDLERINFO info;info.pTarget = NULL;BOOL bHandler = pTarget-OnCmdMsg(m_nID, CN_COMMAND, th

4、is, &info);Enable(bHandler);return bResult;DoUpdate的流程就是:先向你的菜單項(xiàng)發(fā)一個(gè)CN_UPDATE_COMMAND_UI命令消息,讓你的菜單項(xiàng)來(lái)進(jìn)行顯示前的更新,這就是你在classwizard中可以看到的UPDATE_COMMADN_UI消息,你加的處理函數(shù)就是在這個(gè)時(shí)候被調(diào)用的。如果你處理了CN_UPDATE_COMMAND_UI,那么m_bEnableChanged就變成true,接下來(lái)就直接返回了。否則,如果bDisableIfNoHndler也為true,那么就向菜單項(xiàng)發(fā)一個(gè)CN_COMMAND消息,如果你不響應(yīng)這個(gè)消息,說(shuō)明這個(gè)

5、菜單項(xiàng)還沒(méi)有處理函數(shù),那么,bnHandler就是flase,然后Enable(false)就把你的菜單項(xiàng)變灰了。注意在CFrameWnd:OnInitMenuPopup中調(diào)用DoUpdate時(shí)的參數(shù)是m_bAutoMenuEnable & state.m_nID0xF000,這說(shuō)如果你一開(kāi)始就把m_bAutoMenuEnable設(shè)為false的話,實(shí)際上就關(guān)閉了MFC自動(dòng)diable沒(méi)有處理函數(shù)的菜單項(xiàng)的功能。工具欄的更新用的是另外一套方法。首先需要知道當(dāng)你的的程序變得空閑,沒(méi)有消息需要處理的時(shí)候,MFC會(huì)調(diào)用CWinApp:OnIdle函數(shù)利用這個(gè)時(shí)間進(jìn)行一些特殊的工作,其中之一就是更新你

6、的工具欄和狀態(tài)欄。下面來(lái)看相關(guān)的代碼: BOOL CWinThread:OnIdle(LONG lCount)if (lCount m_hWnd != NULL & pMainWnd-IsWindowVisible()AfxCallWndProc(pMainWnd, pMainWnd-m_hWnd, WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0); pMainWnd-SendMessageToDescendants(WM_IDLEUPDATECMDUI,(WPARAM)TRUE, 0, TRUE, TRUE);/接下來(lái)向本線程創(chuàng)建的所有frame window發(fā)送WM

7、_IDLEUPDATECMDUI消息 AFX_MODULE_THREAD_STATE* pState=_AFX_CMDTARGET_GETSTATE()-m_thread;CFrameWnd* pFrameWnd = pState-m_frameList;while (pFrameWnd != NULL)if(pFrameWnd-IsWindowVisible()|pFrameWnd-m_nShowDelay = 0) AfxCallWndProc(pFrameWnd, pFrameWnd-m_hWnd,WM_IDLEUPDATECMDUI, (WPARAM)TRUE, 0);pFrameWn

8、d-SendMessageToDescendants(WM_IDLEUPDATECMDUI,(WPARAM)TRUE, 0, TRUE, TRUE);你的toolbar或者statusbar總是某個(gè)frame window的子窗口(包括子窗口的子窗口),所以它肯定能收到WM_IDLEUPDATECMDUI消息。CToolBar和CStatusBar都是從CControlBar派生的,下面是CControlBar對(duì)這個(gè)消息的處理: LRESULT CControlBar:OnIdleUpdateCmdUI(WPARAM wParam, LPARAM) if (GetStyle() & WS_VI

9、SIBLE) )/將pTarget指向離this最近的父frame windowCFrameWnd* pTarget = (CFrameWnd*)GetOwner();if (pTarget = NULL | !pTarget-IsFrameWnd() pTarget = GetParentFrame();/調(diào)用虛成員函數(shù)OnUpdateCmdUIif (pTarget != NULL)OnUpdateCmdUI(pTarget, (BOOL)wParam);return 0L;OnUpdateCmdUI是CControlBar類(lèi)的一個(gè)純虛函數(shù),CToolBar中對(duì)這個(gè)函數(shù)進(jìn)行了定義:void

10、 CToolBar:OnUpdateCmdUI(CFrameWnd* pTarget, BOOLbDisableIfNoHndler)CToolCmdUI state;state.m_pOther = this;state.m_nIndexMax = DefWindowProc(TB_BUTTONCOUNT, 0, 0); /工具欄上的按鈕數(shù)for (state.m_nIndex=0; state.m_nIndex state.m_nIndexMax; state.m_nIndex+)/如果你派生了自己的CToolBar類(lèi),那么先讓執(zhí)行你定義的處理函數(shù)來(lái)進(jìn)行狀態(tài)更新if (CWnd:OnCmd

11、Msg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL)continue;/如果toolbar沒(méi)有更新自己,讓pTarget(也就是離它最近的父frame window)來(lái)更新它。比如對(duì)于MFC自動(dòng)生成的SDI框架來(lái)說(shuō),pTarget會(huì)指向CMainFrame state.DoUpdate(pTarget, bDisableIfNoHndler); /如果CToolBar中有用戶(hù)創(chuàng)建的控件,也一起更新UpdateDialogControls(pTarget, bDisableIfNoHndler);CCmdUI:DoUpdate的代碼上面已經(jīng)列出

12、過(guò)了。至此,工具欄和狀態(tài)欄也能順利也進(jìn)行更了。有經(jīng)驗(yàn)的朋友應(yīng)該知道,如果你在一個(gè)基于對(duì)話框的程序里模仿doc/view結(jié)構(gòu)中的方法使用UPDATE_COMMAND_UI來(lái)更新用戶(hù)界面元素的話是不會(huì)有任何效果的。其原因是一個(gè)模態(tài)對(duì)話顯示出來(lái)以后,程序就會(huì)進(jìn)入這個(gè)對(duì)話框自己的消息循環(huán)(看看DoModal的源碼就能了解這一點(diǎn)),此時(shí)不會(huì)再有WM_IDLEUPDATECMDUI被發(fā)送到這些界面元素中。下面說(shuō)說(shuō)這種情況下的解決辦法,你可以自己查看MFC的源碼來(lái)弄清它的原理:首先加一個(gè)頭文件afxpriv.h(其中定義了KICKIDLE消息),然后添加一個(gè)消息映射來(lái)處理WM_KICKIDLE消息:ON_M

13、ESSAGE(WM_KICKIDLE,OnKickIdle)。其中OnKickIdle定義如下: LRESULT CTabDialog:OnKickIdle(WPARAM wp, LPARAM lCount)UpdateDialogControls(this, TRUE);return 0;完成這些工作以后,你就可以順利地使用UPDATE_COMMAND_UI機(jī)制了。 -CCmdUICCmdUI沒(méi)有基類(lèi)它僅在一個(gè)CCmdTarget派生類(lèi)的ON_UPDATE_COMMAND_UI處理程序中使用。當(dāng)用戶(hù)在應(yīng)用的下拉菜單時(shí),要確定每個(gè)菜單項(xiàng)的顯示狀態(tài)允許存取或禁止存取。菜單命令的目標(biāo)通過(guò)實(shí)現(xiàn)一個(gè)O

14、N_UPDATE_COMMAND_UI處理來(lái)提供這些信息??梢允褂肅lassWizard來(lái)瀏覽定位應(yīng)用中的命令用戶(hù)接口對(duì)象,然后為它建立一個(gè)消息映射入口,并為每個(gè)消息處理函數(shù)提供函數(shù)原型。當(dāng)菜單被下拉時(shí),框架搜索并調(diào)用每個(gè)ON_UPDATE_COMMAND_UI處理,每個(gè)處理調(diào)用Enable和Check之類(lèi)的成員函數(shù),相應(yīng)地,框架就可以正確地顯示每個(gè)菜單項(xiàng)了。菜單項(xiàng)可以用控件條按鈕或者其它的命令用戶(hù)接口對(duì)象替換,而在ON_UPDATE_COMMAND_UI處理中的代碼不需要改動(dòng)。下表列出了各種命令用戶(hù)接口上的CCmdGUI的成員函數(shù)。用戶(hù)接口項(xiàng) Enable SetCheck SetRadio SetText菜單項(xiàng) 允許或禁止存取該項(xiàng) 選中()或未選中 選中(有黑點(diǎn)) 設(shè)置項(xiàng)的文本工具條按鈕 允許或禁止存取該項(xiàng) 選中、未選中或不定 (不可用) 與SetCheck相同狀態(tài)條狀態(tài)提示 文本可見(jiàn)或不可

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論