1. wxMenu changes: wxMenuBase appears, several new functions for dynamic menu
[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 !defined(USE_SHARED_LIBRARY) || !USE_SHARED_LIBRARY
74 #if wxUSE_OWNER_DRAWN
75 IMPLEMENT_DYNAMIC_CLASS2(wxMenuItem, wxMenuItemBase, wxOwnerDrawn)
76 #else //!USE_OWNER_DRAWN
77 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxMenuItemBase)
78 #endif //USE_OWNER_DRAWN
79 #endif //USE_SHARED_LIBRARY
80
81 // ----------------------------------------------------------------------------
82 // wxMenuItem
83 // ----------------------------------------------------------------------------
84
85 // ctor & dtor
86 // -----------
87
88 wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
89 int id,
90 const wxString& text,
91 const wxString& strHelp,
92 bool bCheckable,
93 wxMenu *pSubMenu) :
94 #if wxUSE_OWNER_DRAWN
95 wxOwnerDrawn(text, bCheckable)
96 #endif // owner drawn
97 {
98 wxASSERT_MSG( pParentMenu != NULL, wxT("a menu item should have a parent") );
99
100 #if wxUSE_OWNER_DRAWN
101 // set default menu colors
102 #define SYS_COLOR(c) (wxSystemSettings::GetSystemColour(wxSYS_COLOUR_##c))
103
104 SetTextColour(SYS_COLOR(MENUTEXT));
105 SetBackgroundColour(SYS_COLOR(MENU));
106
107 // we don't want normal items be owner-drawn
108 ResetOwnerDrawn();
109
110 #undef SYS_COLOR
111 #endif // wxUSE_OWNER_DRAWN
112
113 m_parentMenu = pParentMenu;
114 m_subMenu = pSubMenu;
115 m_isEnabled = TRUE;
116 m_isChecked = FALSE;
117 m_id = id;
118 m_text = text;
119 m_isCheckable = bCheckable;
120 m_help = strHelp;
121 }
122
123 wxMenuItem::~wxMenuItem()
124 {
125 }
126
127 // misc
128 // ----
129
130 // return the id for calling Win32 API functions
131 int wxMenuItem::GetRealId() const
132 {
133 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
134 }
135
136 // get item state
137 // --------------
138
139 bool wxMenuItem::IsChecked() const
140 {
141 int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetId(), MF_BYCOMMAND);
142
143 // don't "and" with MF_ENABLED because its value is 0
144 return (flag & MF_DISABLED) == 0;
145 }
146
147 wxString wxMenuItem::GetLabel() const
148 {
149 return wxStripMenuCodes(m_text);
150 }
151
152 // accelerators
153 // ------------
154
155 #if wxUSE_ACCEL
156
157 wxAcceleratorEntry *wxMenuItem::GetAccel() const
158 {
159 return wxGetAccelFromString(GetText());
160 }
161
162 #endif // wxUSE_ACCEL
163
164 // change item state
165 // -----------------
166
167 void wxMenuItem::Enable(bool enable)
168 {
169 if ( m_isEnabled == enable )
170 return;
171
172 long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
173 GetRealId(),
174 MF_BYCOMMAND |
175 (enable ? MF_ENABLED : MF_GRAYED));
176
177 if ( rc == -1 ) {
178 wxLogLastError("EnableMenuItem");
179 }
180
181 wxMenuItemBase::Enable(enable);
182 }
183
184 void wxMenuItem::Check(bool check)
185 {
186 wxCHECK_RET( m_isCheckable, wxT("only checkable items may be checked") );
187
188 if ( m_isChecked == check )
189 return;
190
191 long rc = CheckMenuItem(GetHMenuOf(m_parentMenu),
192 GetRealId(),
193 MF_BYCOMMAND |
194 (check ? MF_CHECKED : MF_UNCHECKED));
195
196 if ( rc == -1 ) {
197 wxLogLastError("CheckMenuItem");
198 }
199
200 wxMenuItemBase::Check(check);
201 }
202
203 void wxMenuItem::SetText(const wxString& text)
204 {
205 // don't do anything if label didn't change
206 if ( m_text == text )
207 return;
208
209 wxMenuItemBase::SetText(text);
210 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
211
212 HMENU hMenu = GetHMenuOf(m_parentMenu);
213 wxCHECK_RET( hMenu, wxT("menuitem without menu") );
214
215 #if wxUSE_ACCEL
216 m_parentMenu->UpdateAccel(this);
217 #endif // wxUSE_ACCEL
218
219 UINT id = GetRealId();
220 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
221 if ( flagsOld == 0xFFFFFFFF )
222 {
223 wxLogLastError("GetMenuState");
224 }
225 else
226 {
227 if ( IsSubMenu() )
228 {
229 // high byte contains the number of items in a submenu for submenus
230 flagsOld &= 0xFF;
231 flagsOld |= MF_POPUP;
232 }
233
234 LPCTSTR data;
235
236 #if wxUSE_OWNER_DRAWN
237 if ( IsOwnerDrawn() )
238 {
239 flagsOld |= MF_OWNERDRAW;
240 data = (LPCTSTR)this;
241 }
242 else
243 #endif //owner drawn
244 {
245 flagsOld |= MF_STRING;
246 data = (char*) text.c_str();
247 }
248
249 if ( ::ModifyMenu(hMenu, id,
250 MF_BYCOMMAND | flagsOld,
251 id, data) == (int)0xFFFFFFFF )
252 {
253 wxLogLastError(wxT("ModifyMenu"));
254 }
255 }
256 }
257
258 void wxMenuItem::SetCheckable(bool checkable)
259 {
260 wxMenuItemBase::SetCheckable(checkable);
261 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable) );
262 }
263
264 // ----------------------------------------------------------------------------
265 // wxMenuItemBase
266 // ----------------------------------------------------------------------------
267
268 wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
269 int id,
270 const wxString& name,
271 const wxString& help,
272 bool isCheckable,
273 wxMenu *subMenu)
274 {
275 return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
276 }