MFC 功能区:CView::OnUpdate 中的 RemoveAllSubItems() 导致访问冲突 (VS2008)

Posted

技术标签:

【中文标题】MFC 功能区:CView::OnUpdate 中的 RemoveAllSubItems() 导致访问冲突 (VS2008)【英文标题】:MFC Ribbon: RemoveAllSubItems() in CView::OnUpdate leads to access violation (VS2008) 【发布时间】:2014-05-29 15:03:18 【问题描述】:

要重现该行为,请使用 Ribbon(CMyView 作为视图类名称)启动一个新的 MFC Outlook 样式项目。

假设我要修改CMFCRibbonButton 的菜单,例如打印命令的子项,为此,我想先修改RemoveAllSubItems()

将此添加为 MainFrm.h 中的公共成员:

CMFCRibbonButton *m_pBtnPrint;

将此添加到 MainFrm.cpp 中的InitializeRibbon() 成员函数中:

CMFCRibbonButton* pBtnPrint = new CMFCRibbonButton(ID_FILE_PRINT, strTemp, 6, 6);
// store the pointer to the button to be used in CMyView class
m_pBtnPrint = pBtnPrint;   

CMyView::OnUpdate() 中添加此代码:

CMFCRibbonButton *pBtnPrint = ((CMainFrame*)AfxGetMainWnd())->m_pBtnPrint;
if (pBtnPrint) pBtnPrint->RemoveAllSubItems();  

我最好的猜测是打印命令的框架内部复制出了点问题,例如用于快速访问工具栏。我想知道我是否在这里遗漏了什么。在 CMainFrame 中创建功能区栏后是否禁止修改菜单?

编辑:这显然与 m_pBtnPrint 被无效无关,例如在LoadFrame() 之后。如果您使用CMFCRibbonBar::FindByID() 动态检索 pBtnPrint,它也会崩溃:

CMFCRibbonBar *pRibbon = ((CMDIFrameWndEx*) AfxGetMainWnd())->GetRibbonBar();
CMFCRibbonButton *pBtnPrint = DYNAMIC_DOWNCAST(CMFCRibbonButton, pRibbon->FindByID(ID_FILE_PRINT)); 
if (pBtnPrint) pBtnPrint->RemoveAllSubItems();  

编辑:我在 Microsoft Connect 网站上发起了support query,但此后没有任何有意义的回复。

【问题讨论】:

AfxGetMainWnd() 是否返回您在MainFrm.cpp 中定义的类?因为如果你得到一个不同的窗口并将其转换为CMainFrame*,你最终可能会得到一个非空的pBtnPrint,但不是你想的那样。 当然可以。如果您创建一个新的 Visual Studio 项目,您可以检查自己。 您/他们是否已经解决了这个问题?您是否将 m_pBtnPrint 添加到功能区? @Robson... 错误报告:不,那里什么也没发生。 m_pButtonPrint:查看问题的最后一个代码框。框架正在添加打印按钮。这只是为了说明目的。但是我自己添加的按钮也有同样的体验。 为什么必须在视图的 onUpdate 上的功能区上做一些事情? 【参考方案1】:

CmainFrame::LoadFrame() 会覆盖您的指针。如果您上次运行并关闭此程序时保存了注册表值,则 LoadFrame 将序列化 MFC 按钮的旧状态。在此期间内存位置会发生变化,并且您在初始化期间保存的指针将无效。在 LoadFrame 运行后,您必须找到一种方法来获取指向按钮的指针。

我在所有 MFCToolbars 上创建了一个设置函数,只是为了在从注册表创建新按钮后获取这些自定义按钮指针。在调用 CMainFrame::LoadFrame() 之后,我在 CWinAppEx::InitInstance 中调用此 Setup 函数

删除这个程序保存的注册表值应该可以正常运行,但是第二次运行就会崩溃。

【讨论】:

好主意。但这不会改变任何事情。查看我的编辑。

以上是关于MFC 功能区:CView::OnUpdate 中的 RemoveAllSubItems() 导致访问冲突 (VS2008)的主要内容,如果未能解决你的问题,请参考以下文章

在 MFC 功能区的面板中添加四个按钮

基于 mfc 对话框的应用程序中的功能区控件

MFC 6.0 新增功能区不显示

新的 MFC 功能包控件是不是应该出现在 VS 工具箱中

MFC 功能区面板名称问题

MFC 功能包 - 如何更新属性网格控件