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 wrapper around TOOLINFO Win32 structure
68 #pragma warning( disable : 4097 ) // we inherit from a typedef - so what?
71 class wxToolInfo
: public TOOLINFO
76 // initialize all members
77 ::ZeroMemory(this, sizeof(TOOLINFO
));
79 // the structure TOOLINFO has been extended with a 4 byte field in
80 // version 4.70 of comctl32.dll and if we compile on a newer machine
81 // but run on one with the old version of comctl32, nothing will work
82 // because the library will detect that we rely on a more recent
83 // version of it. So we always use the old size - if we ever start
84 // using our lParam member, we'd have to check for comctl32 version
86 #if defined(_WIN32_IE) && (_WIN32_IE >= 0x0300)
87 cbSize
= sizeof(TOOLINFO
) - sizeof(LPARAM
);
89 cbSize
= sizeof(TOOLINFO
);
90 #endif // compile-time comctl32.dll version
92 uFlags
= TTF_IDISHWND
;
98 #pragma warning( default : 4097 )
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
105 // send a message to the tooltip control
106 inline LRESULT
SendTooltipMessage(WXHWND hwnd
,
111 return hwnd
? ::SendMessage((HWND
)hwnd
, msg
, wParam
, (LPARAM
)lParam
)
115 // send a message to all existing tooltip controls
116 static void SendTooltipMessageToAll(WXHWND hwnd
,
121 (void)SendTooltipMessage((WXHWND
)hwnd
, msg
, wParam
, (void *)lParam
);
124 // ============================================================================
126 // ============================================================================
128 #if wxUSE_TTM_WINDOWFROMPOINT
130 // ----------------------------------------------------------------------------
131 // window proc for our tooltip control
132 // ----------------------------------------------------------------------------
134 LRESULT APIENTRY
wxToolTipWndProc(HWND hwndTT
,
139 if ( msg
== TTM_WINDOWFROMPOINT
)
141 LPPOINT ppt
= (LPPOINT
)lParam
;
142 // is the window under control a wxWindow?
143 HWND hwnd
= ::WindowFromPoint(*ppt
);
145 // return a HWND correspondign to wxWindow because only wxWindows are
146 // associated with tooltips using TTM_ADDTOOL
147 while ( hwnd
&& !wxFindWinFromHandle((WXHWND
)hwnd
) )
149 hwnd
= ::GetParent(hwnd
);
154 // modify the point too!
156 GetWindowRect(hwnd
, &rect
);
161 return (LRESULT
)hwnd
;
165 return ::CallWindowProc(gs_wndprocToolTip
, hwndTT
, msg
, wParam
, lParam
);
168 #endif // wxUSE_TTM_WINDOWFROMPOINT
170 // ----------------------------------------------------------------------------
172 // ----------------------------------------------------------------------------
174 void wxToolTip::Enable(bool flag
)
176 SendTooltipMessageToAll(ms_hwndTT
, TTM_ACTIVATE
, flag
, 0);
179 void wxToolTip::SetDelay(long milliseconds
)
181 SendTooltipMessageToAll(ms_hwndTT
, TTM_SETDELAYTIME
,
182 TTDT_INITIAL
, milliseconds
);
185 // ---------------------------------------------------------------------------
186 // implementation helpers
187 // ---------------------------------------------------------------------------
189 // create the tooltip ctrl for our parent frame if it doesn't exist yet
190 WXHWND
wxToolTip::GetToolTipCtrl()
194 ms_hwndTT
= (WXHWND
)::CreateWindow(TOOLTIPS_CLASS
,
197 CW_USEDEFAULT
, CW_USEDEFAULT
,
198 CW_USEDEFAULT
, CW_USEDEFAULT
,
204 HWND hwnd
= (HWND
)ms_hwndTT
;
205 SetWindowPos(hwnd
, HWND_TOPMOST
, 0, 0, 0, 0,
206 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
);
208 #if wxUSE_TTM_WINDOWFROMPOINT
209 // subclass the newly created control
210 gs_wndprocToolTip
= (WNDPROC
)::GetWindowLong(hwnd
, GWL_WNDPROC
);
211 ::SetWindowLong(hwnd
, GWL_WNDPROC
, (long)wxToolTipWndProc
);
212 #endif // wxUSE_TTM_WINDOWFROMPOINT
219 void wxToolTip::RelayEvent(WXMSG
*msg
)
221 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_RELAYEVENT
, 0, msg
);
224 // ----------------------------------------------------------------------------
226 // ----------------------------------------------------------------------------
228 wxToolTip::wxToolTip(const wxString
&tip
)
234 wxToolTip::~wxToolTip()
236 // there is no need to Remove() this tool - it will be done automatically
240 // ----------------------------------------------------------------------------
242 // ----------------------------------------------------------------------------
244 void wxToolTip::Remove()
246 // remove this tool from the tooltip control
249 wxToolInfo
ti(GetHwndOf(m_window
));
250 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_DELTOOL
, 0, &ti
);
254 void wxToolTip::Add(WXHWND hWnd
)
256 HWND hwnd
= (HWND
)hWnd
;
260 // as we store our text anyhow, it seems useless to waste system memory
261 // by asking the tooltip ctrl to remember it too - instead it will send
262 // us TTN_NEEDTEXT (via WM_NOTIFY) when it is about to be shown
264 ti
.lpszText
= LPSTR_TEXTCALLBACK
;
265 // instead of: ti.lpszText = (char *)m_text.c_str();
267 if ( !SendTooltipMessage(GetToolTipCtrl(), TTM_ADDTOOL
, 0, &ti
) )
269 wxLogDebug(_T("Failed to create the tooltip '%s'"), m_text
.c_str());
273 void wxToolTip::SetWindow(wxWindow
*win
)
279 // add the window itself
282 Add(m_window
->GetHWND());
285 // and all of its subcontrols (e.g. radiobuttons in a radiobox) as well
286 wxControl
*control
= wxDynamicCast(m_window
, wxControl
);
289 size_t count
= control
->GetSubcontrols().GetCount();
290 for ( size_t n
= 0; n
< count
; n
++ )
292 wxWindowID id
= control
->GetSubcontrols()[n
];
293 HWND hwnd
= GetDlgItem(GetHwndOf(m_window
), id
);
303 void wxToolTip::SetTip(const wxString
& tip
)
309 // update it immediately
310 wxToolInfo
ti(GetHwndOf(m_window
));
311 ti
.lpszText
= (wxChar
*)m_text
.c_str();
313 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT
, 0, &ti
);
317 #endif // wxUSE_TOOLTIPS