0
votes

I'm trying to override OnToolTipNotify for the CListCtrl to have tooltips that support more than 80 characters. 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. I read T2W uses memory off the stack and when the function returns it will be cleaned up. So, lpszText will become invalid. 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;
    }

    ...
}
3
I used ON_NOTIFY_REFLECT(LVN_GETINFOTIP, OnGetInfoTip) and void CMyListCtrlEx::OnGetInfoTip(NMHDR* pNMHDR, LRESULT* pResult) - sergiol

3 Answers

0
votes

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. If this is the question, you can simply use CStringW - assign tipStr to a variable of this type, and pass it to 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.

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):

0
votes

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.

    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;
        }
0
votes

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. I removed ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA...) from the message map and in CListCtrlEx::OnToolTipNotify I return FALSE if TTN_NEEDTEXTA == notifMsg->code. I will revisit it when I better understand ANSI vs. UNICODE.

In my cell class I changed the CString tooltip member to CStringW as @IInspectable suggested. 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).