MFC功能区:CView :: OnUpdate中的RemoveAllSubItems()导致访问冲突(VS2008) [英] MFC Ribbon: RemoveAllSubItems() in CView::OnUpdate leads to access violation (VS2008)

查看:220
本文介绍了MFC功能区:CView :: OnUpdate中的RemoveAllSubItems()导致访问冲突(VS2008)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要重现此问题,请使用功能区(CMyView作为视图类名称)启动一个新的MFC Outlook样式项目.

To reproduce the behavior, start a new MFC Outlook style project with Ribbon (CMyView as the view class name).

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

Let's say I want to modify a menu of a CMFCRibbonButton, for example the subitems of the Print command, and for this, I want to RemoveAllSubItems() first.

在MainFrm.h中将其添加为公共成员:

Add this as a public member in MainFrm.h:

CMFCRibbonButton *m_pBtnPrint;

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

Add this in the InitializeRibbon() member funcion in MainFrm.cpp:

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();  

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

My best guess is that something goes wrong with the frameworks internal replication of the Print command, e.g. for the Quick Access Toolbar. I wonder if I'm missing something here. Is it somehow forbidden to modify menus after the ribbon bar has been created in CMainFrame?

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

It obviously has nothing to do with m_pBtnPrint being invalidated e.g. after LoadFrame(). If you retreive pBtnPrint dynamically using CMFCRibbonBar::FindByID(), it will crash as well:

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

我已经开始

I have started a support query on the Microsoft Connect website, but no meaningful response since.

推荐答案

CmainFrame :: LoadFrame()会覆盖您的指针.如果您有自上次运行和关闭该程序以来保存的注册表值,则LoadFrame将序列化MFC按钮的旧状态.内存位置在此期间更改,并且在初始化期间保存的指针将无效.在运行LoadFrame之后,您必须找到一种方法来抓住指向按钮的指针.

CmainFrame::LoadFrame() overrides your pointer. If you have registry values saved from the last time you ran and closed this program, then LoadFrame will serialize the old state of the MFC buttons. The memory locations change during this time, and your saved pointers during Initialize will be invalid. You must find a way to grab the pointer to the button AFTER the LoadFrame has been ran.

我在所有MFCToolbar上创建了一个设置功能,只是在从注册表中创建了新按钮之后,才抓住这些自定义按钮指针.在调用CMainFrame :: LoadFrame()之后,我在CWinAppEx :: InitInstance中调用此安装函数

I created a setup function on all my MFCToolbars just to grab these custom button pointers after the new buttons have been created from registry. I call this Setup function in my CWinAppEx::InitInstance after the call to CMainFrame::LoadFrame()

如果删除该程序保存的注册表值,您应该可以正常运行,但是在第二次运行时它将崩溃.

You should be able to run fine if you delete the registry values saved by this program, but upon second run it will crash.

这篇关于MFC功能区:CView :: OnUpdate中的RemoveAllSubItems()导致访问冲突(VS2008)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆