]> git.saurik.com Git - wxWidgets.git/blame - src/msw/tooltip.cpp
Fix for mingw32 compilation (replaced #ifdef NM_CUSTOMDRAW with a test for _WIN32_IE
[wxWidgets.git] / src / msw / tooltip.cpp
CommitLineData
3a19e16d
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: msw/tooltip.cpp
3// Purpose: wxToolTip class implementation for MSW
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 31.01.99
7// RCS-ID: $Id$
8// Copyright: (c) 1999 Vadim Zeitlin
9// Licence: wxWindows license
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/wx.h"
28#endif
29
cb1a1dc9
VZ
30#if wxUSE_TOOLTIPS
31
3a19e16d
VZ
32#include "wx/tooltip.h"
33#include "wx/msw/private.h"
34
f048e32f
VZ
35#if defined(__WIN95__) && !defined(__GNUWIN32_OLD__)
36 #include <commctrl.h>
acbd13a3 37#endif
3a19e16d 38
f048e32f
VZ
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.
42//
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
47
086c94af
VZ
48// ----------------------------------------------------------------------------
49// global variables
50// ----------------------------------------------------------------------------
51
52// the tooltip parent window
f048e32f
VZ
53WXHWND wxToolTip::ms_hwndTT = (WXHWND)NULL;
54
55#if wxUSE_TTM_WINDOWFROMPOINT
56
57// the tooltip window proc
58static WNDPROC gs_wndprocToolTip = (WNDPROC)NULL;
59
60#endif // wxUSE_TTM_WINDOWFROMPOINT
066f302c 61
3a19e16d
VZ
62// ----------------------------------------------------------------------------
63// private classes
64// ----------------------------------------------------------------------------
65
66// a simple wrapper around TOOLINFO Win32 structure
26b83329 67#ifdef __VISUALC__
11c7d5b6 68 #pragma warning( disable : 4097 ) // we inherit from a typedef - so what?
26b83329 69#endif
3a19e16d
VZ
70class wxToolInfo : public TOOLINFO
71{
72public:
f048e32f 73 wxToolInfo(HWND hwnd)
3a19e16d
VZ
74 {
75 // initialize all members
76 ::ZeroMemory(this, sizeof(TOOLINFO));
77
78 cbSize = sizeof(TOOLINFO);
79 uFlags = TTF_IDISHWND;
f048e32f 80 uId = (UINT)hwnd;
3a19e16d
VZ
81 }
82};
26b83329
VZ
83#ifdef __VISUALC__
84 #pragma warning( default : 4097 )
85#endif
3a19e16d
VZ
86
87// ----------------------------------------------------------------------------
88// private functions
89// ----------------------------------------------------------------------------
90
91// send a message to the tooltip control
92inline LRESULT SendTooltipMessage(WXHWND hwnd,
93 UINT msg,
94 WPARAM wParam,
95 void *lParam)
96{
97 return hwnd ? ::SendMessage((HWND)hwnd, msg, wParam, (LPARAM)lParam)
98 : 0;
99}
100
16f6dfd8 101// send a message to all existing tooltip controls
066f302c 102static void SendTooltipMessageToAll(WXHWND hwnd,
18ba9da6
RD
103 UINT msg,
104 WPARAM wParam,
066f302c 105 LPARAM lParam)
16f6dfd8 106{
f048e32f 107 (void)SendTooltipMessage((WXHWND)hwnd, msg, wParam, (void *)lParam);
16f6dfd8
VZ
108}
109
3a19e16d
VZ
110// ============================================================================
111// implementation
112// ============================================================================
113
f048e32f
VZ
114#if wxUSE_TTM_WINDOWFROMPOINT
115
3a19e16d 116// ----------------------------------------------------------------------------
f048e32f 117// window proc for our tooltip control
3a19e16d
VZ
118// ----------------------------------------------------------------------------
119
f048e32f
VZ
120LRESULT APIENTRY wxToolTipWndProc(HWND hwndTT,
121 UINT msg,
122 WPARAM wParam,
123 LPARAM lParam)
124{
125 if ( msg == TTM_WINDOWFROMPOINT )
126 {
127 LPPOINT ppt = (LPPOINT)lParam;
128 // is the window under control a wxWindow?
129 HWND hwnd = ::WindowFromPoint(*ppt);
130
131 // return a HWND correspondign to wxWindow because only wxWindows are
132 // associated with tooltips using TTM_ADDTOOL
133 while ( hwnd && !wxFindWinFromHandle((WXHWND)hwnd) )
134 {
135 hwnd = ::GetParent(hwnd);
136 }
137
138 if ( hwnd )
139 {
140 // modify the point too!
141 RECT rect;
142 GetWindowRect(hwnd, &rect);
143
144 ppt->x = rect.left;
145 ppt->y = rect.top;
066f302c 146
f048e32f
VZ
147 return (LRESULT)hwnd;
148 }
149 }
150
151 return ::CallWindowProc(gs_wndprocToolTip, hwndTT, msg, wParam, lParam);
152}
153
154#endif // wxUSE_TTM_WINDOWFROMPOINT
155
156// ----------------------------------------------------------------------------
157// static functions
158// ----------------------------------------------------------------------------
066f302c 159
16f6dfd8
VZ
160void wxToolTip::Enable(bool flag)
161{
f048e32f 162 SendTooltipMessageToAll(ms_hwndTT, TTM_ACTIVATE, flag, 0);
16f6dfd8
VZ
163}
164
165void wxToolTip::SetDelay(long milliseconds)
166{
f048e32f
VZ
167 SendTooltipMessageToAll(ms_hwndTT, TTM_SETDELAYTIME,
168 TTDT_INITIAL, milliseconds);
16f6dfd8
VZ
169}
170
171// ---------------------------------------------------------------------------
172// implementation helpers
173// ---------------------------------------------------------------------------
174
3a19e16d
VZ
175// create the tooltip ctrl for our parent frame if it doesn't exist yet
176WXHWND wxToolTip::GetToolTipCtrl()
177{
f048e32f 178 if ( !ms_hwndTT )
3a19e16d 179 {
f048e32f
VZ
180 ms_hwndTT = (WXHWND)::CreateWindow(TOOLTIPS_CLASS,
181 (LPSTR)NULL,
182 TTS_ALWAYSTIP,
183 CW_USEDEFAULT, CW_USEDEFAULT,
184 CW_USEDEFAULT, CW_USEDEFAULT,
185 NULL, (HMENU)NULL,
186 wxGetInstance(),
187 NULL);
188 if ( ms_hwndTT )
086c94af 189 {
f048e32f
VZ
190 HWND hwnd = (HWND)ms_hwndTT;
191 SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
086c94af 192 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
28195455 193
f048e32f
VZ
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
199 }
3a19e16d
VZ
200 }
201
f048e32f 202 return ms_hwndTT;
3a19e16d
VZ
203}
204
3a19e16d
VZ
205void wxToolTip::RelayEvent(WXMSG *msg)
206{
207 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_RELAYEVENT, 0, msg);
208}
209
3a19e16d
VZ
210// ----------------------------------------------------------------------------
211// ctor & dtor
212// ----------------------------------------------------------------------------
213
214wxToolTip::wxToolTip(const wxString &tip)
215 : m_text(tip)
216{
217 m_window = NULL;
218}
219
220wxToolTip::~wxToolTip()
221{
222 // there is no need to Remove() this tool - it will be done automatically
223 // anyhow
224}
225
226// ----------------------------------------------------------------------------
227// others
228// ----------------------------------------------------------------------------
229
230void wxToolTip::Remove()
231{
232 // remove this tool from the tooltip control
233 if ( m_window )
234 {
f048e32f 235 wxToolInfo ti(GetHwndOf(m_window));
3a19e16d
VZ
236 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_DELTOOL, 0, &ti);
237 }
238}
239
f048e32f
VZ
240void wxToolTip::Add(WXHWND hWnd)
241{
242 HWND hwnd = (HWND)hWnd;
243
244 wxToolInfo ti(hwnd);
245
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
249 ti.hwnd = hwnd;
250 ti.lpszText = LPSTR_TEXTCALLBACK;
251 // instead of: ti.lpszText = (char *)m_text.c_str();
252
253 if ( !SendTooltipMessage(GetToolTipCtrl(), TTM_ADDTOOL, 0, &ti) )
254 {
255 wxLogSysError(_("Failed to create the tooltip '%s'"),
256 m_text.c_str());
257 }
258}
259
3a19e16d
VZ
260void wxToolTip::SetWindow(wxWindow *win)
261{
262 Remove();
263
264 m_window = win;
265
f048e32f 266 // add the window itself
3a19e16d
VZ
267 if ( m_window )
268 {
f048e32f
VZ
269 Add(m_window->GetHWND());
270 }
3a19e16d 271
f048e32f
VZ
272 // and all of its subcontrols (e.g. radiobuttons in a radiobox) as well
273 wxControl *control = wxDynamicCast(m_window, wxControl);
274 if ( control )
275 {
276 size_t count = control->GetSubcontrols().GetCount();
277 for ( size_t n = 0; n < count; n++ )
3a19e16d 278 {
f048e32f
VZ
279 wxWindowID id = control->GetSubcontrols()[n];
280 HWND hwnd = GetDlgItem(GetHwndOf(m_window), id);
281
282 if ( hwnd )
283 {
284 Add((WXHWND)hwnd);
285 }
3a19e16d
VZ
286 }
287 }
288}
289
290void wxToolTip::SetTip(const wxString& tip)
291{
292 m_text = tip;
293
294 if ( m_window )
295 {
296 // update it immediately
f048e32f 297 wxToolInfo ti(GetHwndOf(m_window));
837e5743 298 ti.lpszText = (wxChar *)m_text.c_str();
3a19e16d
VZ
299
300 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, 0, &ti);
301 }
302}
cb1a1dc9
VZ
303
304#endif // wxUSE_TOOLTIPS