1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/richtooltip.cpp
3 // Purpose: Native MSW implementation of wxRichToolTip.
4 // Author: Vadim Zeitlin
5 // Created: 2011-10-18
6 // Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
9
10 // ============================================================================
11 // declarations
12 // ============================================================================
13
14 // ----------------------------------------------------------------------------
15 // headers
16 // ----------------------------------------------------------------------------
17
18 // for compilers that support precompilation, includes "wx.h".
19 #include "wx/wxprec.h"
20
21 #ifdef __BORLANDC__
22 #pragma hdrstop
23 #endif
24
25 #if wxUSE_RICHTOOLTIP
26
27 #ifndef WX_PRECOMP
28 #include "wx/treectrl.h"
29 #endif // WX_PRECOMP
30
31 #include "wx/private/richtooltip.h"
32 #include "wx/generic/private/richtooltip.h"
33 #include "wx/msw/private.h"
34 #include "wx/msw/uxtheme.h"
35
36 // Provide definitions missing from some compilers SDK headers.
37
38 #ifndef TTI_NONE
39 enum
40 {
41 TTI_NONE,
42 TTI_INFO,
43 TTI_WARNING,
44 TTI_ERROR
45 };
46 #endif // !defined(TTI_XXX)
47
48 #ifndef Edit_ShowBalloonTip
49 struct EDITBALLOONTIP
50 {
51 DWORD cbStruct;
52 LPCWSTR pszTitle;
53 LPCWSTR pszText;
54 int ttiIcon;
55 };
56
57 #define Edit_ShowBalloonTip(hwnd, pebt) \
58 (BOOL)::SendMessage((hwnd), 0x1503 /* EM_SHOWBALLOONTIP */, 0, (LPARAM)(pebt))
59
60 #endif // !defined(Edit_ShowBalloonTip)
61
62 // ============================================================================
63 // wxRichToolTipMSWImpl: the real implementation.
64 // ============================================================================
65
66 class wxRichToolTipMSWImpl : public wxRichToolTipGenericImpl
67 {
68 public:
wxRichToolTipMSWImpl(const wxString & title,const wxString & message)69 wxRichToolTipMSWImpl(const wxString& title, const wxString& message) :
70 wxRichToolTipGenericImpl(title, message)
71 {
72 // So far so good...
73 m_canUseNative = true;
74
75 m_ttiIcon = TTI_NONE;
76 }
77
SetBackgroundColour(const wxColour & col,const wxColour & colEnd)78 virtual void SetBackgroundColour(const wxColour& col,
79 const wxColour& colEnd)
80 {
81 // Setting background colour is not supported neither.
82 m_canUseNative = false;
83
84 wxRichToolTipGenericImpl::SetBackgroundColour(col, colEnd);
85 }
86
SetCustomIcon(const wxIcon & icon)87 virtual void SetCustomIcon(const wxIcon& icon)
88 {
89 // Custom icons are not supported by EM_SHOWBALLOONTIP.
90 m_canUseNative = false;
91
92 wxRichToolTipGenericImpl::SetCustomIcon(icon);
93 }
94
SetStandardIcon(int icon)95 virtual void SetStandardIcon(int icon)
96 {
97 wxRichToolTipGenericImpl::SetStandardIcon(icon);
98 if ( !m_canUseNative )
99 return;
100
101 switch ( icon & wxICON_MASK )
102 {
103 case wxICON_WARNING:
104 m_ttiIcon = TTI_WARNING;
105 break;
106
107 case wxICON_ERROR:
108 m_ttiIcon = TTI_ERROR;
109 break;
110
111 case wxICON_INFORMATION:
112 m_ttiIcon = TTI_INFO;
113 break;
114
115 case wxICON_QUESTION:
116 wxFAIL_MSG("Question icon doesn't make sense for a tooltip");
117 break;
118
119 case wxICON_NONE:
120 m_ttiIcon = TTI_NONE;
121 break;
122 }
123 }
124
SetTimeout(unsigned millisecondsTimeout,unsigned millisecondsDelay)125 virtual void SetTimeout(unsigned millisecondsTimeout,
126 unsigned millisecondsDelay)
127 {
128 // We don't support changing the timeout or the delay
129 // (maybe TTM_SETDELAYTIME could be used for this?).
130 m_canUseNative = false;
131
132 wxRichToolTipGenericImpl::SetTimeout(millisecondsTimeout,
133 millisecondsDelay);
134 }
135
SetTipKind(wxTipKind tipKind)136 virtual void SetTipKind(wxTipKind tipKind)
137 {
138 // Setting non-default tip is not supported.
139 if ( tipKind != wxTipKind_Auto )
140 m_canUseNative = false;
141
142 wxRichToolTipGenericImpl::SetTipKind(tipKind);
143 }
144
SetTitleFont(const wxFont & font)145 virtual void SetTitleFont(const wxFont& font)
146 {
147 // Setting non-default font is not supported.
148 m_canUseNative = false;
149
150 wxRichToolTipGenericImpl::SetTitleFont(font);
151 }
152
ShowFor(wxWindow * win,const wxRect * rect)153 virtual void ShowFor(wxWindow* win, const wxRect* rect)
154 {
155 // TODO: We could use native tooltip control to show native balloon
156 // tooltips for any window but right now we use the simple
157 // EM_SHOWBALLOONTIP API which can only be used with text
158 // controls.
159 if ( m_canUseNative && !rect )
160 {
161 wxTextCtrl* const text = wxDynamicCast(win, wxTextCtrl);
162 if ( text )
163 {
164 EDITBALLOONTIP ebt;
165 ebt.cbStruct = sizeof(EDITBALLOONTIP);
166 ebt.pszTitle = m_title.wc_str();
167 ebt.pszText = m_message.wc_str();
168 ebt.ttiIcon = m_ttiIcon;
169 if ( Edit_ShowBalloonTip(GetHwndOf(text), &ebt) )
170 return;
171 }
172 }
173
174 // Don't set m_canUseNative to false here, we could be able to use the
175 // native tooltips if we're called for a different window the next
176 // time.
177 wxRichToolTipGenericImpl::ShowFor(win, rect);
178 }
179
180 private:
181 // If this is false, we've been requested to do something that the native
182 // version doesn't support and so need to fall back to the generic one.
183 bool m_canUseNative;
184
185 // One of TTI_NONE, TTI_INFO, TTI_WARNING or TTI_ERROR.
186 int m_ttiIcon;
187 };
188
189 /* static */
190 wxRichToolTipImpl*
Create(const wxString & title,const wxString & message)191 wxRichToolTipImpl::Create(const wxString& title, const wxString& message)
192 {
193 // EM_SHOWBALLOONTIP is only implemented by comctl32.dll v6 so don't even
194 // bother using the native implementation if we're not using themes.
195 if ( wxUxThemeEngine::GetIfActive() )
196 return new wxRichToolTipMSWImpl(title, message);
197
198 return new wxRichToolTipGenericImpl(title, message);
199 }
200
201 #endif // wxUSE_RICHTOOLTIP
202