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
); 
 185 } // end of wxMenuItem::IsChecked 
 187 wxString 
wxMenuItemBase::GetLabelFromText( 
 188   const wxString
&                   rsText
 
 193     for (const char* 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("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("CheckMenuItem"); 
 367     wxMenuItemBase::Check(bCheck
); 
 368 } // end of wxMenuItem::Check 
 370 void wxMenuItem::SetText( 
 371   const wxString
&                   rText
 
 375     // Don't do anything if label didn't change 
 378     wxString                        sText 
= wxPMTextToLabel(rText
); 
 382     wxMenuItemBase::SetText(sText
); 
 383     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText
)); 
 384 #if  wxUSE_OWNER_DRAWN 
 385     SetAccelString(rText
.AfterFirst(_T('\t'))); 
 386 #endif // wxUSE_OWNER_DRAWN 
 388     HWND                            hMenu 
= GetHmenuOf(m_parentMenu
); 
 390     wxCHECK_RET(hMenu
, wxT("menuitem without menu")); 
 393     m_parentMenu
->UpdateAccel(this); 
 394 #endif // wxUSE_ACCEL 
 396     USHORT                          uId 
= GetRealId(); 
 400     if (!::WinSendMsg( hMenu
 
 402                       ,MPFROM2SHORT(uId
, TRUE
) 
 406         wxLogLastError("GetMenuState"); 
 410         uFlagsOld 
= vItem
.afStyle
; 
 413             uFlagsOld 
|= MIS_SUBMENU
; 
 418 #if wxUSE_OWNER_DRAWN 
 421             uFlagsOld 
|= MIS_OWNERDRAW
; 
 427             uFlagsOld 
|= MIS_TEXT
; 
 428             pData 
= (BYTE
*)sText
.c_str(); 
 434         if (!::WinSendMsg( hMenu
 
 436                           ,MPFROM2SHORT(uId
, TRUE
) 
 440             wxLogLastError(wxT("ModifyMenu")); 
 446         if (::WinSendMsg( hMenu
 
 452             wxLogLastError(wxT("ModifyMenu")); 
 455 } // end of wxMenuItem::SetText 
 457 void wxMenuItem::SetCheckable( 
 461     wxMenuItemBase::SetCheckable(bCheckable
); 
 462     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable
)); 
 463 } // end of wxMenuItem::SetCheckable 
 465 // ---------------------------------------------------------------------------- 
 467 // ---------------------------------------------------------------------------- 
 469 wxMenuItem
* wxMenuItemBase::New( 
 472 , const wxString
&                   rName
 
 473 , const wxString
&                   rHelp
 
 478     return new wxMenuItem( pParentMenu
 
 485 } // end of wxMenuItemBase::New