Link to home
Start Free TrialLog in
Avatar of AlexFM
AlexFM

asked on

Dynamic tooltip

I have CWnd-derived class and need to show dynamic tooltip in this window. Window doesn't have child windows and must show tooltip for itself. Tooltip string depends on the mouse position (for example, it may show x and y coordinates). Tooltip may be very simple (no need in multiline, balloon etc.)
Avatar of migel
migel

Hi!
IMHO you need to use MFC buildin tooltipsupport
call EnableToolTips(TRUE) int he your CWnd derived window
and catch TTN_NEEDTEXT notify.

ON_NOTIFY_EX( TTN_NEEDTEXT, 0, ToolTipNeedText)

for example:
BOOL CMyWnd::ToolTipNeedText( UINT id, NMHDR* pTTTStruct, LRESULT* pResult )
{
      TOOLTIPTEXT *pTTT = (TOOLTIPTEXT *)pTTTStruct;

      static CString string;
      int col;
      long row;
      POINT point;

      GetCursorPos(&point);
      ScreenToClient(&point);
         string.Format("pos : %d: %d", point.x, point.y);
         pTTT->lpszText = const_cast<LPTSTR>((LPCTSTR)string);
         return TRUE;
}
You can implement basic tooltip functionality without CToolTipCtrl. Just derive a CWnd object:

MyToolTip.h
-----------
class CMyTooltip : public CWnd
{
public: // create from serialization only
    CMyTooltip() {};
    DECLARE_DYNCREATE(CMyTooltip)
public:
    virtual ~CMyTooltip() {};

protected:
    //{{AFX_MSG(CMyTooltip)
    afx_msg void OnPaint();
    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()
};

MyToolTip.cpp

IMPLEMENT_DYNCREATE(CMyTooltip, CWnd)

BEGIN_MESSAGE_MAP(CMyTooltip, CWnd)
    //{{AFX_MSG_MAP(CMyTooltip)
    ON_WM_PAINT()
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void CMyTooltip::OnPaint()
{
    CPaintDC dc(this); // device context for painting
        CRect rect;
        GetClientRect(&rect);
        dc.SelectStockObject(BLACK_PEN);
        dc.SelectStockObject(WHITE_BRUSH);
        dc.Rectangle(&rect);
        dc.SetBkMode(TRANSPARENT);
        dc.DrawText("test", &rect, DT_LEFT);    
}

--------------------------

In your view class, declare a CMyTooltip object as member.

In the create function write this:
    tt.Create(NULL, "ToolTip", WS_OVERLAPPED|WS_VISIBLE, CRect(0,0,80,20), this, 100);
    tt.UpdateWindow();
    tt.ShowWindow(SW_HIDE);

In the mouse move event insert this:
    if (MustShowTip(point)) {   <---- your function here
        tt.MoveWindow(point.x, point.y+20, 100, 20, TRUE);
        tt.ShowWindow(SW_SHOWNOACTIVATE);
    } else
        tt.ShowWindow(SW_HIDE);

That's all, to enhance it, decorate in the OnPaint event of CMyToolTip
Avatar of AlexFM

ASKER

migel: ToolTipNeedText function is never called. Maybe because window is placed on the toolbar. I will try this way with dialog.

jaime_olivares: I want to use standard tooltip, I beleive this is simple way. MustShowTip function in your answer may be complicated.
Avatar of AlexFM

ASKER

By the way, there is the sample program which shows tooltip in the form x = ...  y = ... for the view class. It may be in CodeGuru, CodeProject or somewhere else. I beleive it can be OK for me, but I cannot find it.
Avatar of AlexFM

ASKER

I want to ask this question by other way:
I have CWnd-derived window placed on toolbar's parent on SDI application. In this window I want to show dynamic tooltip based on the mouse position. Window is created using this code:

void CMainFrame::CreateIconsWindow()
{
    m_pIconsWnd = new CIconsWnd();    // CIconsWnd is CWnd-derived class

    CRect rect;
    m_wndToolBar.GetParent()->GetClientRect(&rect);

    rect.top = rect.bottom - 300;   // toolbar is vertical

    m_pIconsWnd->Create(
        NULL,
        _T(""),
        WS_CHILD | WS_VISIBLE,
        rect,
        m_wndToolBar.GetParent(),
        ID_ICONWND);
}
Okay
I have to write some test project :-)
Avatar of AndyAinscow
re your comment - migel: ToolTipNeedText function is never called. Maybe because window is placed on the toolbar. I will try this way with dialog.

Alex - are you pumping the tooltip control in the OnMouseMove of your window?  Do you have a tooltip in your window?
Avatar of AlexFM

ASKER

I don't have a tooltip, and I want to do it. Window is created as shown in my previous post. It is child of status bar parent and placed after status bar buttons. I don't use OnMouseMove. One of jaime_olivares' links shows how to display tooltip from OnMousMove function, but this is not what I need.
In .h for the window

      CToolTipCtrl      m_tooltip;


in .cpp


BOOL CSortDlg::PreTranslateMessage(MSG* pMsg)
{
      // CG: The following block was added by the ToolTips component.
      {
            // Let the ToolTip process this message.
            m_tooltip.RelayEvent(pMsg);
      }
    if(pMsg->message == WM_MOUSEMOVE)
      {
            m_tooltip.Update();  //DYNAMIC TIPS
      }


in OnCreate of the window
            m_tooltip.Create(this, TTS_NOPREFIX);
            m_tooltip.SetMaxTipWidth(600);      //allow it to be very wide
            m_tooltip.SetDelayTime(TTDT_AUTOPOP, 10000);      //display for 10 seconds (stop flashing)
            m_tooltip.Activate(TRUE);

            m_tooltip.AddTool(this, LPSTR_TEXTCALLBACK);


handle the TTN_NEEDTEXT as migel suggests - this should work.
Avatar of AlexFM

ASKER

ToolTipNeedText function is not called.
The tool is with LPSTR_TEXTCALLBACK
Is your window getting a mousemove event?
Avatar of AlexFM

ASKER

Yes, it gets WM_MOUSEMOVE.

Learning DTTest sample from this article, it has functionality I need:

http://www.microsoft.com/msj/0497/tooltip/tooltip.aspx
Avatar of AlexFM

ASKER

I found another solution using some tricks with WM_MOUSEMOVE, WM_MOUSELEAVE and showing prompt on the status bar. Tooltip doesn't want to work in this situation.
ASKER CERTIFIED SOLUTION
Avatar of CetusMOD
CetusMOD
Flag of Netherlands image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial