0

我有一堂课

类 CCfgUserPage : 公共 CPropertyPage

它还拥有各种控件,从复选框到文本区域。我想为每个控件添加工具提示,并且似乎遇到了问题。

在 CCfgUserPage 中,我将此添加到消息映射中

ON_NOTIFY_EX(TTN_NEEDTEXT, 0, OnToolTipText )

当此对象捕获该消息时​​,它会调用函数 OnToolTipText,如下所示

BOOL CCfgUserPage::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
    TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
    UINT nID = pNMHDR->idFrom;
    CString ttStr;

    int partOrient = GetDlgItem(IDC_PARTORIENT_CHECK)->GetDlgCtrlID();

    if (pTTT->uFlags & TTF_IDISHWND)
    {
        // idFrom is actually the HWND of the tool
        nID = ::GetDlgCtrlID((HWND)nID);
        if( nID == partOrient ) // Only Display TT for The buttons with these ID's
        {
            if( nID == partOrient )
                ttStr = "Part Orient";
            pTTT->lpszText = (LPTSTR)(LPCTSTR)ttStr;
            pTTT->hinst = AfxGetResourceHandle();
            return TRUE;
        }
    }
    return FALSE;
}

我还启用了工具提示

CCfgUserPage::OnInitDialog

每当 OnToolTipText 返回 TRUE 时,应用程序就会崩溃并通知我

访问冲突读取位置

我正在尝试遍历堆栈框架,但要深入 MFC 才能了解发生了什么问题。我可能会错过什么会导致这种情况发生?

4

2 回答 2

2

看看你在 MSDN 上的提示:

当您处理 TTN_NEEDTEXT 通知消息时,指定要以下列方式之一显示的字符串:

  • 将文本复制到 szText 成员指定的缓冲区。
  • 将包含文本的缓冲区的地址复制到 lpszText 成员。
  • 将字符串资源的标识符复制到 lpszText 成员,并将包含该资源的实例的句柄复制到 hinst 成员。

所以不要这样做:

        CString ttStr;
        // ...
        if( nID == partOrient )
            ttStr = "Part Orient";
        // Below is the unsafe part: you initialize lpszText with something
        //       expected to be valid after you return from the handler
        //       effectively, this is internal buffer of local ttStr valriable
        //       which is to be freed and lpszText would keep point to undefined
        //       memory
        pTTT->lpszText = (LPTSTR)(LPCTSTR)ttStr;
        pTTT->hinst = AfxGetResourceHandle();

你宁愿:

        if(nID == partOrient)
        {
            // NOTE: Here instead you don't create any dynamic instances (strings)
            //       and the value resides directly in the notification structure
            _tcsncpy_s(pTTT->szText, _T("Part Orient"), _TRUNCATE);
            pTTT->lpszText = pTTT->szText; // Just a safety, it's already pointing there
        }
于 2013-03-25T15:48:08.747 回答
0

问题是 ttStr 在函数末尾超出范围,您正在返回指向它的指针。指针现在无效,应用程序在尝试引用它时崩溃。

如果工具提示总是很小(少于 80 个字符),则使用提供的缓冲区,或者使用成员变量来存储工具提示文本。

于 2015-03-21T16:32:15.200 回答