1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxMenu, wxMenuBar, wxMenuItem 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  13     #pragma implementation "menu.h" 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  29     #include "wx/ownerdrw.h" 
  32 #include "wx/os2/private.h" 
  34 // other standard headers 
  37 // ---------------------------------------------------------------------------- 
  39 // ---------------------------------------------------------------------------- 
  41 extern wxMenu
*                      wxCurrentPopupMenu
; 
  43 // ---------------------------------------------------------------------------- 
  45 // ---------------------------------------------------------------------------- 
  48 // The (popup) menu title has this special id 
  50 static const int                    idMenuTitle 
= -3; 
  53 // The unique ID for Menus 
  55 USHORT                              
wxMenu::m_nextMenuId 
= 0; 
  57 // ---------------------------------------------------------------------------- 
  59 // ---------------------------------------------------------------------------- 
  61     IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
) 
  62     IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
) 
  64 // ============================================================================ 
  66 // ============================================================================ 
  68 // --------------------------------------------------------------------------- 
  69 // wxMenu construction, adding and removing menu items 
  70 // --------------------------------------------------------------------------- 
  73 // Construct a menu with optional title (then use append) 
  78     m_nStartRadioGroup 
= -1; 
  81     // Create the menu (to be used as a submenu or a popup) 
  83     if ((m_hMenu 
=  ::WinCreateWindow( HWND_DESKTOP
 
  98         wxLogLastError("WinLoadMenu"); 
 100     m_vMenuData
.iPosition   
= 0; 
 101     m_vMenuData
.afStyle     
= MIS_SUBMENU 
| MIS_TEXT
; 
 102     m_vMenuData
.afAttribute 
= (USHORT
)0; 
 103     m_vMenuData
.id          
= m_nextMenuId
++; 
 104     m_vMenuData
.hwndSubMenu 
= m_hMenu
; 
 105     m_vMenuData
.hItem       
= NULLHANDLE
; 
 108     // If we have a title, insert it in the beginning of the menu 
 110     if (!m_title
.IsEmpty()) 
 119 } // end of wxMenu::Init 
 122 // The wxWindow destructor will take care of deleting the submenus. 
 127     // We should free PM resources only if PM doesn't do it for us 
 128     // which happens if we're attached to a menubar or a submenu of another 
 130     if (!IsAttached() && !GetParent()) 
 132         if (!::WinDestroyWindow((HWND
)GetHmenu()) ) 
 134             wxLogLastError("WinDestroyWindow"); 
 142     WX_CLEAR_ARRAY(m_vAccels
); 
 143 #endif // wxUSE_ACCEL 
 144 } // end of wxMenu::~wxMenu 
 148     // this will take effect during the next call to Append() 
 150 } // end of wxMenu::Break 
 153   wxMenuBarBase
*                    pMenubar
 
 156     wxMenuBase::Attach(pMenubar
); 
 158 } // end of wxMenu::Break; 
 162 int wxMenu::FindAccel( 
 167     size_t                          nCount 
= m_vAccels
.GetCount(); 
 169     for (n 
= 0; n 
< nCount
; n
++) 
 170         if (m_vAccels
[n
]->m_command 
== nId
) 
 173 } // end of wxMenu::FindAccel 
 175 void wxMenu::UpdateAccel( 
 179     if (pItem
->IsSubMenu()) 
 181         wxMenu
*                     pSubmenu 
= pItem
->GetSubMenu(); 
 182         wxMenuItemList::compatibility_iterator node 
= pSubmenu
->GetMenuItems().GetFirst(); 
 186             UpdateAccel(node
->GetData()); 
 187             node 
= node
->GetNext(); 
 190     else if (!pItem
->IsSeparator()) 
 193         // Find the (new) accel for this item 
 195         wxAcceleratorEntry
*         pAccel 
= wxGetAccelFromString(pItem
->GetText()); 
 198             pAccel
->m_command 
= pItem
->GetId(); 
 203         size_t                      n 
= FindAccel(pItem
->GetId()); 
 205         if (n 
== (size_t)wxNOT_FOUND
) 
 208             // No old, add new if any 
 211                 m_vAccels
.Add(pAccel
); 
 218             // Replace old with new or just remove the old one if no new 
 222                 m_vAccels
[n
] = pAccel
; 
 224                 m_vAccels
.RemoveAt(n
); 
 229             GetMenuBar()->RebuildAccelTable(); 
 232 } // wxMenu::UpdateAccel 
 234 #endif // wxUSE_ACCEL 
 237 // Append a new item or submenu to the menu 
 239 bool wxMenu::DoInsertOrAppend( 
 244     wxMenu
*                         pSubmenu 
= pItem
->GetSubMenu(); 
 245     MENUITEM
&                       rItem 
= (pSubmenu 
!= NULL
)?pSubmenu
->m_vMenuData
: 
 253 #endif // wxUSE_ACCEL 
 256     // If "Break" has just been called, insert a menu break before this item 
 257     // (and don't forget to reset the flag) 
 261         rItem
.afStyle 
|= MIS_BREAK
; 
 266     // Id is the numeric id for normal menu items and HMENU for submenus as 
 267     // required by ::MM_INSERTITEM message API 
 269     if (pSubmenu 
!= NULL
) 
 271         wxASSERT_MSG(pSubmenu
->GetHMenu(), wxT("invalid submenu")); 
 272         pSubmenu
->SetParent(this); 
 274         rItem
.iPosition 
= 0; // submenus have a 0 position 
 275         rItem
.id        
= (USHORT
)pSubmenu
->GetHMenu(); 
 276         rItem
.afStyle  
|= MIS_SUBMENU 
| MIS_TEXT
; 
 280         rItem
.id 
= pItem
->GetId(); 
 285 #if wxUSE_OWNER_DRAWN 
 286     if (pItem
->IsOwnerDrawn()) 
 289         // Want to get {Measure|Draw}Item messages? 
 290         // item draws itself, passing pointer to data doesn't work in OS/2 
 291         // Will eventually need to set the image handle somewhere into vItem.hItem 
 293         rItem
.afStyle             
|= MIS_OWNERDRAW
; 
 295         rItem
.hItem                
= (HBITMAP
)pItem
->GetBitmap().GetHBITMAP(); 
 296         pItem
->m_vMenuData
.afStyle 
= rItem
.afStyle
; 
 297         pItem
->m_vMenuData
.hItem   
= rItem
.hItem
; 
 301     if (pItem
->IsSeparator()) 
 303         rItem
.afStyle 
= MIS_SEPARATOR
; 
 307         if (pItem
->GetId() == idMenuTitle
) 
 309             // Item is an unselectable title to be passed via pData 
 310             rItem
.afStyle 
= MIS_STATIC
; 
 315             // Menu is just a normal string (passed in data parameter) 
 317             rItem
.afStyle 
|= MIS_TEXT
; 
 319         pData 
= (char*)pItem
->GetText().c_str(); 
 322     if (nPos 
== (size_t)-1) 
 324         rItem
.iPosition 
= MIT_END
; 
 328         rItem
.iPosition 
= nPos
; 
 333     rc 
= (APIRET
)::WinSendMsg( GetHmenu() 
 338 #if wxUSE_OWNER_DRAWN 
 339     if (pItem
->IsOwnerDrawn()) 
 343         ::WinSendMsg( GetHmenu() 
 345                      ,MPFROM2SHORT( (USHORT
)pItem
->GetId() 
 352     if (rc 
== (APIRET
)MIT_MEMERROR 
|| rc 
== (APIRET
)MIT_ERROR
) 
 354         vError 
= ::WinGetLastError(vHabmain
); 
 355         sError 
= wxPMErrorToStr(vError
); 
 356         wxLogError("Error inserting or appending a menuitem. Error: %s\n", sError
.c_str()); 
 357         wxLogLastError("Insert or AppendMenu"); 
 363         // If we're already attached to the menubar, we must update it 
 365         if (IsAttached() && GetMenuBar()->IsAttached()) 
 367             GetMenuBar()->Refresh(); 
 372 } // end of wxMenu::DoInsertOrAppend 
 374 void wxMenu::EndRadioGroup() 
 377     // We're not inside a radio group any longer 
 379     m_nStartRadioGroup 
= -1; 
 380 } // end of wxMenu::EndRadioGroup 
 382 wxMenuItem
* wxMenu::DoAppend( 
 386     wxCHECK_MSG( pItem
, NULL
, _T("NULL item in wxMenu::DoAppend") ); 
 390     if (pItem
->GetKind() == wxITEM_RADIO
) 
 392         int                         nCount 
= GetMenuItemCount(); 
 394         if (m_nStartRadioGroup 
== -1) 
 397             // Start a new radio group 
 399             m_nStartRadioGroup 
= nCount
; 
 402             // For now it has just one element 
 404             pItem
->SetAsRadioGroupStart(); 
 405             pItem
->SetRadioGroupEnd(m_nStartRadioGroup
); 
 408             // Ensure that we have a checked item in the radio group 
 412         else // extend the current radio group 
 415             // We need to update its end item 
 417             pItem
->SetRadioGroupStart(m_nStartRadioGroup
); 
 419             wxMenuItemList::compatibility_iterator node 
= GetMenuItems().Item(m_nStartRadioGroup
); 
 423                 node
->GetData()->SetRadioGroupEnd(nCount
); 
 427                 wxFAIL_MSG( _T("where is the radio group start item?") ); 
 431     else // not a radio item 
 436     if (!wxMenuBase::DoAppend(pItem
) || !DoInsertOrAppend(pItem
)) 
 443         // Check the item initially 
 448 } // end of wxMenu::DoAppend 
 450 wxMenuItem
* wxMenu::DoInsert( 
 455     if ( wxMenuBase::DoInsert( nPos
 
 457              DoInsertOrAppend( pItem
 
 463 } // end of wxMenu::DoInsert 
 465 wxMenuItem
* wxMenu::DoRemove( 
 470     // We need to find the items position in the child list 
 473     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 475     for (nPos 
= 0; node
; nPos
++) 
 477         if (node
->GetData() == pItem
) 
 479         node 
= node
->GetNext(); 
 483     // DoRemove() (unlike Remove) can only be called for existing item! 
 485     wxCHECK_MSG(node
, NULL
, wxT("bug in wxMenu::Remove logic")); 
 489     // Remove the corresponding accel from the accel table 
 491     int                             n 
= FindAccel(pItem
->GetId()); 
 493     if (n 
!= wxNOT_FOUND
) 
 496         m_vAccels
.RemoveAt(n
); 
 499 #endif // wxUSE_ACCEL 
 501     // Remove the item from the menu 
 503     ::WinSendMsg( GetHmenu() 
 505                  ,MPFROM2SHORT(pItem
->GetId(), TRUE
) 
 508     if (IsAttached() && GetMenuBar()->IsAttached()) 
 511         // Otherwise, the chane won't be visible 
 513         GetMenuBar()->Refresh(); 
 517     // And from internal data structures 
 519     return wxMenuBase::DoRemove(pItem
); 
 520 } // end of wxMenu::DoRemove 
 522 // --------------------------------------------------------------------------- 
 523 // accelerator helpers 
 524 // --------------------------------------------------------------------------- 
 529 // Create the wxAcceleratorEntries for our accels and put them into provided 
 530 // array - return the number of accels we have 
 532 size_t wxMenu::CopyAccels( 
 533   wxAcceleratorEntry
*               pAccels
 
 536     size_t                          nCount 
= GetAccelCount(); 
 538     for (size_t n 
= 0; n 
< nCount
; n
++) 
 540         *pAccels
++ = *m_vAccels
[n
]; 
 543 } // end of wxMenu::CopyAccels 
 545 #endif // wxUSE_ACCEL 
 547 // --------------------------------------------------------------------------- 
 549 // --------------------------------------------------------------------------- 
 551 void wxMenu::SetTitle( 
 552   const wxString
&                   rLabel
 
 555     bool                            bHasNoTitle 
= m_title
.IsEmpty(); 
 556     HWND                            hMenu 
= GetHmenu(); 
 561         if (!rLabel
.IsEmpty()) 
 563             if (!::WinSetWindowText(hMenu
, rLabel
.c_str())) 
 565                 wxLogLastError("SetMenuTitle"); 
 571         if (rLabel
.IsEmpty() ) 
 573             ::WinSendMsg( GetHmenu() 
 575                          ,MPFROM2SHORT(hMenu
, TRUE
) 
 584             if (!::WinSetWindowText(hMenu
, rLabel
.c_str())) 
 586                 wxLogLastError("SetMenuTitle"); 
 590 } // end of wxMenu::SetTitle 
 592 // --------------------------------------------------------------------------- 
 594 // --------------------------------------------------------------------------- 
 596 bool wxMenu::OS2Command( 
 597   WXUINT                            
WXUNUSED(uParam
) 
 602     // Ignore commands from the menu title 
 605     if (vId 
!= (WXWORD
)idMenuTitle
) 
 608                   ,(int)::WinSendMsg( GetHmenu() 
 616 } // end of wxMenu::OS2Command 
 618 // --------------------------------------------------------------------------- 
 620 // --------------------------------------------------------------------------- 
 622 wxWindow
* wxMenu::GetWindow() const 
 624     if (m_invokingWindow 
!= NULL
) 
 625         return m_invokingWindow
; 
 626     else if ( GetMenuBar() != NULL
) 
 627         return GetMenuBar()->GetFrame(); 
 630 } // end of wxMenu::GetWindow 
 632 // recursive search for item by id 
 633 wxMenuItem
* wxMenu::FindItem( 
 636 , wxMenu
**                          ppItemMenu
 
 642     wxMenuItem
*                     pItem 
= NULL
; 
 644     for ( wxMenuItemList::compatibility_iterator node 
= m_items
.GetFirst(); 
 646           node 
= node
->GetNext() ) 
 648         pItem 
= node
->GetData(); 
 650         if ( pItem
->GetId() == nItemId 
&& pItem
->m_vMenuData
.hItem 
== hItem
) 
 653                 *ppItemMenu 
= (wxMenu 
*)this; 
 655         else if ( pItem
->IsSubMenu() ) 
 657             pItem 
= pItem
->GetSubMenu()->FindItem( nItemId
 
 666             // don't exit the loop 
 671 } // end of wxMenu::FindItem 
 673 // --------------------------------------------------------------------------- 
 675 // --------------------------------------------------------------------------- 
 677 void wxMenuBar::Init() 
 679     m_eventHandler 
= this; 
 680     m_menuBarFrame 
= NULL
; 
 682 } // end of wxMenuBar::Init 
 684 wxMenuBar::wxMenuBar() 
 687 } // end of wxMenuBar::wxMenuBar 
 689 wxMenuBar::wxMenuBar( 
 690  long                               WXUNUSED(lStyle
) 
 694 } // end of wxMenuBar::wxMenuBar 
 696 wxMenuBar::wxMenuBar( 
 699 , const wxString                    sTitles
[] 
 704     m_titles
.Alloc(nCount
); 
 705     for ( int i 
= 0; i 
< nCount
; i
++ ) 
 707         m_menus
.Append(vMenus
[i
]); 
 708         m_titles
.Add(sTitles
[i
]); 
 709         vMenus
[i
]->Attach(this); 
 711 } // end of wxMenuBar::wxMenuBar 
 713 wxMenuBar::~wxMenuBar() 
 716     // We should free PM's resources only if PM doesn't do it for us 
 717     // which happens if we're attached to a frame 
 719     if (m_hMenu 
&& !IsAttached()) 
 721         ::WinDestroyWindow((HMENU
)m_hMenu
); 
 722         m_hMenu 
= (WXHMENU
)NULL
; 
 724 } // end of wxMenuBar::~wxMenuBar 
 726 // --------------------------------------------------------------------------- 
 728 // --------------------------------------------------------------------------- 
 730 void wxMenuBar::Refresh() 
 732     wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") ); 
 734     WinSendMsg(GetWinHwnd(m_menuBarFrame
), WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0); 
 735 } // end of wxMenuBar::Refresh 
 737 WXHMENU 
wxMenuBar::Create() 
 744     wxCHECK_MSG(!m_hMenu
, TRUE
, wxT("menubar already created")); 
 747     // Menubars should be associated with a frame otherwise they are popups 
 749     if (m_menuBarFrame 
!= NULL
) 
 750         hFrame 
= GetWinHwnd(m_menuBarFrame
); 
 752         hFrame 
= HWND_DESKTOP
; 
 754     // Create an empty menu and then fill it with insertions 
 756     if ((m_hMenu 
=  ::WinCreateWindow( hFrame
 
 759                                       ,MS_ACTIONBAR 
| WS_SYNCPAINT 
| WS_VISIBLE
 
 771         wxLogLastError("WinLoadMenu"); 
 775         size_t                      nCount 
= GetMenuCount(), i
; 
 776         wxMenuList::iterator it
; 
 777         for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
 785             // Set the parent and owner of the submenues to be the menubar, not the desktop 
 787             hSubMenu 
= (*it
)->m_vMenuData
.hwndSubMenu
; 
 788             if (!::WinSetParent((*it
)->m_vMenuData
.hwndSubMenu
, m_hMenu
, FALSE
)) 
 790                 vError 
= ::WinGetLastError(vHabmain
); 
 791                 sError 
= wxPMErrorToStr(vError
); 
 792                 wxLogError("Error setting parent for submenu. Error: %s\n", sError
.c_str()); 
 796             if (!::WinSetOwner((*it
)->m_vMenuData
.hwndSubMenu
, m_hMenu
)) 
 798                 vError 
= ::WinGetLastError(vHabmain
); 
 799                 sError 
= wxPMErrorToStr(vError
); 
 800                 wxLogError("Error setting parent for submenu. Error: %s\n", sError
.c_str()); 
 804             (*it
)->m_vMenuData
.iPosition 
= i
; 
 806             rc 
= (APIRET
)::WinSendMsg(m_hMenu
, MM_INSERTITEM
, (MPARAM
)&(*it
)->m_vMenuData
, (MPARAM
)m_titles
[i
].c_str()); 
 807             if (rc 
== (APIRET
)MIT_MEMERROR 
|| rc 
== (APIRET
)MIT_ERROR
) 
 809                 vError 
= ::WinGetLastError(vHabmain
); 
 810                 sError 
= wxPMErrorToStr(vError
); 
 811                 wxLogError("Error inserting or appending a menuitem. Error: %s\n", sError
.c_str()); 
 817 } // end of wxMenuBar::Create 
 819 // --------------------------------------------------------------------------- 
 820 // wxMenuBar functions to work with the top level submenus 
 821 // --------------------------------------------------------------------------- 
 824 // NB: we don't support owner drawn top level items for now, if we do these 
 825 //     functions would have to be changed to use wxMenuItem as well 
 827 void wxMenuBar::EnableTop( 
 832     wxCHECK_RET(IsAttached(), wxT("doesn't work with unattached menubars")); 
 837        uFlag 
= MIA_DISABLED
; 
 839     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 840     if (nId 
== MIT_ERROR
) 
 842         wxLogLastError("LogLastError"); 
 845     ::WinSendMsg((HWND
)m_hMenu
, MM_SETITEMATTR
, MPFROM2SHORT(nId
, TRUE
), MPFROM2SHORT(MIA_DISABLED
, uFlag
)); 
 847 } // end of wxMenuBar::EnableTop 
 849 void wxMenuBar::SetLabelTop( 
 851 , const wxString
&                   rLabel
 
 857     wxCHECK_RET(nPos 
< GetMenuCount(), wxT("invalid menu index")); 
 858     m_titles
[nPos
] = rLabel
; 
 865     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 866     if (nId 
== MIT_ERROR
) 
 868         wxLogLastError("LogLastError"); 
 871     if(!::WinSendMsg( (HWND
)m_hMenu
 
 873                      ,MPFROM2SHORT(nId
, TRUE
) 
 877         wxLogLastError("QueryItem"); 
 881     if (::WinSendMsg(GetHmenu(), MM_SETITEMTEXT
, MPFROMSHORT(nId
), (MPARAM
)rLabel
.c_str())); 
 883         wxLogLastError("ModifyMenu"); 
 886 } // end of wxMenuBar::SetLabelTop 
 888 wxString 
wxMenuBar::GetLabelTop( 
 892     wxCHECK_MSG( nPos 
< GetMenuCount(), wxEmptyString
, 
 893                  wxT("invalid menu index in wxMenuBar::GetLabelTop") ); 
 894     return m_titles
[nPos
]; 
 895 } // end of wxMenuBar::GetLabelTop 
 897 // --------------------------------------------------------------------------- 
 898 // wxMenuBar construction 
 899 // --------------------------------------------------------------------------- 
 901 wxMenu
* wxMenuBar::Replace( 
 904 , const wxString
&                    rTitle
 
 908     wxString                         sTitle 
= wxPMTextToLabel(rTitle
); 
 909     wxMenu
*                          pMenuOld 
= wxMenuBarBase::Replace( nPos
 
 915     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 916     if (nId 
== MIT_ERROR
) 
 918         wxLogLastError("LogLastError"); 
 923     m_titles
[nPos
] = sTitle
; 
 926         ::WinSendMsg((HWND
)m_hMenu
, MM_REMOVEITEM
, MPFROM2SHORT(nId
, TRUE
), (MPARAM
)0); 
 927         ::WinSendMsg((HWND
)m_hMenu
, MM_INSERTITEM
, (MPARAM
)&pMenu
->m_vMenuData
, (MPARAM
)sTitle
.c_str()); 
 930         if (pMenuOld
->HasAccels() || pMenu
->HasAccels()) 
 933             // Need to rebuild accell table 
 937 #endif // wxUSE_ACCEL 
 941 } // end of wxMenuBar::Replace 
 943 bool wxMenuBar::Insert( 
 946 , const wxString
&                   rTitle
 
 949     wxString                        sTitle 
= wxPMTextToLabel(rTitle
); 
 951     if (!wxMenuBarBase::Insert( nPos
 
 957     m_titles
.Insert( sTitle
 
 963         pMenu
->m_vMenuData
.iPosition 
= nPos
; 
 964         ::WinSendMsg( (HWND
)m_hMenu
 
 966                      ,(MPARAM
)&pMenu
->m_vMenuData
 
 967                      ,(MPARAM
)sTitle
.c_str() 
 970         if (pMenu
->HasAccels()) 
 972             // need to rebuild accell table 
 975 #endif // wxUSE_ACCEL 
 979 } // end of wxMenuBar::Insert 
 981 bool wxMenuBar::Append( 
 983 , const wxString
&                   rsTitle
 
 986     WXHMENU                         hSubmenu 
= pMenu 
? pMenu
->GetHMenu() : 0; 
 988     wxCHECK_MSG(hSubmenu
, FALSE
, wxT("can't append invalid menu to menubar")); 
 990     wxString                        sTitle 
= wxPMTextToLabel(rsTitle
); 
 992     if (!wxMenuBarBase::Append(pMenu
, sTitle
)) 
 995     m_titles
.Add(sTitle
); 
 999         pMenu
->m_vMenuData
.iPosition 
= MIT_END
; 
1000         ::WinSendMsg((HWND
)m_hMenu
, MM_INSERTITEM
, (MPARAM
)&pMenu
->m_vMenuData
, (MPARAM
)sTitle
.c_str()); 
1002         if (pMenu
->HasAccels()) 
1005             // Need to rebuild accell table 
1007             RebuildAccelTable(); 
1009 #endif // wxUSE_ACCEL 
1013 } // end of wxMenuBar::Append 
1015 wxMenu
* wxMenuBar::Remove( 
1019     wxMenu
*                         pMenu 
= wxMenuBarBase::Remove(nPos
); 
1025     nId 
= SHORT1FROMMR(::WinSendMsg( (HWND
)GetHmenu() 
1026                                     ,MM_ITEMIDFROMPOSITION
 
1030     if (nId 
== MIT_ERROR
) 
1032         wxLogLastError("LogLastError"); 
1037         ::WinSendMsg( (HWND
)GetHmenu() 
1039                      ,MPFROM2SHORT(nId
, TRUE
) 
1044         if (pMenu
->HasAccels()) 
1047             // Need to rebuild accell table 
1049             RebuildAccelTable(); 
1051 #endif // wxUSE_ACCEL 
1054     m_titles
.RemoveAt(nPos
); 
1056 } // end of wxMenuBar::Remove 
1060 void wxMenuBar::RebuildAccelTable() 
1063     // Merge the accelerators of all menus into one accel table 
1065     size_t                          nAccelCount 
= 0; 
1067     size_t                          nCount 
= GetMenuCount(); 
1068     wxMenuList::iterator it
; 
1069     for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1071         nAccelCount 
+= (*it
)->GetAccelCount(); 
1076         wxAcceleratorEntry
*         pAccelEntries 
= new wxAcceleratorEntry
[nAccelCount
]; 
1079         for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1081             nAccelCount 
+= (*it
)->CopyAccels(&pAccelEntries
[nAccelCount
]); 
1083         m_vAccelTable 
= wxAcceleratorTable( nAccelCount
 
1086         delete [] pAccelEntries
; 
1088 } // end of wxMenuBar::RebuildAccelTable 
1090 #endif // wxUSE_ACCEL 
1092 void wxMenuBar::Attach( 
1096     wxMenuBarBase::Attach(pFrame
); 
1099     RebuildAccelTable(); 
1101     // Ensure the accelerator table is set to the frame (not the client!) 
1103     if (!::WinSetAccelTable( vHabmain
 
1104                             ,m_vAccelTable
.GetHACCEL() 
1105                             ,(HWND
)pFrame
->GetFrame() 
1107         wxLogLastError("WinSetAccelTable"); 
1108 #endif // wxUSE_ACCEL 
1109 } // end of wxMenuBar::Attach 
1111 void wxMenuBar::Detach() 
1113     ::WinDestroyWindow((HWND
)m_hMenu
); 
1114     m_hMenu 
= (WXHMENU
)NULL
; 
1115     m_menuBarFrame 
= NULL
; 
1116 } // end of wxMenuBar::Detach 
1118 // --------------------------------------------------------------------------- 
1119 // wxMenuBar searching for menu items 
1120 // --------------------------------------------------------------------------- 
1123 // Find the itemString in menuString, and return the item id or wxNOT_FOUND 
1125 int wxMenuBar::FindMenuItem( 
1126   const wxString
&                   rMenuString
 
1127 , const wxString
&                   rItemString
 
1130     wxString                        sMenuLabel 
= wxStripMenuCodes(rMenuString
); 
1131     size_t                          nCount 
= GetMenuCount(), i
; 
1132     wxMenuList::const_iterator it
; 
1133     for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1135         wxString                    sTitle 
= wxStripMenuCodes(m_titles
[i
]); 
1137         if (rMenuString 
== sTitle
) 
1138             return (*it
)->FindItem(rItemString
); 
1141 } // end of wxMenuBar::FindMenuItem 
1143 wxMenuItem
* wxMenuBar::FindItem( 
1145 , wxMenu
**                          ppItemMenu
 
1151     wxMenuItem
*                     pItem 
= NULL
; 
1152     size_t                          nCount 
= GetMenuCount(), i
; 
1153     wxMenuList::const_iterator it
; 
1154     for (i 
= 0, it 
= m_menus
.begin(); !pItem 
&& (i 
< nCount
); i
++, it
++) 
1156         pItem 
= (*it
)->FindItem( nId
 
1161 } // end of wxMenuBar::FindItem 
1163 wxMenuItem
* wxMenuBar::FindItem( 
1166 , wxMenu
**                          ppItemMenu
 
1172     wxMenuItem
*                     pItem 
= NULL
; 
1173     size_t                          nCount 
= GetMenuCount(), i
; 
1174     wxMenuList::const_iterator it
; 
1175     for (i 
= 0, it 
= m_menus
.begin(); !pItem 
&& (i 
< nCount
); i
++, it
++) 
1177         pItem 
= (*it
)->FindItem( nId
 
1183 } // end of wxMenuBar::FindItem