]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/menuitem.cpp
warnings (and some errors) fixes for wxUniv DLL build
[wxWidgets.git] / src / msw / menuitem.cpp
... / ...
CommitLineData
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 licence
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#ifdef __WXWINCE__
54// Implemented in menu.cpp
55UINT GetMenuState(HMENU hMenu, UINT id, UINT flags) ;
56#endif
57
58// ---------------------------------------------------------------------------
59// macro
60// ---------------------------------------------------------------------------
61
62// hide the ugly cast
63#define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
64
65// conditional compilation
66#if wxUSE_OWNER_DRAWN
67 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
68#else // !wxUSE_OWNER_DRAWN
69 #define OWNER_DRAWN_ONLY( code )
70#endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
71
72// ============================================================================
73// implementation
74// ============================================================================
75
76// ----------------------------------------------------------------------------
77// dynamic classes implementation
78// ----------------------------------------------------------------------------
79
80IMPLEMENT_DYNAMIC_CLASS(wxMenuItem, wxObject)
81
82// ----------------------------------------------------------------------------
83// wxMenuItem
84// ----------------------------------------------------------------------------
85
86// ctor & dtor
87// -----------
88
89wxMenuItem::wxMenuItem(wxMenu *pParentMenu,
90 int id,
91 const wxString& text,
92 const wxString& strHelp,
93 wxItemKind kind,
94 wxMenu *pSubMenu)
95 : wxMenuItemBase(pParentMenu, id, text, strHelp, kind, pSubMenu)
96#if wxUSE_OWNER_DRAWN
97 , wxOwnerDrawn(text, kind == wxITEM_CHECK)
98#endif // owner drawn
99{
100 Init();
101}
102
103wxMenuItem::wxMenuItem(wxMenu *parentMenu,
104 int id,
105 const wxString& text,
106 const wxString& help,
107 bool isCheckable,
108 wxMenu *subMenu)
109 : wxMenuItemBase(parentMenu, id, text, help,
110 isCheckable ? wxITEM_CHECK : wxITEM_NORMAL, subMenu)
111#if wxUSE_OWNER_DRAWN
112 , wxOwnerDrawn(text, isCheckable, true)
113#endif // owner drawn
114{
115 Init();
116}
117
118void wxMenuItem::Init()
119{
120 m_radioGroup.start = -1;
121 m_isRadioGroupStart = FALSE;
122
123#if wxUSE_OWNER_DRAWN
124 // set default menu colors
125 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
126
127 SetTextColour(SYS_COLOR(MENUTEXT));
128 SetBackgroundColour(SYS_COLOR(MENU));
129
130 #undef SYS_COLOR
131
132 // we don't want normal items be owner-drawn
133 ResetOwnerDrawn();
134
135 // tell the owner drawing code to to show the accel string as well
136 SetAccelString(m_text.AfterFirst(_T('\t')));
137#endif // wxUSE_OWNER_DRAWN
138}
139
140wxMenuItem::~wxMenuItem()
141{
142}
143
144// misc
145// ----
146
147// return the id for calling Win32 API functions
148int wxMenuItem::GetRealId() const
149{
150 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
151}
152
153// get item state
154// --------------
155
156bool wxMenuItem::IsChecked() const
157{
158 int flag = ::GetMenuState(GetHMenuOf(m_parentMenu), GetId(), MF_BYCOMMAND);
159
160 return (flag & MF_CHECKED) != 0;
161}
162
163/* static */
164wxString wxMenuItemBase::GetLabelFromText(const wxString& text)
165{
166 return wxStripMenuCodes(text);
167}
168
169// radio group stuff
170// -----------------
171
172void wxMenuItem::SetAsRadioGroupStart()
173{
174 m_isRadioGroupStart = TRUE;
175}
176
177void wxMenuItem::SetRadioGroupStart(int start)
178{
179 wxASSERT_MSG( !m_isRadioGroupStart,
180 _T("should only be called for the next radio items") );
181
182 m_radioGroup.start = start;
183}
184
185void wxMenuItem::SetRadioGroupEnd(int end)
186{
187 wxASSERT_MSG( m_isRadioGroupStart,
188 _T("should only be called for the first radio item") );
189
190 m_radioGroup.end = end;
191}
192
193// change item state
194// -----------------
195
196void wxMenuItem::Enable(bool enable)
197{
198 if ( m_isEnabled == enable )
199 return;
200
201 long rc = EnableMenuItem(GetHMenuOf(m_parentMenu),
202 GetRealId(),
203 MF_BYCOMMAND |
204 (enable ? MF_ENABLED : MF_GRAYED));
205
206 if ( rc == -1 ) {
207 wxLogLastError(wxT("EnableMenuItem"));
208 }
209
210 wxMenuItemBase::Enable(enable);
211}
212
213void wxMenuItem::Check(bool check)
214{
215 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
216
217 if ( m_isChecked == check )
218 return;
219
220 int flags = check ? MF_CHECKED : MF_UNCHECKED;
221 HMENU hmenu = GetHMenuOf(m_parentMenu);
222
223 if ( GetKind() == wxITEM_RADIO )
224 {
225 // it doesn't make sense to uncheck a radio item - what would this do?
226 if ( !check )
227 return;
228
229 // get the index of this item in the menu
230 const wxMenuItemList& items = m_parentMenu->GetMenuItems();
231 int pos = items.IndexOf(this);
232 wxCHECK_RET( pos != wxNOT_FOUND,
233 _T("menuitem not found in the menu items list?") );
234
235 // get the radio group range
236 int start,
237 end;
238
239 if ( m_isRadioGroupStart )
240 {
241 // we already have all information we need
242 start = pos;
243 end = m_radioGroup.end;
244 }
245 else // next radio group item
246 {
247 // get the radio group end from the start item
248 start = m_radioGroup.start;
249 end = items.Item(start)->GetData()->m_radioGroup.end;
250 }
251
252#ifdef __WIN32__
253 // calling CheckMenuRadioItem() with such parameters hangs my system
254 // (NT4 SP6) and I suspect this could happen to the others as well - so
255 // don't do it!
256 wxCHECK_RET( start != -1 && end != -1,
257 _T("invalid ::CheckMenuRadioItem() parameter(s)") );
258
259 if ( !::CheckMenuRadioItem(hmenu,
260 start, // the first radio group item
261 end, // the last one
262 pos, // the one to check
263 MF_BYPOSITION) )
264 {
265 wxLogLastError(_T("CheckMenuRadioItem"));
266 }
267#endif // __WIN32__
268
269 // also uncheck all the other items in this radio group
270 wxMenuItemList::compatibility_iterator node = items.Item(start);
271 for ( int n = start; n <= end && node; n++ )
272 {
273 if ( n != pos )
274 {
275 node->GetData()->m_isChecked = FALSE;
276 }
277
278 // we also have to do it in the menu for Win16 (under Win32
279 // CheckMenuRadioItem() does it for us)
280#ifndef __WIN32__
281 ::CheckMenuItem(hmenu, n, n == pos ? MF_CHECKED : MF_UNCHECKED);
282#endif // Win16
283
284 node = node->GetNext();
285 }
286 }
287 else // check item
288 {
289 if ( ::CheckMenuItem(hmenu,
290 GetRealId(),
291 MF_BYCOMMAND | flags) == (DWORD)-1 )
292 {
293 wxLogLastError(wxT("CheckMenuItem"));
294 }
295 }
296
297 wxMenuItemBase::Check(check);
298}
299
300void wxMenuItem::SetText(const wxString& text)
301{
302 // don't do anything if label didn't change
303 if ( m_text == text )
304 return;
305
306 wxMenuItemBase::SetText(text);
307 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text) );
308#if wxUSE_OWNER_DRAWN
309 // tell the owner drawing code to to show the accel string as well
310 SetAccelString(text.AfterFirst(_T('\t')));
311#endif
312
313 HMENU hMenu = GetHMenuOf(m_parentMenu);
314 wxCHECK_RET( hMenu, wxT("menuitem without menu") );
315
316#if wxUSE_ACCEL
317 m_parentMenu->UpdateAccel(this);
318#endif // wxUSE_ACCEL
319
320 UINT id = GetRealId();
321 UINT flagsOld = ::GetMenuState(hMenu, id, MF_BYCOMMAND);
322 if ( flagsOld == 0xFFFFFFFF )
323 {
324 wxLogLastError(wxT("GetMenuState"));
325 }
326 else
327 {
328 if ( IsSubMenu() )
329 {
330 // high byte contains the number of items in a submenu for submenus
331 flagsOld &= 0xFF;
332 flagsOld |= MF_POPUP;
333 }
334
335 LPCTSTR data;
336
337#if wxUSE_OWNER_DRAWN
338 if ( IsOwnerDrawn() )
339 {
340 flagsOld |= MF_OWNERDRAW;
341 data = (LPCTSTR)this;
342 }
343 else
344#endif //owner drawn
345 {
346 flagsOld |= MF_STRING;
347 data = (wxChar*) text.c_str();
348 }
349
350#ifdef __WXWINCE__
351 // FIXME: complete this, applying the old
352 // flags.
353 // However, the WinCE doc for SetMenuItemInfo
354 // says that you can't use it to set the menu
355 // item state; only data, id and type.
356 MENUITEMINFO info;
357 wxZeroMemory(info);
358 info.cbSize = sizeof(info);
359 info.fMask = MIIM_TYPE;
360 info.fType = MFT_STRING;
361 info.cch = text.Length();
362 info.dwTypeData = (LPTSTR) data ;
363 if ( !SetMenuItemInfo(hMenu, id, FALSE, & info) )
364 {
365 wxLogLastError(wxT("SetMenuItemInfo"));
366 }
367#else
368 if ( ::ModifyMenu(hMenu, id,
369 MF_BYCOMMAND | flagsOld,
370 id, data) == (int)0xFFFFFFFF )
371 {
372 wxLogLastError(wxT("ModifyMenu"));
373 }
374#endif
375 }
376}
377
378void wxMenuItem::SetCheckable(bool checkable)
379{
380 wxMenuItemBase::SetCheckable(checkable);
381 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable) );
382}
383
384// ----------------------------------------------------------------------------
385// wxMenuItemBase
386// ----------------------------------------------------------------------------
387
388wxMenuItem *wxMenuItemBase::New(wxMenu *parentMenu,
389 int id,
390 const wxString& name,
391 const wxString& help,
392 wxItemKind kind,
393 wxMenu *subMenu)
394{
395 return new wxMenuItem(parentMenu, id, name, help, kind, subMenu);
396}
397
398#endif // wxUSE_MENUS