MFC MDI框架中自定义Toolbar停靠触发断言错误求助
MFC MDI程序自定义工具栏停靠触发Debug断言失败问题
在MFC MDI程序的CMainFrame::OnCreate方法中添加自定义工具栏m_wndColorBar的停靠代码后,编译正常但运行时触发Debug Assertion Failed错误,此前程序无异常。
出现问题的OnCreate代码
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWndEx::OnCreate(lpCreateStruct) == -1) return -1; BOOL bNameValid; CMDITabInfo mdiTabParams; mdiTabParams.m_style = CMFCTabCtrl::STYLE_3D_ONENOTE; mdiTabParams.m_bActiveTabCloseButton = TRUE; mdiTabParams.m_bTabIcons = FALSE; mdiTabParams.m_bAutoColor = TRUE; mdiTabParams.m_bDocumentMenu = TRUE; EnableMDITabbedGroups(TRUE, mdiTabParams); if (!m_wndMenuBar.Create(this)) { TRACE0("Failed to create menubar\n"); return -1; } m_wndMenuBar.SetPaneStyle(m_wndMenuBar.GetPaneStyle() | CBRS_SIZE_DYNAMIC | CBRS_TOOLTIPS | CBRS_FLYBY); CMFCPopupMenu::SetForceMenuFocus(FALSE); if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(theApp.m_bHiColorIcons ? IDR_MAINFRAME_256 : IDR_MAINFRAME)) { TRACE0("Failed to create toolbar\n"); return -1; } CString strToolBarName; bNameValid = strToolBarName.LoadString(IDS_TOOLBAR_STANDARD); ASSERT(bNameValid); m_wndToolBar.SetWindowText(strToolBarName); CString strCustomize; bNameValid = strCustomize.LoadString(IDS_TOOLBAR_CUSTOMIZE); ASSERT(bNameValid); m_wndToolBar.EnableCustomizeButton(TRUE, ID_VIEW_CUSTOMIZE, strCustomize); InitUserToolbars(nullptr, uiFirstUserToolBarId, uiLastUserToolBarId); if (!m_wndStatusBar.Create(this)) { TRACE0("Failed to create status bar\n"); return -1; } m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT)); int iTBCtlID; if (!m_wndColorBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndColorBar.LoadToolBar(IDR_TBCOLOR)) { TRACE0("Failed to Create toolbar \n"); return -1; } iTBCtlID = m_wndColorBar.CommandToIndex(ID_COLORS_BLACK); if (iTBCtlID >= 0) { for (int i = iTBCtlID; i < (iTBCtlID + 11); i++) m_wndColorBar.SetButtonStyle(i, TBBS_CHECKGROUP); } m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY); m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockPane(&m_wndMenuBar); DockPane(&m_wndToolBar); CDockingManager::SetDockingMode(DT_SMART); EnableAutoHidePanes(CBRS_ALIGN_ANY); CMFCToolBar::AddToolBarForImageCollection(IDR_MENU_IMAGES, theApp.m_bHiColorIcons ? IDB_MENU_IMAGES_24 : 0); if (!CreateDockingWindows()) { TRACE0("Failed to create docking windows\n"); return -1; } m_wndFileView.EnableDocking(CBRS_ALIGN_ANY); m_wndClassView.EnableDocking(CBRS_ALIGN_ANY); DockPane(&m_wndFileView); CDockablePane* pTabbedBar = nullptr; m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar); m_wndOutput.EnableDocking(CBRS_ALIGN_ANY); DockPane(&m_wndOutput); m_wndProperties.EnableDocking(CBRS_ALIGN_ANY); DockPane(&m_wndProperties); OnApplicationLook(theApp.m_nAppLook); EnableWindowsDialog(ID_WINDOW_MANAGER, ID_WINDOW_MANAGER, TRUE); EnablePaneMenu(TRUE, ID_VIEW_CUSTOMIZE, strCustomize, ID_VIEW_TOOLBAR); CMFCToolBar::EnableQuickCustomization(); if (CMFCToolBar::GetUserImages() == nullptr) { if (m_UserImages.Load(_T(".\\UserImages.bmp"))) { CMFCToolBar::SetUserImages(&m_UserImages); } } CList<UINT, UINT> lstBasicCommands; lstBasicCommands.AddTail(ID_FILE_NEW); lstBasicCommands.AddTail(ID_FILE_OPEN); lstBasicCommands.AddTail(ID_FILE_SAVE); lstBasicCommands.AddTail(ID_FILE_PRINT); lstBasicCommands.AddTail(ID_APP_EXIT); lstBasicCommands.AddTail(ID_EDIT_CUT); lstBasicCommands.AddTail(ID_EDIT_PASTE); lstBasicCommands.AddTail(ID_EDIT_UNDO); lstBasicCommands.AddTail(ID_APP_ABOUT); lstBasicCommands.AddTail(ID_VIEW_STATUS_BAR); lstBasicCommands.AddTail(ID_VIEW_TOOLBAR); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2003); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_VS_2005); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_BLUE); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_SILVER); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_BLACK); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_OFF_2007_AQUA); lstBasicCommands.AddTail(ID_VIEW_APPLOOK_WINDOWS_7); lstBasicCommands.AddTail(ID_SORTING_SORTALPHABETIC); lstBasicCommands.AddTail(ID_SORTING_SORTBYTYPE); lstBasicCommands.AddTail(ID_SORTING_SORTBYACCESS); lstBasicCommands.AddTail(ID_SORTING_GROUPBYTYPE); CMFCToolBar::SetBasicCommands(lstBasicCommands); ModifyStyle(0, FWS_PREFIXTITLE); DockControlBar(&m_wndColorBar); // 触发断言的代码行 return 0; }
问题原因
断言失败是因为启用智能停靠模式(CDockingManager::SetDockingMode(DT_SMART))后,不能再使用旧版MFC的DockControlBar函数。DockControlBar属于传统停靠机制,和新版的CDockingManager管理的智能停靠不兼容,调用后会触发内部断言检查失败。
解决方案
- 移除代码末尾的
DockControlBar(&m_wndColorBar)调用 - 使用新版停靠函数
DockPane(&m_wndColorBar),并将其放到启用智能停靠之前,和其他工具栏的停靠代码放在一起:
修改后的关键代码段:
// 启用停靠并停靠标准栏 m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY); m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); m_wndColorBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockPane(&m_wndMenuBar); DockPane(&m_wndToolBar); DockPane(&m_wndColorBar); // 新增:用DockPane停靠自定义工具栏 // 启用智能停靠(必须在DockPane之后调用) CDockingManager::SetDockingMode(DT_SMART); EnableAutoHidePanes(CBRS_ALIGN_ANY);
额外注意事项
- 确保
m_wndColorBar的类型是CMFCToolBar,而非旧版CToolBar,因为DockPane只支持MFC扩展库的控件类型。 - 如果需要调整工具栏的停靠位置,可以在
DockPane后调用SetPaneAlignment等函数设置对齐方式。
内容的提问来源于stack exchange,提问作者Violet
相关产品推荐
相关产品推荐

