1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/menuitem.cpp 
   3 // Purpose:     wxMenuItem implementation 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  13 // headers & declarations 
  14 // ============================================================================ 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  19 #include "wx/menuitem.h" 
  23     #include "wx/bitmap.h" 
  24     #include "wx/settings.h" 
  25     #include "wx/window.h" 
  28     #include "wx/string.h" 
  36 #include "wx/os2/private.h" 
  38 // --------------------------------------------------------------------------- 
  40 // --------------------------------------------------------------------------- 
  43 #define GetHMenuOf(menu)    ((HMENU)menu->GetHMenu()) 
  45 // conditional compilation 
  47     #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code 
  48 #else // !wxUSE_OWNER_DRAWN 
  49     #define OWNER_DRAWN_ONLY( code ) 
  50 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN 
  52 // ============================================================================ 
  54 // ============================================================================ 
  56 // ---------------------------------------------------------------------------- 
  57 // dynamic classes implementation 
  58 // ---------------------------------------------------------------------------- 
  60 IMPLEMENT_DYNAMIC_CLASS(wxMenuItem
, wxObject
) 
  62 // ---------------------------------------------------------------------------- 
  64 // ---------------------------------------------------------------------------- 
  69 wxMenuItem::wxMenuItem( 
  72 , const wxString
&                   rsText
 
  73 , const wxString
&                   rsHelp
 
  77 : wxMenuItemBase( pParentMenu
 
  79                  ,wxPMTextToLabel(rsText
) 
  85 ,  wxOwnerDrawn( wxPMTextToLabel(rsText
) 
  86                 ,eKind 
== wxITEM_CHECK
 
  90     wxASSERT_MSG(pParentMenu 
!= NULL
, wxT("a menu item should have a parent")); 
  91     memset(&m_vMenuData
, '\0', sizeof(m_vMenuData
)); 
  92     m_vMenuData
.id 
= (USHORT
)nId
; 
  95 } // end of wxMenuItem::wxMenuItem 
  97 wxMenuItem::wxMenuItem( 
 100 , const wxString
&                   rsText
 
 101 , const wxString
&                   rsHelp
 
 105 : wxMenuItemBase( pParentMenu
 
 107                  ,wxPMTextToLabel(rsText
) 
 109                  ,bIsCheckable 
? wxITEM_CHECK 
: wxITEM_NORMAL
 
 112 #if wxUSE_OWNER_DRAWN 
 113 ,  wxOwnerDrawn( wxPMTextToLabel(rsText
) 
 116 #endif // owner drawn 
 118     wxASSERT_MSG(pParentMenu 
!= NULL
, wxT("a menu item should have a parent")); 
 119     memset(&m_vMenuData
, '\0', sizeof(m_vMenuData
)); 
 120     m_vMenuData
.id 
= (USHORT
)nId
; 
 123 } // end of wxMenuItem::wxMenuItem 
 125 void wxMenuItem::Init() 
 127     m_vRadioGroup
.m_nStart 
= -1; 
 128     m_bIsRadioGroupStart 
= FALSE
; 
 130 #if  wxUSE_OWNER_DRAWN 
 132     // Set default menu colors 
 134     #define SYS_COLOR(c) (wxSystemSettings::GetColour(wxSYS_COLOUR_##c)) 
 136     SetTextColour(SYS_COLOR(MENUTEXT
)); 
 137     SetBackgroundColour(SYS_COLOR(MENU
)); 
 140     // We don't want normal items be owner-drawn 
 146     // Tell the owner drawing code to to show the accel string as well 
 148     SetAccelString(m_text
.AfterFirst(_T('\t'))); 
 149 #endif // wxUSE_OWNER_DRAWN 
 150 } // end of wxMenuItem::Init 
 152 wxMenuItem::~wxMenuItem() 
 154 } // end of wxMenuItem::~wxMenuItem 
 161 // Return the id for calling Win32 API functions 
 163 int wxMenuItem::GetRealId() const 
 165     return m_subMenu 
? (int)m_subMenu
->GetHMenu() : GetId(); 
 166 } // end of wxMenuItem::GetRealId 
 171 bool wxMenuItem::IsChecked() const 
 173     USHORT uFlag 
= SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu
) 
 175                                              ,MPFROM2SHORT(GetId(), TRUE
) 
 176                                              ,MPFROMSHORT(MIA_CHECKED
) 
 179     return (uFlag 
& MIA_CHECKED
) == MIA_CHECKED 
; 
 180 } // end of wxMenuItem::IsChecked 
 182 wxString 
wxMenuItemBase::GetLabelFromText( 
 183   const wxString
&                   rsText
 
 188     for (const wxChar
* zPc 
= rsText
.c_str(); *zPc
; zPc
++) 
 190         if (*zPc 
== wxT('~') || *zPc 
== wxT('&')) 
 193             // '~' is the escape character for OS/2PM and '&' is the one for 
 194             // wxWidgets - skip both of them 
 201 } // end of wxMenuItemBase::GetLabelFromText 
 207 void wxMenuItem::SetAsRadioGroupStart() 
 209     m_bIsRadioGroupStart 
= true; 
 210 } // end of wxMenuItem::SetAsRadioGroupStart 
 212 void wxMenuItem::SetRadioGroupStart( 
 216     wxASSERT_MSG( !m_bIsRadioGroupStart
 
 217                  ,_T("should only be called for the next radio items") 
 220     m_vRadioGroup
.m_nStart 
= nStart
; 
 221 } // wxMenuItem::SetRadioGroupStart 
 223 void wxMenuItem::SetRadioGroupEnd( 
 227     wxASSERT_MSG( m_bIsRadioGroupStart
 
 228                  ,_T("should only be called for the first radio item") 
 230     m_vRadioGroup
.m_nEnd 
= nEnd
; 
 231 } // end of wxMenuItem::SetRadioGroupEnd 
 236 void wxMenuItem::Enable( 
 242     if (m_isEnabled 
== bEnable
) 
 245         bOk 
= (bool)::WinSendMsg( GetHMenuOf(m_parentMenu
) 
 247                                  ,MPFROM2SHORT(GetRealId(), TRUE
) 
 248                                  ,MPFROM2SHORT(MIA_DISABLED
, FALSE
) 
 251         bOk 
= (bool)::WinSendMsg( GetHMenuOf(m_parentMenu
) 
 253                                  ,MPFROM2SHORT(GetRealId(), TRUE
) 
 254                                  ,MPFROM2SHORT(MIA_DISABLED
, MIA_DISABLED
) 
 258         wxLogLastError(wxT("EnableMenuItem")); 
 260     wxMenuItemBase::Enable(bEnable
); 
 261 } // end of wxMenuItem::Enable 
 263 void wxMenuItem::Check( 
 269     wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") ); 
 270     if (m_isChecked 
== bCheck
) 
 273     HMENU                           hMenu 
= GetHmenuOf(m_parentMenu
); 
 275     if (GetKind() == wxITEM_RADIO
) 
 278         // It doesn't make sense to uncheck a radio item - what would this do? 
 284         // Get the index of this item in the menu 
 286         const wxMenuItemList
&       rItems 
= m_parentMenu
->GetMenuItems(); 
 287         int                         nPos 
= rItems
.IndexOf(this); 
 289         wxCHECK_RET( nPos 
!= wxNOT_FOUND
 
 290                     ,_T("menuitem not found in the menu items list?") 
 294         // Get the radio group range 
 299         if (m_bIsRadioGroupStart
) 
 302             // We already have all information we need 
 305             nEnd   
= m_vRadioGroup
.m_nEnd
; 
 307         else // next radio group item 
 310             // Get the radio group end from the start item 
 312             nStart 
= m_vRadioGroup
.m_nStart
; 
 313             nEnd 
= rItems
.Item(nStart
)->GetData()->m_vRadioGroup
.m_nEnd
; 
 317         // Also uncheck all the other items in this radio group 
 319         wxMenuItemList::compatibility_iterator node 
= rItems
.Item(nStart
); 
 321         for (int n 
= nStart
; n 
<= nEnd 
&& node
; n
++) 
 327                              ,MPFROM2SHORT(n
, TRUE
) 
 328                              ,MPFROM2SHORT(MIA_CHECKED
, MIA_CHECKED
) 
 333                 node
->GetData()->m_isChecked 
= FALSE
; 
 336                              ,MPFROM2SHORT(n
, TRUE
) 
 337                              ,MPFROM2SHORT(MIA_CHECKED
, FALSE
) 
 340             node 
= node
->GetNext(); 
 346             bOk 
= (bool)::WinSendMsg( hMenu
 
 348                                      ,MPFROM2SHORT(GetRealId(), TRUE
) 
 349                                      ,MPFROM2SHORT(MIA_CHECKED
, MIA_CHECKED
) 
 352             bOk 
= (bool)::WinSendMsg( hMenu
 
 354                                      ,MPFROM2SHORT(GetRealId(), TRUE
) 
 355                                      ,MPFROM2SHORT(MIA_CHECKED
, FALSE
) 
 360         wxLogLastError(wxT("CheckMenuItem")); 
 362     wxMenuItemBase::Check(bCheck
); 
 363 } // end of wxMenuItem::Check 
 365 void wxMenuItem::SetText( const wxString
& rText 
) 
 368     // Don't do anything if label didn't change 
 371     wxString                        sText 
= wxPMTextToLabel(rText
); 
 375     wxMenuItemBase::SetText(sText
); 
 376     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetName(sText
)); 
 377 #if  wxUSE_OWNER_DRAWN 
 378     SetAccelString(rText
.AfterFirst(_T('\t'))); 
 379 #endif // wxUSE_OWNER_DRAWN 
 381     HWND                            hMenu 
= GetHmenuOf(m_parentMenu
); 
 383     wxCHECK_RET(hMenu
, wxT("menuitem without menu")); 
 386     m_parentMenu
->UpdateAccel(this); 
 387 #endif // wxUSE_ACCEL 
 389     USHORT   uId 
= (USHORT
)GetRealId(); 
 393     if (!::WinSendMsg( hMenu
 
 395                       ,MPFROM2SHORT(uId
, TRUE
) 
 399         wxLogLastError(wxT("GetMenuState")); 
 403         uFlagsOld 
= vItem
.afStyle
; 
 406             uFlagsOld 
|= MIS_SUBMENU
; 
 411 #if wxUSE_OWNER_DRAWN 
 414             uFlagsOld 
|= MIS_OWNERDRAW
; 
 420             uFlagsOld 
|= MIS_TEXT
; 
 421             pData 
= (BYTE
*)sText
.c_str(); 
 427         if (!::WinSendMsg( hMenu
 
 429                           ,MPFROM2SHORT(uId
, TRUE
) 
 433             wxLogLastError(wxT("ModifyMenu")); 
 439         if (::WinSendMsg( hMenu
 
 445             wxLogLastError(wxT("ModifyMenu")); 
 448 } // end of wxMenuItem::SetText 
 450 void wxMenuItem::SetCheckable( 
 454     wxMenuItemBase::SetCheckable(bCheckable
); 
 455     OWNER_DRAWN_ONLY(wxOwnerDrawn::SetCheckable(bCheckable
)); 
 456 } // end of wxMenuItem::SetCheckable 
 458 // ---------------------------------------------------------------------------- 
 460 // ---------------------------------------------------------------------------- 
 462 wxMenuItem
* wxMenuItemBase::New( 
 465 , const wxString
&                   rName
 
 466 , const wxString
&                   rHelp
 
 471     return new wxMenuItem( pParentMenu
 
 478 } // end of wxMenuItemBase::New