【问题标题】:MFC Ribbon quick access toolbar crash when state is changed状态更改时 MFC 功能区快速访问工具栏崩溃
【发布时间】:2021-12-17 13:03:09
【问题描述】:

我正在更新一个旧的 MFC 应用程序,我刚刚添加了一个功能区(使用 CMFCRibbonBar 类)。

但是,当从快速访问工具栏而不是普通功能区使用命令时,功能区上快速访问工具栏中的任何导致状态更改(例如关闭文件并退出到主菜单)的命令都会导致崩溃按钮。

崩溃发生在OnMouseMove()中的MFC文件afxribbonbar.cpp

if (pHit != m_pHighlighted)
    {
        PopTooltip();

        if (m_pHighlighted != NULL)
        {
            ASSERT_VALID(m_pHighlighted);
            m_pHighlighted->m_bIsHighlighted = FALSE;
            m_pHighlighted->OnHighlight(FALSE);

            InvalidateRect(m_pHighlighted->GetRect());

            m_pHighlighted = NULL;
        }

它在InvalidateRect 行崩溃,因为m_pHighlighted 似乎存在但没有数据,因此堆栈已损坏或m_pHighlighted 不再存在。

我有一些行要重新加载,其中所有帧都是用户上次处于新状态时的位置,我发现如果我在更改状态时注释掉这些行,则不会发生崩溃:

theApp.SaveState(this, ToolbarKey(i_oldAppState));

theApp.LoadState( this, ToolbarKey(i_newAppState) );

但理想情况下,我希望这些行,否则所有窗口和框架都会恢复到默认状态,用户必须再次调整所有内容的大小。

当我更改状态时,感觉就像快速访问工具栏中的条目正在被销毁并重新创建,但我找不到 MFC 在哪里执行此操作,或者找不到将突出显示的条目设置为 null 的方法。

编辑:由于 mfc140u.dll 中的访问读取冲突,崩溃是未处理的异常。崩溃发生在 MFC 代码的深处,与我编写的任何内容相去甚远。

这个未处理的异常发生时的调用栈是:

  mfc140u.dll!CBasePane::get_accValue(tagVARIANT varChild, wchar_t * * pszValue) Line 1494 C++
  mfc140u.dll!CMFCRibbonBar::OnMouseMove(unsigned int nFlags, CPoint point) Line 2348 C++
  mfc140u.dll!CMFCRibbonBar::OnLButtonUp(unsigned int nFlags, CPoint point) Line 2276 C++
  mfc140u.dll!CWnd::OnWndMsg(unsigned int message, unsigned __int64 wParam, __int64 lParam, __int64 * pResult) Line 2698 C++
  mfc140u.dll!CWnd::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 2099 C++
  mfc140u.dll!CBasePane::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 1020 C++
  mfc140u.dll!CMFCRibbonBar::WindowProc(unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 4884 C++
  mfc140u.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 265 C++
  mfc140u.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 417 C++
  mfc140u.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned __int64 wParam, __int64 lParam) Line 299 C++
  user32.dll!UserCallWinProcCheckWow() Unknown
  user32.dll!DispatchMessageWorker() Unknown
  user32.dll!IsDialogMessageW() Unknown
  mfc140u.dll!CWnd::IsDialogMessageW(tagMSG * lpMsg) Line 194 C++
  [Inline Frame] mfc140u.dll!CWnd::PreTranslateInput(tagMSG *) Line 4606 C++
  mfc140u.dll!CBasePane::PreTranslateMessage(tagMSG * pMsg) Line 1057 C++
  mfc140u.dll!CMFCRibbonBar::PreTranslateMessage(tagMSG * pMsg) Line 3734 C++
  mfc140u.dll!CWnd::WalkPreTranslateTree(HWND__ * hWndStop, tagMSG * pMsg) Line 3379 C++
  mfc140u.dll!AfxInternalPreTranslateMessage(tagMSG * pMsg) Line 233 C++
  mfc140u.dll!AfxInternalPumpMessage() Line 178 C++
  mfc140u.dll!CWinThread::Run() Line 629 C++

【问题讨论】:

  • 你从哪里得到 m_pHighlighted?您可以在执行 LoadState 之前将其设置为 null 吗?
  • “It crashs” - 这是一个非常通用的短语,许多人将许多不同的语义归结为 “crash” 是什么。程序是否因未捕获的异常而终止?它是否响应 SEH 异常而终止。或者您看到的是 failed debug assertion dialog,它实际上并没有崩溃。
  • m_pHighlighted 指向的那个内存内容?所有字节 0xdd?旧的存储空间被删除了。

标签: c++ mfc


【解决方案1】:

我在 BCG 库中遇到了同样的错误。我在那里对变量 m_pHighlighted 和 m_pPressed 进行了私人修复。

BOOL CBCGPRibbonBar::LoadState (LPCTSTR lpszProfileName, int nIndex, UINT uiID)
{
// 2014-04-23 mri: we need to clear pointer to may be active elements that
// may get deleted, when LoadState is executed.
// We cannot set m_pActiveCategory to NULL!!!! This get us into problems when the
// program starts and the minimize/maximize button is used, when this pointer is 
// NULL. 
    m_pHighlighted = NULL;
    m_pPressed = NULL;

您应该在调用 LoadState 之前将它们设置为 nullptr

我记得问题在于功能区中的单击是在鼠标按下消息中处理的。因此,永远不会执行清除此成员的 Mouse-Up 消息...

【讨论】:

  • 非常感谢。这似乎是修复。事后看来如此明显。我想我认为 MFC 库会比这更智能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多