]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/menuitem.cpp
1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenuItem implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
12 // ===========================================================================
14 // ===========================================================================
16 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
21 #pragma implementation "menuitem.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
35 #include "wx/bitmap.h"
36 #include "wx/settings.h"
38 #include "wx/window.h"
41 #include "wx/string.h"
44 #include "wx/menuitem.h"
51 #include "wx/msw/private.h"
53 // ---------------------------------------------------------------------------
55 // ---------------------------------------------------------------------------
58 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
60 // conditional compilation
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
67 // ============================================================================
69 // ============================================================================
71 // ----------------------------------------------------------------------------
72 // dynamic classes implementation
73 // ----------------------------------------------------------------------------
75 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
84 wxMenuItem::wxMenuItem(wxMenu
*pParentMenu
,
87 const wxString
& strHelp
,
90 : wxMenuItemBase(pParentMenu
, id
, text
, strHelp
, kind
, pSubMenu
)
92 , wxOwnerDrawn(GetLabelFromText(text
), kind
== wxITEM_CHECK
)
98 wxMenuItem::wxMenuItem(wxMenu
*parentMenu
,
100 const wxString
& text
,
101 const wxString
& help
,
104 : wxMenuItemBase(parentMenu
, id
, text
, help
,
105 isCheckable
? wxITEM_CHECK
: wxITEM_NORMAL
, subMenu
)
106 #if wxUSE_OWNER_DRAWN
107 , wxOwnerDrawn(GetLabelFromText(text
), isCheckable
)
108 #endif // owner drawn
113 void wxMenuItem::Init()
115 m_radioGroup
.start
= -1;
116 m_isRadioGroupStart
= FALSE
;
118 #if wxUSE_OWNER_DRAWN
119 // set default menu colors
120 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
122 SetTextColour(SYS_COLOR(MENUTEXT
));
123 SetBackgroundColour(SYS_COLOR(MENU
));
127 // we don't want normal items be owner-drawn
130 // tell the owner drawing code to to show the accel string as well
131 SetAccelString(m_text
.AfterFirst(_T('\t')));
132 #endif // wxUSE_OWNER_DRAWN
135 wxMenuItem::~wxMenuItem()
142 // return the id for calling Win32 API functions
143 int wxMenuItem::GetRealId() const
145 return m_subMenu
? (int)m_subMenu
->GetHMenu() : GetId();
151 bool wxMenuItem::IsChecked() const
153 int flag
= ::GetMenuState(GetHMenuOf(m_parentMenu
), GetId(), MF_BYCOMMAND
);
155 return (flag
& MF_CHECKED
) != 0;
159 wxString
wxMenuItemBase::GetLabelFromText(const wxString
& text
)
161 return wxStripMenuCodes(text
);
167 void wxMenuItem::SetAsRadioGroupStart()
169 m_isRadioGroupStart
= TRUE
;
172 void wxMenuItem::SetRadioGroupStart(int start
)
174 wxASSERT_MSG( !m_isRadioGroupStart
,
175 _T("should only be called for the next radio items") );
177 m_radioGroup
.start
= start
;
180 void wxMenuItem::SetRadioGroupEnd(int end
)
182 wxASSERT_MSG( m_isRadioGroupStart
,
183 _T("should only be called for the first radio item") );
185 m_radioGroup
.end
= end
;
191 void wxMenuItem::Enable(bool enable
)
193 if ( m_isEnabled
== enable
)
196 long rc
= EnableMenuItem(GetHMenuOf(m_parentMenu
),
199 (enable
? MF_ENABLED
: MF_GRAYED
));
202 wxLogLastError(wxT("EnableMenuItem"));
205 wxMenuItemBase::Enable(enable
);
208 void wxMenuItem::Check(bool check
)
210 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
212 if ( m_isChecked
== check
)
215 int flags
= check
? MF_CHECKED
: MF_UNCHECKED
;
216 HMENU hmenu
= GetHMenuOf(m_parentMenu
);
218 if ( GetKind() == wxITEM_RADIO
)
220 // it doesn't make sense to uncheck a radio item - what would this do?
224 // get the index of this item in the menu
225 const wxMenuItemList
& items
= m_parentMenu
->GetMenuItems();
226 int pos
= items
.IndexOf(this);
227 wxCHECK_RET( pos
!= wxNOT_FOUND
,
228 _T("menuitem not found in the menu items list?") );
230 // get the radio group range
234 if ( m_isRadioGroupStart
)
236 // we already have all information we need
238 end
= m_radioGroup
.end
;
240 else // next radio group item
242 // get the radio group end from the start item
243 start
= m_radioGroup
.start
;
244 end
= items
.Item(start
)->GetData()->m_radioGroup
.end
;
248 // calling CheckMenuRadioItem() with such parameters hangs my system
249 // (NT4 SP6) and I suspect this could happen to the others as well - so
251 wxCHECK_RET( start
!= -1 && end
!= -1,
252 _T("invalid ::CheckMenuRadioItem() parameter(s)") );
254 if ( !::CheckMenuRadioItem(hmenu
,
255 start
, // the first radio group item
257 pos
, // the one to check
258 MF_BYPOSITION
| flags
) )
260 wxLogLastError(_T("CheckMenuRadioItem"));
264 // also uncheck all the other items in this radio group
265 wxMenuItemList::Node
*node
= items
.Item(start
);
266 for ( int n
= start
; n
<= end
&& node
; n
++ )
270 node
->GetData()->m_isChecked
= FALSE
;
273 // we also have to do it in the menu for Win16 (under Win32
274 // CheckMenuRadioItem() does it for us)
276 ::CheckMenuItem(hmenu
, n
, n
== pos
? MF_CHECKED
: MF_UNCHECKED
);
279 node
= node
->GetNext();
284 if ( ::CheckMenuItem(hmenu
,
286 MF_BYCOMMAND
| flags
) == -1 )
288 wxLogLastError(wxT("CheckMenuItem"));
292 wxMenuItemBase::Check(check
);
295 void wxMenuItem::SetText(const wxString
& text
)
297 // don't do anything if label didn't change
298 if ( m_text
== text
)
301 wxMenuItemBase::SetText(text
);
302 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetName(text
) );
304 HMENU hMenu
= GetHMenuOf(m_parentMenu
);
305 wxCHECK_RET( hMenu
, wxT("menuitem without menu") );
308 m_parentMenu
->UpdateAccel(this);
309 #endif // wxUSE_ACCEL
311 UINT id
= GetRealId();
312 UINT flagsOld
= ::GetMenuState(hMenu
, id
, MF_BYCOMMAND
);
313 if ( flagsOld
== 0xFFFFFFFF )
315 wxLogLastError(wxT("GetMenuState"));
321 // high byte contains the number of items in a submenu for submenus
323 flagsOld
|= MF_POPUP
;
328 #if wxUSE_OWNER_DRAWN
329 if ( IsOwnerDrawn() )
331 flagsOld
|= MF_OWNERDRAW
;
332 data
= (LPCTSTR
)this;
337 flagsOld
|= MF_STRING
;
338 data
= (wxChar
*) text
.c_str();
341 if ( ::ModifyMenu(hMenu
, id
,
342 MF_BYCOMMAND
| flagsOld
,
343 id
, data
) == (int)0xFFFFFFFF )
345 wxLogLastError(wxT("ModifyMenu"));
350 void wxMenuItem::SetCheckable(bool checkable
)
352 wxMenuItemBase::SetCheckable(checkable
);
353 OWNER_DRAWN_ONLY( wxOwnerDrawn::SetCheckable(checkable
) );
356 // ----------------------------------------------------------------------------
358 // ----------------------------------------------------------------------------
360 wxMenuItem
*wxMenuItemBase::New(wxMenu
*parentMenu
,
362 const wxString
& name
,
363 const wxString
& help
,
367 return new wxMenuItem(parentMenu
, id
, name
, help
, kind
, subMenu
);
370 #endif // wxUSE_MENUS