WEB开发网      濠电姷鏁告繛鈧繛浣冲洤纾瑰┑鐘宠壘閻ょ偓銇勯幇鍫曟闁稿鍠愰妵鍕冀閵娧佲偓鎺楁⒒閸曨偄顏柡宀嬬畱铻e〒姘煎灡绗戦梻浣筋嚙濮橈箓顢氳濠€浣糕攽閻樿宸ュΔ鐘叉啞缁傚秹宕滆绾惧ジ寮堕崼娑樺缂佹宀搁弻鐔风暋閻楀牆娈楅梺璇″枓閺呯姴鐣疯ぐ鎺濇晝闁靛牆妫欓蹇旂節閻㈤潧浠﹂柛銊ョ埣楠炴劙骞橀鑲╋紱闂佽宕樼粔顔裤亹閹烘挸浜归梺缁樺灦閿曗晛螞閸曨垱鈷戦柟鑲╁仜婵″ジ鎮楀☉鎺撴珖缂侇喖顑呴鍏煎緞濡粯娅囬梻浣瑰缁诲倿寮绘繝鍥ㄦ櫇闁稿本绋撻崢鐢告煟鎼淬垻鈯曢柨姘舵煟韫囥儳绋荤紒缁樼箖缁绘繈宕橀妸褌绱濋梻浣筋嚃閸ㄤ即宕弶鎴犳殾闁绘梻鈷堥弫鍌炴煕閳锯偓閺呮瑧妲愬Ο琛℃斀闁绘劕妯婇崵鐔封攽椤旇棄鍔ら摶鐐烘煕閺囥劌澧柛娆忕箻閺屽秹宕崟顒€娅g紓浣插亾濠㈣泛顑囩粻楣冩煙鐎涙ḿ绠橀柨娑樼У椤ㄣ儵鎮欓鍕紙闂佽鍠栫紞濠傜暦閹偊妲诲┑鈩冨絻椤兘寮诲☉銏犖╅柕澶堝労閸斿绱撴担绋库偓鍝ョ矓瑜版帒鏋侀柟鍓х帛閺呮悂鏌ㄩ悤鍌涘 ---闂傚倸鍊烽悞锔锯偓绗涘厾娲煛閸涱厾顔嗛梺璺ㄥ櫐閹凤拷
开发学院软件开发VC MFC教程(13)-MFC工具条和状态栏(2) 阅读

MFC教程(13)-MFC工具条和状态栏(2)

 2007-10-04 20:11:26 来源:WEB开发网 闂傚倸鍊风欢姘缚瑜嶈灋闁圭虎鍠栫粻顖炴煥閻曞倹瀚�闂傚倸鍊风粈渚€骞夐敓鐘插瀭闁汇垹鐏氬畷鏌ユ煙閹殿喖顣奸柛搴$У閵囧嫰骞掗幋婵冨亾閻㈢ǹ纾婚柟鐐灱濡插牊绻涢崱妤冃℃繛宀婁簽缁辨捇宕掑鎵佹瀸闂佺懓鍤栭幏锟�濠电姷鏁告慨顓㈠箯閸愵喖宸濇い鎾寸箘閹规洟姊绘笟鈧ḿ褍煤閵堝悿娲Ω閳轰胶鍔﹀銈嗗笂閼冲爼鍩婇弴銏$厪闁搞儮鏅涙禒褏绱掓潏鈺佷槐闁轰焦鎹囬弫鎾绘晸閿燂拷闂傚倸鍊风欢姘缚瑜嶈灋闁圭虎鍠栫粻顖炴煥閻曞倹瀚�  闂傚倸鍊烽懗鑸电仚缂備胶绮〃鍛村煝瀹ュ鍗抽柕蹇曞У閻庮剟姊虹紒妯哄闁诲繑姘ㄩ埀顒佸嚬閸撶喎顫忓ú顏勫瀭妞ゆ洖鎳庨崜浼存⒑闁偛鑻晶顔剧磼婢跺﹦绉虹€殿喖顭锋俊姝岊槷闁稿鎹囧Λ鍐ㄢ槈濞嗗繑娈橀梻浣风串缂嶁偓濞存粠鍓熼崺鈧い鎺戝€归弳顒勬煕鐎n亷韬€规洑鍗冲鍊燁槾闁哄棴绠撻弻銊╂偆閸屾稑顏�
核心提示:void CToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler){//定义一个CCmdUI对象,CToolCmdUI派生于CCmdUICToolCmdUI state;//给CCmdUI的各个成员赋值state.m_pOther = th

void CToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
//定义一个CCmdUI对象,CToolCmdUI派生于CCmdUI
CToolCmdUI state;
//给CCmdUI的各个成员赋值
state.m_pOther = this;
//得到总的按钮数目
state.m_nIndexMax = (UINT)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
//逐个按钮进行状态更新
for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++)
{
//获取按钮状态信息
TBBUTTON button;
_GetButton(state.m_nIndex, &button);
//得到按钮的ID
state.m_nID = button.idCommand;
// ignore separators
if (!(button.fsStyle & TBSTYLE_SEP))
{
//优先让CToolBar对象处理状态更新消息
if (CWnd::OnCmdMsg(state.m_nID,
CN_UPDATE_COMMAND_UI, &state, NULL))
continue;//处理了更新消息,更新下一个按钮
//CToolBar没有处理,将发送给pTarget处理状态更新消息
//第二个参数bDisableIfNoHndler往下传
state.DoUpdate(pTarget, bDisableIfNoHndler);
}
}
//更新加到控制条中的对话框控制的状态
UpdateDialogControls(pTarget, bDisableIfNoHndler);
}

CToolBar的OnUpdateCmdUI函数完成工具条按钮的状态更新。它接受两个参数,参数1表示接收状态更新命令消息的对象,由CControlBar的函数OnIdleUpdateCmdUI传递过来,一般是边框窗口对象;参数2表示如果某条命令消息没有处理函数时,对应的用户接口对象是否被禁止。

OnUpdateCmdUI通过发送状态更新通知消息,逐个更新按钮的状态。更新消息首先让工具条对象处理,如果没有处理的话,送给边框窗口对象处理,导致状态更新命令消息的处理函数被调用,参见4.4.5节。

CStatusBar的OnUpdateCmdUI类似于此。

CDialogBar的OnUpdateCmdUI则调用了虚拟函数UpdateDialogControls来进行状态更新,CWnd提供了该函数的实现,过程类似于CToolBar的函数OnUpdateCmdUI。

菜单项的自动更新

那么,菜单项的自动更新如何实现的呢?OnInitMenuPopup在菜单项状态的自动更新中曾经被提到,其实现如下:

void CFrameWnd::OnInitMenuPopup(CMenu* pMenu, UINT, BOOL bSysMenu)
{
AfxCancelModes(m_hWnd);
if (bSysMenu)
return; // don't support system menu
ASSERT(pMenu != NULL);
// check the enabled state of various menu items
CCmdUI state;
state.m_pMenu = pMenu;
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pParentMenu == NULL);
//判断菜单是否在顶层菜单(top level menu)中弹出,如果这样
//则设置m_pParentMenu指向顶层菜单,否则m_pParentMenu
//为空,表示它是一个二级弹出菜单
HMENU hParentMenu;
//是否是浮动式的弹出菜单(floating pop up menu)
if (AfxGetThreadState()->m_hTrackingMenu == pMenu->m_hMenu)
state.m_pParentMenu = pMenu; // parent == child for tracking popup
else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)//
{
CWnd* pParent = GetTopLevelParent();
// child windows don't have menus -- need to go to the top!
//得到顶层窗口的菜单
if (pParent != NULL &&
(hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)
{
int nIndexMax = ::GetMenuItemCount(hParentMenu);
//确定顶层窗口的菜单是否包含本菜单项
for (int nIndex = 0; nIndex < nIndexMax; nIndex++)
{
if (::GetSubMenu(hParentMenu, nIndex) == pMenu->m_hMenu)
{
//顶层窗口菜单是本菜单的父菜单
state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
break;
}
}
}
}
//本菜单的菜单项(menu item)数量
state.m_nIndexMax = pMenu->GetMenuItemCount();
//对所有菜单项逐个进行状态更新
for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
state.m_nIndex++)
{
state.m_nID = pMenu->GetMenuItemID(state.m_nIndex);
if (state.m_nID == 0)
continue; // menu separator or invalid cmd - ignore it
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pMenu != NULL);
if (state.m_nID == (UINT)-1)
{
// 可能是一个popup菜单,得到其第一个子菜单项目
state.m_pSubMenu = pMenu->GetSubMenu(state.m_nIndex);
if (state.m_pSubMenu == NULL ||
(state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
state.m_nID == (UINT)-1)
{
continue; // 找不到popup菜单的子菜单项
}
//popup菜单不会被自动的禁止
state.DoUpdate(this, FALSE);
}
else
{
//正常的菜单项,若边框窗口的m_bAutoMenuEnable设置为
//TURE且菜单项非系统菜单,则自动enable/disable该菜单项
state.m_pSubMenu = NULL;
state.DoUpdate(this, m_bAutoMenuEnable && state.m_nID < 0xF000);
}
//经过菜单状态的更新处理,可能增加或删除了一些菜单项
UINT nCount = pMenu->GetMenuItemCount();
if (nCount < state.m_nIndexMax)
{
state.m_nIndex -= (state.m_nIndexMax - nCount);
while (state.m_nIndex < nCount &&
pMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
{
state.m_nIndex++;
}
}
state.m_nIndexMax = nCount;
}
}

菜单弹出之前,发送WM_INITMENUPOPUP消息,OnInitMenuPopup消息处理函数被调用,逐个更新菜单项目(menu item)的状态。程序员可以处理它们对应的状态更新消息,禁止/允许菜单项目被使用(disable/enable),在菜单项目上打钩或者取消(checked/unchecked),等等。

上一页  3 4 5 6 7 8 9 10 11  下一页

Tags:MFC 教程 MFC

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接