]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/menuitem.cpp
6e450bc97391806cd45b682bc7703ce827cb39f1
   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 
 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
) == (DWORD
)-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