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