在对话框程序中 pCmdUI->SetCheck(1)不起作用??

天地之灵 2001-08-06 10:49:26
同样的代码,在用单文档时就行,用对话框就不行了。为什么啊????
...全文
606 3 打赏 收藏 举报
写回复
3 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
蒋晟 2001-08-06
PRB: Update Command UI Handlers Do Not Work for Menu Attached to a Dialog Box
ID: Q242577


--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Visual C++, 32-bit Editions, version 6.0, used with:
The Microsoft Foundation Classes (MFC)

--------------------------------------------------------------------------------


SYMPTOMS
Changing the state (enable/disable, check/uncheck, change text) of a menu item from its command user-interface (UI) handler does not work correctly if the menu is attached to a dialog box:


void CTestDlg::OnUpdateFileExit(CCmdUI* pCmdUI)
{
pCmdUI->Enable(FALSE); //Not calling the command handler, but does not show as disabled.
pCmdUI->SetCheck(TRUE); // Does not show check mark before the text.
pCmdUI->SetRadio(TRUE); // Does not show dot before the text.
pCmdUI->SetText("Close"); //Does not change the text.
}



CAUSE
When a drop-down menu is displayed, the WM_INITMENUPOPUP message is sent prior to displaying the menu items. The MFC CFrameWnd::OnInitMenuPopup function iterates through the menu items and calls the update command UI handler for the item, if there is one. The appearance of each menu item is updated to reflect its state (enabled/disabled, checked/unchecked).

The update UI mechanism doesn't work for a dialog box-based application because CDialog has no OnInitMenuPopup handler and it uses CWnd's default handler, which does not call update command UI handlers for menu items.



RESOLUTION
Use the following steps to resolve this problem:

Add an ON_WM_INITMENUPOPUP entry to the message map:

BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
//{{AFX_MSG_MAP(CTestDlg)
........................
........................
//}}AFX_MSG_MAP

ON_WM_INITMENUPOPUP()
END_MESSAGE_MAP()



Add a OnInitMenuPopup member function to your dialog box class and copy the following code (note that this code is taken largely from CFrameWnd::OnInitMenuPopup in WinFrm.cpp):

void CTestDlg::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu)
{
ASSERT(pPopupMenu != NULL);
// Check the enabled state of various menu items.

CCmdUI state;
state.m_pMenu = pPopupMenu;
ASSERT(state.m_pOther == NULL);
ASSERT(state.m_pParentMenu == NULL);

// Determine if menu is popup in top-level menu and set m_pOther to
// it if so (m_pParentMenu == NULL indicates that it is secondary popup).
HMENU hParentMenu;
if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)
state.m_pParentMenu = pPopupMenu; // Parent == child for tracking popup.
else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)
{
CWnd* pParent = this;
// 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) == pPopupMenu->m_hMenu)
{
// When popup is found, m_pParentMenu is containing menu.
state.m_pParentMenu = CMenu::FromHandle(hParentMenu);
break;
}
}
}
}

state.m_nIndexMax = pPopupMenu->GetMenuItemCount();
for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;
state.m_nIndex++)
{
state.m_nID = pPopupMenu->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)
{
// Possibly a popup menu, route to first item of that popup.
state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);
if (state.m_pSubMenu == NULL ||
(state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||
state.m_nID == (UINT)-1)
{
continue; // First item of popup can't be routed to.
}
state.DoUpdate(this, TRUE); // Popups are never auto disabled.
}
else
{
// Normal menu item.
// Auto enable/disable if frame window has m_bAutoMenuEnable
// set and command is _not_ a system command.
state.m_pSubMenu = NULL;
state.DoUpdate(this, FALSE);
}

// Adjust for menu deletions and additions.
UINT nCount = pPopupMenu->GetMenuItemCount();
if (nCount < state.m_nIndexMax)
{
state.m_nIndex -= (state.m_nIndexMax - nCount);
while (state.m_nIndex < nCount &&
pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)
{
state.m_nIndex++;
}
}
state.m_nIndexMax = nCount;
}
}






STATUS
This behavior is by design.



MORE INFORMATION
The update command UI handler is also called from CWnd::OnCommand to make sure that command has not become disabled before routing. This is why the command handler is not called for a disabled menu item even though it is not grayed (unavailable). Menu items are not drawn to reflect their status in this case. This is the related code from the Wincore.cpp file:


// Make sure command has not become disabled before routing.
CTestCmdUI state;
state.m_nID = nID;
OnCmdMsg(nID, CN_UPDATE_COMMAND_UI, &state, NULL);
if (!state.m_bEnabled)
{
TRACE1("Warning: not executing disabled command %d\n", nID);
return TRUE;
}
Steps to Reproduce Behavior
Create a dialog-based application by using AppWizard.


Create a new menu resource and add the File and File/Exit menu items to it.


Set this menu as the menu for the dialog box in properties.


Add an UPDATE_COMMAND_UI handler for File/Exit menu item by using ClassWizard, and then add either one of the statements to the handler.


pCmdUI->Enable(FALSE); //Not calling the handler, but does not show as disabled
pCmdUI->SetCheck(TRUE); // Does not show check mark before the text.
pCmdUI->SetRadio(TRUE); // Does not show dot before the text.
pCmdUI->SetText("Close"); //Does not change the text.



Build and run the application.





REFERENCES
For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

Q141751 SAMPLE: Adding Control Bars to Dialog Boxes in MFC
© Microsoft Corporation 9/29/1999, All Rights Reserved.
Contributions by Sreedhar Pelluru, Microsoft Corporation


Additional query words: WM_INITMENUPOPUP ON_UPDATE_COMMAND_UI

Keywords : kbDlg kbMenu kbMFC KbUIDesign kbVC600 kbDSupport kbGrpMFCATL
Version : winnt:6.0
Platform : winnt
Issue type : kbprb
Technology : kbvc


Last Reviewed: February 4, 2000
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.




--------------------------------------------------------------------------------
Send feedback to MSDN.Look here for MSDN Online resources.
  • 打赏
  • 举报
回复
prog_st 2001-08-06
debug跟踪到VC的内部代码,你会看到在对话框中调用pCmdUI->SetCheck(1)和在文档框架中调用的内部代码是不一样的,对话框调用的是空代码,根本没写。
SetCheck需自己来写,我有例程,如需要请给Email
  • 打赏
  • 举报
回复
天地之灵 2001-08-06
??
  • 打赏
  • 举报
回复
发帖
VC/MFC

1.6w+

社区成员

VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
帖子事件
创建了帖子
2001-08-06 10:49
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……