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

下載本文檔

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

文檔簡介

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

2、消息的默認(rèn)處理:voidCFrameWnd:OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu) /為了說明問題,我省略了很多代碼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、(就那種帶右箭頭的菜單項),/它是不會自動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的流程就是:先向你的菜單項發(fā)一個CN_UPDATE_COMMAND_UI命令消息,讓你的菜單項來進(jìn)行顯示前的更新,這就是你在classwizard中可以看到的UPDATE_COMMADN_UI消息,你加的處理函數(shù)就是在這個時候被調(diào)用的。如果你處理了CN_UPDATE_COMMAND_UI,那么m_bEnableChanged就變成true,接下來就直接返回了。否則,如果bDisableIfNoHndler也為true,那么就向菜單項發(fā)一個CN_COMMAND消息,如果你不響應(yīng)這個消息,說明這個

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

6、的工具欄和狀態(tà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);/接下來向本線程創(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總是某個frame window的子窗口(包括子窗口的子窗口),所以它肯定能收到WM_IDLEUPDATECMDUI消息。CToolBar和CStatusBar都是從CControlBar派生的,下面是CControlBar對這個消息的處理: 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類的一個純虛函數(shù),CToolBar中對這個函數(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類,那么先讓執(zhí)行你定義的處理函數(shù)來進(jìn)行狀態(tài)更新if (CWnd:OnCmd

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

12、過了。至此,工具欄和狀態(tài)欄也能順利也進(jìn)行更了。有經(jīng)驗的朋友應(yīng)該知道,如果你在一個基于對話框的程序里模仿doc/view結(jié)構(gòu)中的方法使用UPDATE_COMMAND_UI來更新用戶界面元素的話是不會有任何效果的。其原因是一個模態(tài)對話顯示出來以后,程序就會進(jìn)入這個對話框自己的消息循環(huán)(看看DoModal的源碼就能了解這一點(diǎn)),此時不會再有WM_IDLEUPDATECMDUI被發(fā)送到這些界面元素中。下面說說這種情況下的解決辦法,你可以自己查看MFC的源碼來弄清它的原理:首先加一個頭文件afxpriv.h(其中定義了KICKIDLE消息),然后添加一個消息映射來處理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沒有基類它僅在一個CCmdTarget派生類的ON_UPDATE_COMMAND_UI處理程序中使用。當(dāng)用戶在應(yīng)用的下拉菜單時,要確定每個菜單項的顯示狀態(tài)允許存取或禁止存取。菜單命令的目標(biāo)通過實現(xiàn)一個O

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

溫馨提示

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

評論

0/150

提交評論