13

I haven't been able to find a concise chunk of code that allows me to add/display tooltips to a CStatic (and CLed) control. Obviously, the standard code to do so does not apply for this type of control. Can someone post code snippets?

Jason
  • 2,147
  • 6
  • 32
  • 40

6 Answers6

10

I hope this code will solve your problem .One important thing make NOTIFY property of CStatic =TRUE.

if( !m_ToolTip.Create(this))
{
    TRACE0("Unable to create the ToolTip!");
}
else
{
    CWnd* pWnd = GetDlgItem(IDC_STATIC_MASTER_PWD);
    m_ToolTip.AddTool(pWnd,"Ok");
    m_ToolTip.Activate(TRUE);
}

Let me know if any problem.

Himanshu
  • 4,327
  • 16
  • 31
  • 39
user3148898
  • 135
  • 2
  • 9
  • 1
    I needed to do this *plus* implement a `PreTranslateMessage` handler as described in [m_skipper's answer](https://stackoverflow.com/a/33772406/3549027) before it would work. Also might be good to point out that `m_ToolTip` is a `CToolTipCtrl`. – dlf Oct 18 '17 at 13:35
4

I don't know if this is still needed, but here's what I used to solve the problem: just add SS_NOTIFY to dwStyle when creating the static label. (or simply set "Nofity" "True" in the properties). That worked fine for me.

chris
  • 41
  • 1
  • This was what I was lacking... already had the RelayEvent bit, and I'd created the static text with a control variable since I modify it in real time. So setting Notify to True in the properties was an easy fix. Thanks for taking the time to post an answer! – El Ronaldo Apr 22 '20 at 20:27
2

I've had success with multiline tooltips using this simple class:

Create a class for ToolTips:

class ToolTip
{
public:
    static HWND CreateToolTip(int toolID, HWND hDlg, UINT id);
};

Next, implement a tooltip creation function:

HWND ToolTip::CreateToolTip(int toolID, HWND hDlg, UINT id)
{
    if (!toolID || !hDlg || !id)
    {
        return FALSE;
    }

    CString strTTText;
    strTTText.LoadString( id );

    // Get the window handle of the control to attach the TT to.
    HWND hwndTool = ::GetDlgItem(hDlg, toolID);

    // Create the tooltip window
    HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                              WS_POPUP |TTS_ALWAYSTIP,// | TTS_BALLOON,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              hDlg, NULL, 
                              AfxGetInstanceHandle() , NULL);

   if (!hwndTool || !hwndTip)
   {
       return (HWND)NULL;
   }                              

    // Associate the tooltip with the tool.
    TOOLINFO toolInfo = { 0 };
    toolInfo.cbSize = sizeof(toolInfo);
    toolInfo.hwnd = hDlg;
    toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
    toolInfo.uId = (UINT_PTR)hwndTool;
    toolInfo.lpszText = (char*)(LPCTSTR)strTTText;
    ::SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
    ::SendMessageA(hwndTip, TTM_SETMAXTIPWIDTH, 0, 40); // force multi-line

    return hwndTip;
}

Call it somewhere in your InitDialog:

CMyDialog::InitDialog()
{
    ToolTip::CreateToolTip( PickAUniqueNumber, m_hWnd, IDS_MY_RESOURCE_STRING );
}
Himanshu
  • 4,327
  • 16
  • 31
  • 39
RamblinRose
  • 172
  • 6
2

When I add CStatic on Dialog based autocreated mfc application, tooltips don't show until I add RelayEvent in pretranslate dialog message

BOOL CTooltipStaticDlg::PreTranslateMessage(MSG* pMsg)
{
    m_ToolTip.RelayEvent(pMsg); 
    return CDialog::PreTranslateMessage(pMsg);
}
m_skipper
  • 121
  • 1
  • 3
0

I've had on my dialog label with assigned custom ID IDC_PATH. I needed to turn on Notify flag (SS_NOTIFY) of the label and I needed to overload CWnd method OnToolHitTest and handle tooltip hit test like this:

INT_PTR CPath::OnToolHitTest(CPoint point, TOOLINFO* pTI) const
{
    INT_PTR r = CWnd::OnToolHitTest(point,pTI);

    this->ClientToScreen(&point);
    CRect rcLbl;
    GetDlgItem(IDC_PATH)->GetWindowRect(&rcLbl);
    if( rcLbl.PtInRect(point) )
    {
        pTI->uFlags |= TTF_IDISHWND;
        pTI->uFlags &= ~TTF_NOTBUTTON;
        pTI->uId = (UINT_PTR)GetDlgItem(IDC_PATH)->m_hWnd;
        return IDC_PATH;
    }

    return r;
}

Then my dialog started to receive TTN_NEEDTEXT notification, which I handled and dynamicaly set text for tooltip.

BOOL CPath::OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult)
{
   UNREFERENCED_PARAMETER(id);

   TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pNMHDR;
   UINT_PTR nID = pNMHDR->idFrom;
   BOOL bRet = FALSE;

   if (pTTT->uFlags & TTF_IDISHWND)
   {
      // idFrom is actually the HWND of the tool
      nID = ::GetDlgCtrlID((HWND)nID);
      if(nID == IDC_PATH)
      {
         pTTT->lpszText = (LPSTR)(LPCTSTR)m_FullDestPath;
         bRet = TRUE;
      }
   }

   *pResult = 0;

   return bRet;
}
SalgoMato
  • 302
  • 2
  • 6
0

I use this working MFC variant for a tool tip for a static control in a dialog box. The static control is not assigned to the tool tip as a window but as a rectangular area. Nothing more is necessary.

// header file
CStatic     m_sc;
CToolTipCtrl m_ttc;

// C++ file
    CDialogA::OnInitDialog()
    {
        if (m_ttc.Create(this))
        {
            CRect Rect;
            m_sc.GetWindowRect(Rect);
            ScreenToClient(Rect);
    
            TTTOOLINFO ti;
            ::ZeroMemory(&ti, sizeof(ti));
            ti.cbSize = sizeof(ti);
            ti.uFlags = TTF_SUBCLASS;
            ti.hwnd = GetSafeHwnd();
            ti.uId = m_sc.GetDlgCtrlID();
            ti.rect = Rect;
            ti.lpszText = _T("Text");
            m_ttc.SendMessage(TTM_ADDTOOL, 0, (LPARAM)&ti);
        }
    }
Aron
  • 1
  • 1