]> git.saurik.com Git - wxWidgets.git/blob - src/msw/tooltip.cpp
New HTML help system. The old controller class has been split in
[wxWidgets.git] / src / msw / tooltip.cpp
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
30 #if wxUSE_TOOLTIPS
31
32 #include "wx/tooltip.h"
33 #include "wx/msw/private.h"
34
35 #if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS)
36 #include <commctrl.h>
37 #endif
38
39 // ----------------------------------------------------------------------------
40 // private classes
41 // ----------------------------------------------------------------------------
42
43 // a simple wrapper around TOOLINFO Win32 structure
44 #pragma warning( disable : 4097 )
45 class wxToolInfo : public TOOLINFO
46 {
47 public:
48 wxToolInfo(wxWindow *win)
49 {
50 // initialize all members
51 #if defined( __GNUWIN32__ ) && !defined(wxUSE_NORLANDER_HEADERS)
52 memset(this, 0, sizeof(TOOLINFO));
53 #else
54 ::ZeroMemory(this, sizeof(TOOLINFO));
55 #endif
56
57 cbSize = sizeof(TOOLINFO);
58 uFlags = TTF_IDISHWND;
59 uId = (UINT)win->GetHWND();
60 }
61 };
62 #pragma warning( default : 4097 )
63
64 // ----------------------------------------------------------------------------
65 // private functions
66 // ----------------------------------------------------------------------------
67
68 // send a message to the tooltip control
69 inline LRESULT SendTooltipMessage(WXHWND hwnd,
70 UINT msg,
71 WPARAM wParam,
72 void *lParam)
73 {
74 return hwnd ? ::SendMessage((HWND)hwnd, msg, wParam, (LPARAM)lParam)
75 : 0;
76 }
77
78 // send a message to all existing tooltip controls
79 static void SendTooltipMessageToAll(UINT msg, WPARAM wParam, LPARAM lParam)
80 {
81 // NB: it might be somewhat easier to maintain a list of all existing
82 // wxToolTip controls (put them there in ctor, delete from the list
83 // in dtor) - may be it's worth doing it this way? OTOH, typical
84 // application won't have many top level windows, so iterating over all
85 // of them shouldnt' take much time neither...
86
87 // iterate over all top level windows and send message to the tooltip
88 // control of each and every of them (or more precisely to all dialogs and
89 // frames)
90 wxDialog *dialog = NULL;
91 wxFrame *frame = NULL;
92
93 wxNode *node = wxTopLevelWindows.First();
94 while ( node )
95 {
96 wxWindow *win = (wxWindow *)node->Data();
97
98 node = node->Next();
99
100 if ( win->IsKindOf(CLASSINFO(wxFrame)) )
101 {
102 frame = (wxFrame *)win;
103 dialog = NULL;
104 }
105 else if ( win->IsKindOf(CLASSINFO(wxDialog)) )
106 {
107 dialog = (wxDialog *)win;
108 frame = NULL;
109 }
110 else
111 {
112 // skip this strange top level window
113 continue;
114 }
115
116 wxASSERT_MSG( dialog || frame, _T("logic error") );
117
118 WXHWND hwndTT = frame ? frame->GetToolTipCtrl()
119 : dialog->GetToolTipCtrl();
120 if ( hwndTT )
121 {
122 (void)SendTooltipMessage(hwndTT, msg, wParam, (void *)lParam);
123 }
124 }
125 }
126
127 // ============================================================================
128 // implementation
129 // ============================================================================
130
131 // ----------------------------------------------------------------------------
132 // static functions
133 // ----------------------------------------------------------------------------
134
135 void wxToolTip::Enable(bool flag)
136 {
137 SendTooltipMessageToAll(TTM_ACTIVATE, flag, 0);
138 }
139
140 void wxToolTip::SetDelay(long milliseconds)
141 {
142 SendTooltipMessageToAll(TTM_SETDELAYTIME, TTDT_INITIAL, milliseconds);
143 }
144
145 // ---------------------------------------------------------------------------
146 // implementation helpers
147 // ---------------------------------------------------------------------------
148
149 // create the tooltip ctrl for our parent frame if it doesn't exist yet
150 WXHWND wxToolTip::GetToolTipCtrl()
151 {
152 // find either parent dialog or parent frame - tooltip controls are managed
153 // by these 2 classes only (it doesn't make sense to create one tooltip per
154 // each and every wxWindow)
155 wxFrame *frame = NULL;
156 wxDialog *dialog = NULL;
157
158 wxWindow *parent = m_window;
159 while ( parent )
160 {
161 if ( parent->IsKindOf(CLASSINFO(wxFrame)) )
162 {
163 frame = (wxFrame *)parent;
164
165 break;
166 }
167 else if ( parent->IsKindOf(CLASSINFO(wxDialog)) )
168 {
169 dialog = (wxDialog *)parent;
170
171 break;
172 }
173
174 parent = parent->GetParent();
175 }
176
177 wxCHECK_MSG( frame || dialog, 0,
178 _T("can't create tooltip control outside a frame or a dialog") );
179
180 HWND hwndTT = (HWND)(frame ? frame->GetToolTipCtrl()
181 : dialog->GetToolTipCtrl());
182 if ( !hwndTT )
183 {
184 hwndTT = ::CreateWindow(TOOLTIPS_CLASS,
185 (LPSTR)NULL,
186 TTS_ALWAYSTIP,
187 CW_USEDEFAULT, CW_USEDEFAULT,
188 CW_USEDEFAULT, CW_USEDEFAULT,
189 (HWND)parent->GetHWND(), (HMENU)NULL,
190 wxGetInstance(), NULL);
191
192 if ( hwndTT )
193 {
194 if ( frame )
195 frame->SetToolTipCtrl((WXHWND)hwndTT);
196 else
197 dialog->SetToolTipCtrl((WXHWND)hwndTT);
198 }
199 else
200 {
201 wxLogSysError(_("Can not create tooltip control"));
202 }
203 }
204
205 return (WXHWND)hwndTT;
206 }
207
208 void wxToolTip::RelayEvent(WXMSG *msg)
209 {
210 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_RELAYEVENT, 0, msg);
211 }
212
213 // ----------------------------------------------------------------------------
214 // ctor & dtor
215 // ----------------------------------------------------------------------------
216
217 wxToolTip::wxToolTip(const wxString &tip)
218 : m_text(tip)
219 {
220 m_window = NULL;
221 }
222
223 wxToolTip::~wxToolTip()
224 {
225 // there is no need to Remove() this tool - it will be done automatically
226 // anyhow
227 }
228
229 // ----------------------------------------------------------------------------
230 // others
231 // ----------------------------------------------------------------------------
232
233 void wxToolTip::Remove()
234 {
235 // remove this tool from the tooltip control
236 if ( m_window )
237 {
238 wxToolInfo ti(m_window);
239 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_DELTOOL, 0, &ti);
240 }
241 }
242
243 void wxToolTip::SetWindow(wxWindow *win)
244 {
245 Remove();
246
247 m_window = win;
248
249 if ( m_window )
250 {
251 wxToolInfo ti(m_window);
252
253 // as we store our text anyhow, it seems useless to waste system memory
254 // by asking the tooltip ctrl to remember it too - instead it will send
255 // us TTN_NEEDTEXT (via WM_NOTIFY) when it is about to be shown
256 ti.hwnd = (HWND)m_window->GetHWND();
257 ti.lpszText = LPSTR_TEXTCALLBACK;
258 // instead of: ti.lpszText = (char *)m_text.c_str();
259
260 if ( !SendTooltipMessage(GetToolTipCtrl(), TTM_ADDTOOL, 0, &ti) )
261 {
262 wxLogSysError(_("Failed to create the tooltip '%s'"),
263 m_text.c_str());
264 }
265 }
266 }
267
268 void wxToolTip::SetTip(const wxString& tip)
269 {
270 m_text = tip;
271
272 if ( m_window )
273 {
274 // update it immediately
275 wxToolInfo ti(m_window);
276 ti.lpszText = (wxChar *)m_text.c_str();
277
278 (void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, 0, &ti);
279 }
280 }
281
282 #endif // wxUSE_TOOLTIPS