简体   繁体   English

MFC CListCtrl OnToolTipNotify

[英]MFC CListCtrl OnToolTipNotify

I'm trying to override OnToolTipNotify for the CListCtrl to have tooltips that support more than 80 characters. 我试图为CListCtrl覆盖OnToolTipNotify,以具有支持80个以上字符的工具提示。 I want the tooltips to appear for specific cells. 我希望工具提示针对特定的单元格出现。 I've seen a bunch of posts related to this, but none have completely helped me understand the best way to do this. 我看过很多与此相关的文章,但是没有一篇文章可以完全帮助我了解执行此操作的最佳方法。 Here is what I have so far, but I'm concerned with the wide char code that uses T2W. 这是到目前为止的内容,但是我担心使用T2W的宽字符代码。 I read T2W uses memory off the stack and when the function returns it will be cleaned up. 我读到T2W占用了堆栈的内存,当函数返回时它将被清除。 So, lpszText will become invalid. 因此,lpszText将变得无效。 This seems to work though and I cannot find another way to do it. 虽然这似乎可行,但我找不到其他方法。

BOOL CListCtrlEx::OnToolTipNotify(UINT tooldId, NMHDR* notifMsg, LRESULT result)
{
    USES_CONVERSION;
    TOOLTIPTEXTA* tttA = reinterpret_cast<TOOLTIPTEXTA*>(notifMsg);
    TOOLTIPTEXTW* tttW = reinterpret_cast<TOOLTIPTEXTW*>(notifMsg);
    ...
    int row, col;
    cellHitTest(row, col);
    CString tipStr;

    // Note getTooltip() returns const ref to cell's tooltip string
    if (-1 < row && -1 < col)
        tipStr = m_Data[row]->colvals[col]->getTooltip();

    if (tipStr.IsEmpty()) return FALSE;

    if (TTN_NEEDTEXTA == notifMsg->code)
    {
        tttA->lpszText = tipStr.GetBuffer();
        tttA->hinst = 0;
    }
    else
    {
        // Question: Is this a problem?  Will the buffer pointed to
        // by tttW->lpszText be deleted after this function ends  
        // making the pointer invalid?
        tttW->lpszText = T2W(tipStr.GetBuffer());
        tttW->hinst = 0;
    }

    ...
}

I tried to understand your question with my best efforts. 我已尽力了解您的问题。 All you are saying that CString can be used, but the wide conversion cannot be used directly without T2W conversion macro. 您只是说可以使用CString ,但是如果没有T2W转换宏,则不能直接使用广泛转换。 If this is the question, you can simply use CStringW - assign tipStr to a variable of this type, and pass it to lpszText . 如果这是问题,您可以简单地使用CStringWtipStr分配给此类型的变量,然后将其传递给lpszText

But, I see problem with your code - you are assuming that if code is not TTN_NEEDTEXTA , it must be TTN_NEEDTEXTW - this assumption is wrong. 但是,我发现您的代码有问题-您假设如果code不是TTN_NEEDTEXTA ,它必须是TTN_NEEDTEXTW这个假设是错误的。

EDIT: From this article , I found out that you need to allocate it dynamically. 编辑: 从本文开始 ,我发现您需要动态分配它。 Hope this helps! 希望这可以帮助!

If using the TTN_NEEDTEXT message handler and one wants to display tooltip longer than 80 characters, then one must allocate the wanted text buffer and set the TOOLTIPTEXT::lpszText pointer to this text-buffer in the message handler (one has to deallocate this text buffer manually): 如果使用TTN_NEEDTEXT消息处理程序,并且想要显示超过80个字符的工具提示,则必须分配所需的文本缓冲区,并将TOOLTIPTEXT :: lpszText指针设置为消息处理程序中的此文本缓冲区(必须取消分配此文本缓冲区)手动):

This is the code I use: tiptext is the CString containing the text I want to show m_pchTip and m_pwchTip are members of my list control. 这是我使用的代码:tiptext是包含要显示的文本的CString,m_pchTip和m_pwchTip是我的列表控件的成员。

    if(m_pchTip != NULL)
    {
        delete[] m_pchTip;
        m_pchTip = nullptr;
    }

    if(m_pwchTip != NULL)
    {
        delete[] m_pwchTip;
        m_pwchTip = nullptr;
    }

        if(pNMHDR->code == TTN_NEEDTEXTA)
        {
            TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
            m_pchTip = new char[tiptext.GetLength() + 1];
            lstrcpyn(m_pchTip,tiptext,tiptext.GetLength() + 1);
            m_pchTip[tiptext.GetLength()] = 0;
            pTTTA->lpszText = m_pchTip;
        }
        else
        {
            TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
            m_pwchTip = new WCHAR[tiptext.GetLength() + 1];
            _mbstowcsz(m_pwchTip,tiptext,tiptext.GetLength() + 1);
            m_pwchTip[tiptext.GetLength()] = 0;
            pTTTW->lpszText = (WCHAR*)m_pwchTip;
        }

Here is what I ended up doing. 这就是我最终要做的。 Since I could not find a case in my applications where I need to handle the TTN_NEEDTEXTA == notifMsg->code case I'm not supporting it. 由于我在我的应用程序中找不到需要处理TTN_NEEDTEXTA == notifMsg->code case的情况,因此我不支持它。 I removed ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA...) from the message map and in CListCtrlEx::OnToolTipNotify I return FALSE if TTN_NEEDTEXTA == notifMsg->code . 我从消息映射中删除了ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA...) ,并且在CListCtrlEx::OnToolTipNotify如果TTN_NEEDTEXTA == notifMsg->code我返回FALSE。 I will revisit it when I better understand ANSI vs. UNICODE. 当我更好地理解ANSI与UNICODE时,我将重新审视它。

In my cell class I changed the CString tooltip member to CStringW as @IInspectable suggested. 在我的单元格类中,按照@IInspectable的建议,将CString tooltip成员CStringW为CStringW。 The CListCtrlEx::OnToolTipNotify function has access to the cell's CStringW member, so I set lpszText = const_cast<LPWSTR>((LPCWSTR)m_Data[row]->colvals[col]->tooltip) . CListCtrlEx :: OnToolTipNotify函数可以访问单元格的CStringW成员,因此我设置了lpszText = const_cast<LPWSTR>((LPCWSTR)m_Data[row]->colvals[col]->tooltip)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM