]> git.saurik.com Git - wxWidgets.git/blob - src/msw/menuitem.cpp
wxRegion fixes (off by one)
[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 #if wxUSE_OWNER_DRAWN
76 IMPLEMENT_DYNAMIC_CLASS2(wxMenuItem, wxMenuItemBase, wxOwnerDrawn)
77 #else //!USE_OWNER_DRAWN
78 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxMenuItemBase)
79 #endif //USE_OWNER_DRAWN
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(GetLabelFromText(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 #undef SYS_COLOR
108
109 // we don't want normal items be owner-drawn
110 ResetOwnerDrawn();
111
112 // tell the owner drawing code to to show the accel string as well
113 SetAccelString(text.AfterFirst(_T('\t')));
114 #endif // wxUSE_OWNER_DRAWN
115
116 m_parentMenu = pParentMenu;
117 m_subMenu = pSubMenu;
118 m_isEnabled = TRUE;
119 m_isChecked = FALSE;
120 m_id = id;
121 m_text = text;
122 m_isCheckable = bCheckable;
123 m_help = strHelp;
124 }
125
126 wxMenuItem::~wxMenuItem()
127 {
128 }
129
130 // misc
131 // ----
132
133 // return the id for calling Win32 API functions
134 int wxMenuItem::GetRealId() const
135 {
136 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
137 }
138
139 // get item state
140 // --------------
141
142 bool wxMenuItem::IsChecked() const
143 {
144 int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetId(), MF_BYCOMMAND);
145
146 return (flag & MF_CHECKED) != 0;
147 }
148
149 /* static */
150 wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
151 {
152 return wxStripMenuCodes(text);
153 }
154
155 // change item state
156 // -----------------
157
158 void wxMenuItem::Enable(bool enable)
159 {
160 if ( m_isEnabled == enable )
161 return;
162
163 long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
164 GetRealId(),
165 MF_BYCOMMAND |
166 (enable ? MF_ENABLED : MF_GRAYED));
167
168 if ( rc == -1 ) {
169 wxLogLastError(wxT("EnableMenuItem"));
170 }
171
172 wxMenuItemBase::Enable(enable);
173 }
174
175 void wxMenuItem::Check(bool check)
176 {
177 wxCHECK_RET( m_isCheckable, wxT("only checkable items may be checked") );
178
179 if ( m_isChecked == check )
180 return;
181
182 long rc = CheckMenuItem(GetHMenuOf(m_parentMenu),
183 GetRealId(),
184 MF_BYCOMMAND |
185 (check ? MF_CHECKED : MF_UNCHECKED));
186
187 if ( rc == -1 ) {
188 wxLogLastError(wxT("CheckMenuItem"));
189 }
190
191 wxMenuItemBase::Check(check);
192 }
193
194 void wxMenuItem::SetText(const wxString& text)
195 {
196 // don't do anything if label didn't change
197 if ( m_text == text )
198 return;
199
200 wxMenuItemBase::SetText(text);
201 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
202
203 HMENU hMenu = GetHMenuOf(m_parentMenu);
204 wxCHECK_RET( hMenu, wxT("menuitem without menu") );
205
206 #if wxUSE_ACCEL
207 m_parentMenu->UpdateAccel(this);
208 #endif // wxUSE_ACCEL
209
210 UINT id = GetRealId();
211 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
212 if ( flagsOld == 0xFFFFFFFF )
213 {
214 wxLogLastError(wxT("GetMenuState"));
215 }
216 else
217 {
218 if ( IsSubMenu() )
219 {
220 // high byte contains the number of items in a submenu for submenus
221 flagsOld &= 0xFF;
222 flagsOld |= MF_POPUP;
223 }
224
225 LPCTSTR data;
226
227 #if wxUSE_OWNER_DRAWN
228 if ( IsOwnerDrawn() )
229 {
230 flagsOld |= MF_OWNERDRAW;
231 data = (LPCTSTR)this;
232 }
233 else
234 #endif //owner drawn
235 {
236 flagsOld |= MF_STRING;
237 data = (wxChar*) text.c_str();
238 }
239
240 if ( ::ModifyMenu(hMenu, id,
241 MF_BYCOMMAND | flagsOld,
242 id, data) == (int)0xFFFFFFFF )
243 {
244 wxLogLastError(wxT("ModifyMenu"));
245 }
246 }
247 }
248
249 void wxMenuItem::SetCheckable(bool checkable)
250 {
251 wxMenuItemBase::SetCheckable(checkable);
252 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable) );
253 }
254
255 // ----------------------------------------------------------------------------
256 // wxMenuItemBase
257 // ----------------------------------------------------------------------------
258
259 wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
260 int id,
261 const wxString& name,
262 const wxString& help,
263 bool isCheckable,
264 wxMenu *subMenu)
265 {
266 return new wxMenuItem(parentMenu, id, name, help, isCheckable, subMenu);
267 }
268
269 #endif // wxUSE_MENUS