1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxMenuItem implementation
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
17 #pragma implementation "menuitem.h"
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
25 #include "wx/bitmap.h"
26 #include "wx/settings.h"
28 #include "wx/window.h"
31 #include "wx/string.h"
34 #include "wx/menuitem.h"
41 #include "wx/os2/private.h"
43 // ---------------------------------------------------------------------------
45 // ---------------------------------------------------------------------------
48 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
50 // conditional compilation
52 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
53 #else // !wxUSE_OWNER_DRAWN
54 #define OWNER_DRAWN_ONLY( code )
55 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
57 // ============================================================================
59 // ============================================================================
61 // ----------------------------------------------------------------------------
62 // dynamic classes implementation
63 // ----------------------------------------------------------------------------
65 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
)
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
74 wxMenuItem::wxMenuItem(
77 , const wxString
& rsText
78 , const wxString
& rsHelp
82 : wxMenuItemBase( pParentMenu
84 ,wxPMTextToLabel(rsText
)
90 , wxOwnerDrawn( wxPMTextToLabel(rsText
)
91 ,eKind
== wxITEM_CHECK
95 wxASSERT_MSG(pParentMenu
!= NULL
, wxT("a menu item should have a parent"));
96 memset(&m_vMenuData
, '\0', sizeof(m_vMenuData
));
97 m_vMenuData
.id
= (USHORT
)nId
;
100 } // end of wxMenuItem::wxMenuItem
102 wxMenuItem::wxMenuItem(
105 , const wxString
& rsText
106 , const wxString
& rsHelp
110 : wxMenuItemBase( pParentMenu
112 ,wxPMTextToLabel(rsText
)
114 ,bIsCheckable
? wxITEM_CHECK
: wxITEM_NORMAL
117 #if wxUSE_OWNER_DRAWN
118 , wxOwnerDrawn( wxPMTextToLabel(rsText
)
121 #endif // owner drawn
123 wxASSERT_MSG(pParentMenu
!= NULL
, wxT("a menu item should have a parent"));
124 memset(&m_vMenuData
, '\0', sizeof(m_vMenuData
));
125 m_vMenuData
.id
= (USHORT
)nId
;
128 } // end of wxMenuItem::wxMenuItem
130 void wxMenuItem::Init()
132 m_vRadioGroup
.m_nStart
= -1;
133 m_bIsRadioGroupStart
= FALSE
;
135 #if wxUSE_OWNER_DRAWN
137 // Set default menu colors
139 #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c))
141 SetTextColour(SYS_COLOR(MENUTEXT
));
142 SetBackgroundColour(SYS_COLOR(MENU
));
145 // We don't want normal items be owner-drawn
151 // Tell the owner drawing code to to show the accel string as well
153 SetAccelString(m_text
.AfterFirst(_T('\t')));
154 #endif // wxUSE_OWNER_DRAWN
155 } // end of wxMenuItem::Init
157 wxMenuItem::~wxMenuItem()
159 } // end of wxMenuItem::~wxMenuItem
166 // Return the id for calling Win32 API functions
168 int wxMenuItem::GetRealId() const
170 return m_subMenu
? (int)m_subMenu
->GetHMenu() : GetId();
171 } // end of wxMenuItem::GetRealId
176 bool wxMenuItem::IsChecked() const
178 USHORT uFlag
= SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu
)
180 ,MPFROM2SHORT(GetId(), TRUE
)
181 ,MPFROMSHORT(MIA_CHECKED
)
184 return (uFlag
& MIA_CHECKED
) == MIA_CHECKED
;
185 } // end of wxMenuItem::IsChecked
187 wxString
wxMenuItemBase::GetLabelFromText(
188 const wxString
& rsText
193 for (const wxChar
* zPc
= rsText
.c_str(); *zPc
; zPc
++)
195 if (*zPc
== wxT('~') || *zPc
== wxT('&'))
198 // '~' is the escape character for OS/2PM and '&' is the one for
199 // wxWidgets - skip both of them
206 } // end of wxMenuItemBase::GetLabelFromText
212 void wxMenuItem::SetAsRadioGroupStart()
214 m_bIsRadioGroupStart
= true;
215 } // end of wxMenuItem::SetAsRadioGroupStart
217 void wxMenuItem::SetRadioGroupStart(
221 wxASSERT_MSG( !m_bIsRadioGroupStart
222 ,_T("should only be called for the next radio items")
225 m_vRadioGroup
.m_nStart
= nStart
;
226 } // wxMenuItem::SetRadioGroupStart
228 void wxMenuItem::SetRadioGroupEnd(
232 wxASSERT_MSG( m_bIsRadioGroupStart
233 ,_T("should only be called for the first radio item")
235 m_vRadioGroup
.m_nEnd
= nEnd
;
236 } // end of wxMenuItem::SetRadioGroupEnd
241 void wxMenuItem::Enable(
247 if (m_isEnabled
== bEnable
)
250 bOk
= (bool)::WinSendMsg( GetHMenuOf(m_parentMenu
)
252 ,MPFROM2SHORT(GetRealId(), TRUE
)
253 ,MPFROM2SHORT(MIA_DISABLED
, FALSE
)
256 bOk
= (bool)::WinSendMsg( GetHMenuOf(m_parentMenu
)
258 ,MPFROM2SHORT(GetRealId(), TRUE
)
259 ,MPFROM2SHORT(MIA_DISABLED
, MIA_DISABLED
)
263 wxLogLastError(wxT("EnableMenuItem"));
265 wxMenuItemBase::Enable(bEnable
);
266 } // end of wxMenuItem::Enable
268 void wxMenuItem::Check(
274 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
275 if (m_isChecked
== bCheck
)
278 HMENU hMenu
= GetHmenuOf(m_parentMenu
);
280 if (GetKind() == wxITEM_RADIO
)
283 // It doesn't make sense to uncheck a radio item - what would this do?
289 // Get the index of this item in the menu
291 const wxMenuItemList
& rItems
= m_parentMenu
->GetMenuItems();
292 int nPos
= rItems
.IndexOf(this);
294 wxCHECK_RET( nPos
!= wxNOT_FOUND
295 ,_T("menuitem not found in the menu items list?")
299 // Get the radio group range
304 if (m_bIsRadioGroupStart
)
307 // We already have all information we need
310 nEnd
= m_vRadioGroup
.m_nEnd
;
312 else // next radio group item
315 // Get the radio group end from the start item
317 nStart
= m_vRadioGroup
.m_nStart
;
318 nEnd
= rItems
.Item(nStart
)->GetData()->m_vRadioGroup
.m_nEnd
;
322 // Also uncheck all the other items in this radio group
324 wxMenuItemList::compatibility_iterator node
= rItems
.Item(nStart
);
326 for (int n
= nStart
; n
<= nEnd
&& node
; n
++)
332 ,MPFROM2SHORT(n
, TRUE
)
333 ,MPFROM2SHORT(MIA_CHECKED
, MIA_CHECKED
)
338 node
->GetData()->m_isChecked
= FALSE
;
341 ,MPFROM2SHORT(n
, TRUE
)
342 ,MPFROM2SHORT(MIA_CHECKED
, FALSE
)
345 node
= node
->GetNext();
351 bOk
= (bool)::WinSendMsg( hMenu
353 ,MPFROM2SHORT(GetRealId(), TRUE
)
354 ,MPFROM2SHORT(MIA_CHECKED
, MIA_CHECKED
)
357 bOk
= (bool)::WinSendMsg( hMenu
359 ,MPFROM2SHORT(GetRealId(), TRUE
)
360 ,MPFROM2SHORT(MIA_CHECKED
, FALSE
)
365 wxLogLastError(wxT("CheckMenuItem"));
367 wxMenuItemBase::Check(bCheck
);
368 } // end of wxMenuItem::Check
370 void wxMenuItem::SetText( const wxString
& rText
)
373 // Don't do anything if label didn't change
376 wxString sText
= wxPMTextToLabel(rText
);
380 wxMenuItemBase::SetText(sText
);
381 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText
));
382 #if wxUSE_OWNER_DRAWN
383 SetAccelString(rText
.AfterFirst(_T('\t')));
384 #endif // wxUSE_OWNER_DRAWN
386 HWND hMenu
= GetHmenuOf(m_parentMenu
);
388 wxCHECK_RET(hMenu
, wxT("menuitem without menu"));
391 m_parentMenu
->UpdateAccel(this);
392 #endif // wxUSE_ACCEL
394 USHORT uId
= (USHORT
)GetRealId();
398 if (!::WinSendMsg( hMenu
400 ,MPFROM2SHORT(uId
, TRUE
)
404 wxLogLastError(wxT("GetMenuState"));
408 uFlagsOld
= vItem
.afStyle
;
411 uFlagsOld
|= MIS_SUBMENU
;
416 #if wxUSE_OWNER_DRAWN
419 uFlagsOld
|= MIS_OWNERDRAW
;
425 uFlagsOld
|= MIS_TEXT
;
426 pData
= (BYTE
*)sText
.c_str();
432 if (!::WinSendMsg( hMenu
434 ,MPFROM2SHORT(uId
, TRUE
)
438 wxLogLastError(wxT("ModifyMenu"));
444 if (::WinSendMsg( hMenu
450 wxLogLastError(wxT("ModifyMenu"));
453 } // end of wxMenuItem::SetText
455 void wxMenuItem::SetCheckable(
459 wxMenuItemBase::SetCheckable(bCheckable
);
460 OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable
));
461 } // end of wxMenuItem::SetCheckable
463 // ----------------------------------------------------------------------------
465 // ----------------------------------------------------------------------------
467 wxMenuItem
* wxMenuItemBase::New(
470 , const wxString
& rName
471 , const wxString
& rHelp
476 return new wxMenuItem( pParentMenu
483 } // end of wxMenuItemBase::New