tried to fix the accel string drawing in the owner drawn menu items
[wxWidgets.git] / src / msw / menuitem.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: menuitem.cpp
3 // Purpose: wxMenuItem implementation
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 11.11.97
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "menuitem.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #ifndef WX_PRECOMP
32 #include "wx/font.h"
33 #include "wx/bitmap.h"
34 #include "wx/settings.h"
35 #include "wx/font.h"
36 #include "wx/window.h"
37 #include "wx/accel.h"
38 #include "wx/menu.h"
39 #include "wx/string.h"
40 #endif
41
42 #include "wx/menuitem.h"
43 #include "wx/log.h"
44
45 #if wxUSE_ACCEL
46 #include "wx/accel.h"
47 #endif // wxUSE_ACCEL
48
49 #include "wx/msw/private.h"
50
51 // ---------------------------------------------------------------------------
52 // macro
53 // ---------------------------------------------------------------------------
54
55 // hide the ugly cast
56 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
57
58 // conditional compilation
59 #if wxUSE_OWNER_DRAWN
60 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
61 #else // !wxUSE_OWNER_DRAWN
62 #define OWNER_DRAWN_ONLY( code )
63 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
64
65 // ============================================================================
66 // implementation
67 // ============================================================================
68
69 // ----------------------------------------------------------------------------
70 // dynamic classes implementation
71 // ----------------------------------------------------------------------------
72
73 #if wxUSE_OWNER_DRAWN
74 IMPLEMENT_DYNAMIC_CLASS2(wxMenuItem, wxMenuItemBase, wxOwnerDrawn)
75 #else //!USE_OWNER_DRAWN
76 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxMenuItemBase)
77 #endif //USE_OWNER_DRAWN
78
79 // ----------------------------------------------------------------------------
80 // wxMenuItem
81 // ----------------------------------------------------------------------------
82
83 // ctor & dtor
84 // -----------
85
86 wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
87 int id,
88 const wxString& text,
89 const wxString& strHelp,
90 bool bCheckable,
91 wxMenu *pSubMenu)
92 #if wxUSE_OWNER_DRAWN
93 : wxOwnerDrawn(GetLabelFromText(text), bCheckable)
94 #endif // owner drawn
95 {
96 wxASSERT_MSG( pParentMenu != NULL, wxT("a menu item should have a parent") );
97
98 #if wxUSE_OWNER_DRAWN
99 // set default menu colors
100 #define SYS_COLOR(c) (wxSystemSettings::GetSystemColour(wxSYS_COLOUR_##c))
101
102 SetTextColour(SYS_COLOR(MENUTEXT));
103 SetBackgroundColour(SYS_COLOR(MENU));
104
105 #undef SYS_COLOR
106
107 // we don't want normal items be owner-drawn
108 ResetOwnerDrawn();
109
110 // tell the owner drawing code to to show the accel string as well
111 SetAccelString(text.AfterFirst(_T('\t')));
112 #endif // wxUSE_OWNER_DRAWN
113
114 m_parentMenu = pParentMenu;
115 m_subMenu = pSubMenu;
116 m_isEnabled = TRUE;
117 m_isChecked = FALSE;
118 m_id = id;
119 m_text = text;
120 m_isCheckable = bCheckable;
121 m_help = strHelp;
122 }
123
124 wxMenuItem::~wxMenuItem()
125 {
126 }
127
128 // misc
129 // ----
130
131 // return the id for calling Win32 API functions
132 int wxMenuItem::GetRealId() const
133 {
134 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
135 }
136
137 // get item state
138 // --------------
139
140 bool wxMenuItem::IsChecked() const
141 {
142 int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetId(), MF_BYCOMMAND);
143
144 return (flag & MF_CHECKED) != 0;
145 }
146
147 /* static */
148 wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
149 {
150 return wxStripMenuCodes(text);
151 }
152
153 // accelerators
154 // ------------
155
156 #if wxUSE_ACCEL
157
158 wxAcceleratorEntry *wxMenuItem::GetAccel() const
159 {
160 return wxGetAccelFromString(GetText());
161 }
162
163 #endif // wxUSE_ACCEL
164
165 // change item state
166 // -----------------
167
168 void wxMenuItem::Enable(bool enable)
169 {
170 if ( m_isEnabled == enable )
171 return;
172
173 long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
174 GetRealId(),
175 MF_BYCOMMAND |
176 (enable ? MF_ENABLED : MF_GRAYED));
177
178 if ( rc == -1 ) {
179 wxLogLastError(wxT("EnableMenuItem"));
180 }
181
182 wxMenuItemBase::Enable(enable);
183 }
184
185 void wxMenuItem::Check(bool check)
186 {
187 wxCHECK_RET( m_isCheckable, wxT("only checkable items may be checked") );
188
189 if ( m_isChecked == check )
190 return;
191
192 long rc = CheckMenuItem(GetHMenuOf(m_parentMenu),
193 GetRealId(),
194 MF_BYCOMMAND |
195 (check ? MF_CHECKED : MF_UNCHECKED));
196
197 if ( rc == -1 ) {
198 wxLogLastError(wxT("CheckMenuItem"));
199 }
200
201 wxMenuItemBase::Check(check);
202 }
203
204 void wxMenuItem::SetText(const wxString& text)
205 {
206 // don't do anything if label didn't change
207 if ( m_text == text )
208 return;
209
210 wxMenuItemBase::SetText(text);
211 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
212
213 HMENU hMenu = GetHMenuOf(m_parentMenu);
214 wxCHECK_RET( hMenu, wxT("menuitem without menu") );
215
216 #if wxUSE_ACCEL
217 m_parentMenu->UpdateAccel(this);
218 #endif // wxUSE_ACCEL
219
220 UINT id = GetRealId();
221 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
222 if ( flagsOld == 0xFFFFFFFF )
223 {
224 wxLogLastError(wxT("GetMenuState"));
225 }
226 else
227 {
228 if ( IsSubMenu() )
229 {
230 // high byte contains the number of items in a submenu for submenus
231 flagsOld &= 0xFF;
232 flagsOld |= MF_POPUP;
233 }
234
235 LPCTSTR data;
236
237 #if wxUSE_OWNER_DRAWN
238 if ( IsOwnerDrawn() )
239 {
240 flagsOld |= MF_OWNERDRAW;
241 data = (LPCTSTR)this;
242 }
243 else
244 #endif //owner drawn
245 {
246 flagsOld |= MF_STRING;
247 data = (wxChar*) text.c_str();
248 }
249
250 if ( ::ModifyMenu(hMenu, id,
251 MF_BYCOMMAND | flagsOld,
252 id, data) == (int)0xFFFFFFFF )
253 {
254 wxLogLastError(wxT("ModifyMenu"));
255 }
256 }
257 }
258
259 void wxMenuItem::SetCheckable(bool checkable)
260 {
261 wxMenuItemBase::SetCheckable(checkable);
262 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable) );
263 }
264
265 // ----------------------------------------------------------------------------
266 // wxMenuItemBase
267 // ----------------------------------------------------------------------------
268
269 wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
270 int id,
271 const wxString& name,
272 const wxString& help,
273 bool isCheckable,
274 wxMenu *subMenu)
275 {
276 return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
277 }