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.)
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(CMyToolt ip)
public:
virtual ~CMyTooltip() {};
protected:
//{{AFX_MSG(CMyTooltip)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
MyToolTip.cpp
IMPLEMENT_DYNCREATE(CMyToo ltip, CWnd)
BEGIN_MESSAGE_MAP(CMyToolt ip, 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_SHOWNOACT IVATE);
} else
tt.ShowWindow(SW_HIDE);
That's all, to enhance it, decorate in the OnPaint event of CMyToolTip
MyToolTip.h
-----------
class CMyTooltip : public CWnd
{
public: // create from serialization only
CMyTooltip() {};
DECLARE_DYNCREATE(CMyToolt
public:
virtual ~CMyTooltip() {};
protected:
//{{AFX_MSG(CMyTooltip)
afx_msg void OnPaint();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
MyToolTip.cpp
IMPLEMENT_DYNCREATE(CMyToo
BEGIN_MESSAGE_MAP(CMyToolt
//{{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
dc.SelectStockObject(WHITE
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_SHOWNOACT
} else
tt.ShowWindow(SW_HIDE);
That's all, to enhance it, decorate in the OnPaint event of CMyToolTip
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.
jaime_olivares: I want to use standard tooltip, I beleive this is simple way. MustShowTip function in your answer may be complicated.
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.
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::CreateIconsWin dow()
{
m_pIconsWnd = new CIconsWnd(); // CIconsWnd is CWnd-derived class
CRect rect;
m_wndToolBar.GetParent()-> GetClientR ect(&rect) ;
rect.top = rect.bottom - 300; // toolbar is vertical
m_pIconsWnd->Create(
NULL,
_T(""),
WS_CHILD | WS_VISIBLE,
rect,
m_wndToolBar.GetParent(),
ID_ICONWND);
}
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::CreateIconsWin
{
m_pIconsWnd = new CIconsWnd(); // CIconsWnd is CWnd-derived class
CRect rect;
m_wndToolBar.GetParent()->
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 :-)
I have to write some test project :-)
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?
Alex - are you pumping the tooltip control in the OnMouseMove of your window? Do you have a tooltip in your window?
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::PreTranslateMess age(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(6 00); //allow it to be very wide
m_tooltip.SetDelayTime(TTD T_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.
CToolTipCtrl m_tooltip;
in .cpp
BOOL CSortDlg::PreTranslateMess
{
// 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(6
m_tooltip.SetDelayTime(TTD
m_tooltip.Activate(TRUE);
m_tooltip.AddTool(this, LPSTR_TEXTCALLBACK);
handle the TTN_NEEDTEXT as migel suggests - this should work.
ASKER
ToolTipNeedText function is not called.
The tool is with LPSTR_TEXTCALLBACK
Is your window getting a mousemove event?
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
Learning DTTest sample from this article, it has functionality I need:
http://www.microsoft.com/msj/0497/tooltip/tooltip.aspx
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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>((LPCTST
return TRUE;
}