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