1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/tooltip.cpp
3 // Purpose: wxToolTip class implementation for MSW
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1999 Vadim Zeitlin
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
32 #include "wx/tooltip.h"
33 #include "wx/msw/private.h"
35 #if defined(__WIN95__) && (!defined(__GNUWIN32__) || defined(__MINGW32__))
39 // VZ: normally, the trick with subclassing the tooltip control and processing
40 // TTM_WINDOWFROMPOINT should work but, somehow, it doesn't. I leave the
41 // code here for now (but it's not compiled) in case we need it later.
43 // For now, instead of this, we just add all radiobox buttons to the
44 // tooltip control as well (see SetWindow) - this is probably less
45 // efficient, but it works.
46 #define wxUSE_TTM_WINDOWFROMPOINT 0
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // the tooltip parent window
53 WXHWND
wxToolTip::ms_hwndTT
= (WXHWND
)NULL
;
55 #if wxUSE_TTM_WINDOWFROMPOINT
57 // the tooltip window proc
58 static WNDPROC gs_wndprocToolTip
= (WNDPROC
)NULL
;
60 #endif // wxUSE_TTM_WINDOWFROMPOINT
62 // ----------------------------------------------------------------------------
64 // ----------------------------------------------------------------------------
66 // a simple wrapper around TOOLINFO Win32 structure
68 #pragma warning( disable : 4097 ) // we inherit from a typedef - so what?
70 class wxToolInfo
: public TOOLINFO
75 // initialize all members
76 ::ZeroMemory(this, sizeof(TOOLINFO
));
78 cbSize
= sizeof(TOOLINFO
);
79 uFlags
= TTF_IDISHWND
;
84 #pragma warning( default : 4097 )
87 // ----------------------------------------------------------------------------
89 // ----------------------------------------------------------------------------
91 // send a message to the tooltip control
92 inline LRESULT
SendTooltipMessage(WXHWND hwnd
,
97 return hwnd
? ::SendMessage((HWND
)hwnd
, msg
, wParam
, (LPARAM
)lParam
)
101 // send a message to all existing tooltip controls
102 static void SendTooltipMessageToAll(WXHWND hwnd
,
107 (void)SendTooltipMessage((WXHWND
)hwnd
, msg
, wParam
, (void *)lParam
);
110 // ============================================================================
112 // ============================================================================
114 #if wxUSE_TTM_WINDOWFROMPOINT
116 // ----------------------------------------------------------------------------
117 // window proc for our tooltip control
118 // ----------------------------------------------------------------------------
120 LRESULT APIENTRY
wxToolTipWndProc(HWND hwndTT
,
125 if ( msg
== TTM_WINDOWFROMPOINT
)
127 LPPOINT ppt
= (LPPOINT
)lParam
;
128 // is the window under control a wxWindow?
129 HWND hwnd
= ::WindowFromPoint(*ppt
);
131 // return a HWND correspondign to wxWindow because only wxWindows are
132 // associated with tooltips using TTM_ADDTOOL
133 while ( hwnd
&& !wxFindWinFromHandle((WXHWND
)hwnd
) )
135 hwnd
= ::GetParent(hwnd
);
140 // modify the point too!
142 GetWindowRect(hwnd
, &rect
);
147 return (LRESULT
)hwnd
;
151 return ::CallWindowProc(gs_wndprocToolTip
, hwndTT
, msg
, wParam
, lParam
);
154 #endif // wxUSE_TTM_WINDOWFROMPOINT
156 // ----------------------------------------------------------------------------
158 // ----------------------------------------------------------------------------
160 void wxToolTip::Enable(bool flag
)
162 SendTooltipMessageToAll(ms_hwndTT
, TTM_ACTIVATE
, flag
, 0);
165 void wxToolTip::SetDelay(long milliseconds
)
167 SendTooltipMessageToAll(ms_hwndTT
, TTM_SETDELAYTIME
,
168 TTDT_INITIAL
, milliseconds
);
171 // ---------------------------------------------------------------------------
172 // implementation helpers
173 // ---------------------------------------------------------------------------
175 // create the tooltip ctrl for our parent frame if it doesn't exist yet
176 WXHWND
wxToolTip::GetToolTipCtrl()
180 ms_hwndTT
= (WXHWND
)::CreateWindow(TOOLTIPS_CLASS
,
183 CW_USEDEFAULT
, CW_USEDEFAULT
,
184 CW_USEDEFAULT
, CW_USEDEFAULT
,
190 HWND hwnd
= (HWND
)ms_hwndTT
;
191 SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, 0, 0,
192 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
194 #if wxUSE_TTM_WINDOWFROMPOINT
195 // subclass the newly created control
196 gs_wndprocToolTip
= (WNDPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
197 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (long)wxToolTipWndProc
);
198 #endif // wxUSE_TTM_WINDOWFROMPOINT
205 void wxToolTip::RelayEvent(WXMSG
*msg
)
207 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_RELAYEVENT
, 0, msg
);
210 // ----------------------------------------------------------------------------
212 // ----------------------------------------------------------------------------
214 wxToolTip::wxToolTip(const wxString
&tip
)
220 wxToolTip::~wxToolTip()
222 // there is no need to Remove() this tool - it will be done automatically
226 // ----------------------------------------------------------------------------
228 // ----------------------------------------------------------------------------
230 void wxToolTip::Remove()
232 // remove this tool from the tooltip control
235 wxToolInfo
ti(GetHwndOf(m_window
));
236 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_DELTOOL
, 0, &ti
);
240 void wxToolTip::Add(WXHWND hWnd
)
242 HWND hwnd
= (HWND
)hWnd
;
246 // as we store our text anyhow, it seems useless to waste system memory
247 // by asking the tooltip ctrl to remember it too - instead it will send
248 // us TTN_NEEDTEXT (via WM_NOTIFY) when it is about to be shown
250 ti
.lpszText
= LPSTR_TEXTCALLBACK
;
251 // instead of: ti.lpszText = (char *)m_text.c_str();
253 if ( !SendTooltipMessage(GetToolTipCtrl(), TTM_ADDTOOL
, 0, &ti
) )
255 wxLogSysError(_("Failed to create the tooltip '%s'"),
260 void wxToolTip::SetWindow(wxWindow
*win
)
266 // add the window itself
269 Add(m_window
->GetHWND());
272 // and all of its subcontrols (e.g. radiobuttons in a radiobox) as well
273 wxControl
*control
= wxDynamicCast(m_window
, wxControl
);
276 size_t count
= control
->GetSubcontrols().GetCount();
277 for ( size_t n
= 0; n
< count
; n
++ )
279 wxWindowID id
= control
->GetSubcontrols()[n
];
280 HWND hwnd
= GetDlgItem(GetHwndOf(m_window
), id
);
290 void wxToolTip::SetTip(const wxString
& tip
)
296 // update it immediately
297 wxToolInfo
ti(GetHwndOf(m_window
));
298 ti
.lpszText
= (wxChar
*)m_text
.c_str();
300 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT
, 0, &ti
);
304 #endif // wxUSE_TOOLTIPS