1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/menu.cpp 
   3 // Purpose:     wxMenu, wxMenuBar, wxMenuItem 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  26     #include "wx/ownerdrw.h" 
  29 #include "wx/os2/private.h" 
  31 // other standard headers 
  34 // ---------------------------------------------------------------------------- 
  36 // ---------------------------------------------------------------------------- 
  38 extern wxMenu
*                      wxCurrentPopupMenu
; 
  40 // ---------------------------------------------------------------------------- 
  42 // ---------------------------------------------------------------------------- 
  45 // The (popup) menu title has this special id 
  47 static const int                    idMenuTitle 
= -3; 
  50 // The unique ID for Menus 
  52 USHORT                              
wxMenu::m_nextMenuId 
= 0; 
  54 // ---------------------------------------------------------------------------- 
  56 // ---------------------------------------------------------------------------- 
  58     IMPLEMENT_DYNAMIC_CLASS(wxMenu
, wxEvtHandler
) 
  59     IMPLEMENT_DYNAMIC_CLASS(wxMenuBar
, wxEvtHandler
) 
  61 // ============================================================================ 
  63 // ============================================================================ 
  65 // --------------------------------------------------------------------------- 
  66 // wxMenu construction, adding and removing menu items 
  67 // --------------------------------------------------------------------------- 
  70 // Construct a menu with optional title (then use append) 
  75     m_nStartRadioGroup 
= -1; 
  78     // Create the menu (to be used as a submenu or a popup) 
  80     if ((m_hMenu 
=  ::WinCreateWindow( HWND_DESKTOP
 
  95         wxLogLastError(wxT("WinLoadMenu")); 
  97     m_vMenuData
.iPosition   
= 0; 
  98     m_vMenuData
.afStyle     
= MIS_SUBMENU 
| MIS_TEXT
; 
  99     m_vMenuData
.afAttribute 
= (USHORT
)0; 
 100     m_vMenuData
.id          
= m_nextMenuId
++; 
 101     m_vMenuData
.hwndSubMenu 
= m_hMenu
; 
 102     m_vMenuData
.hItem       
= NULLHANDLE
; 
 105     // If we have a title, insert it in the beginning of the menu 
 107     if (!m_title
.empty()) 
 116 } // end of wxMenu::Init 
 119 // The wxWindow destructor will take care of deleting the submenus. 
 124     // We should free PM resources only if PM doesn't do it for us 
 125     // which happens if we're attached to a menubar or a submenu of another 
 127     if (!IsAttached() && !GetParent()) 
 129         if (!::WinDestroyWindow((HWND
)GetHmenu()) ) 
 131             wxLogLastError(wxT("WinDestroyWindow")); 
 139     WX_CLEAR_ARRAY(m_vAccels
); 
 140 #endif // wxUSE_ACCEL 
 141 } // end of wxMenu::~wxMenu 
 145     // this will take effect during the next call to Append() 
 147 } // end of wxMenu::Break 
 150   wxMenuBarBase
*                    pMenubar
 
 153     wxMenuBase::Attach(pMenubar
); 
 155 } // end of wxMenu::Break; 
 159 int wxMenu::FindAccel( 
 164     size_t                          nCount 
= m_vAccels
.GetCount(); 
 166     for (n 
= 0; n 
< nCount
; n
++) 
 167         if (m_vAccels
[n
]->m_command 
== nId
) 
 170 } // end of wxMenu::FindAccel 
 172 void wxMenu::UpdateAccel( 
 176     if (pItem
->IsSubMenu()) 
 178         wxMenu
*                     pSubmenu 
= pItem
->GetSubMenu(); 
 179         wxMenuItemList::compatibility_iterator node 
= pSubmenu
->GetMenuItems().GetFirst(); 
 183             UpdateAccel(node
->GetData()); 
 184             node 
= node
->GetNext(); 
 187     else if (!pItem
->IsSeparator()) 
 190         // Recurse upwards: we should only modify m_accels of the top level 
 191         // menus, not of the submenus as wxMenuBar doesn't look at them 
 192         // (alternative and arguable cleaner solution would be to recurse 
 193         // downwards in GetAccelCount() and CopyAccels()) 
 197             GetParent()->UpdateAccel(pItem
); 
 202         // Find the (new) accel for this item 
 204         wxAcceleratorEntry
*         pAccel 
= wxAcceleratorEntry::Create(pItem
->GetItemLabel()); 
 207             pAccel
->m_command 
= pItem
->GetId(); 
 212         size_t                      n 
= FindAccel(pItem
->GetId()); 
 214         if (n 
== (size_t)wxNOT_FOUND
) 
 217             // No old, add new if any 
 220                 m_vAccels
.Add(pAccel
); 
 227             // Replace old with new or just remove the old one if no new 
 231                 m_vAccels
[n
] = pAccel
; 
 233                 m_vAccels
.RemoveAt(n
); 
 238             GetMenuBar()->RebuildAccelTable(); 
 241 } // wxMenu::UpdateAccel 
 243 #endif // wxUSE_ACCEL 
 246 // Append a new item or submenu to the menu 
 248 bool wxMenu::DoInsertOrAppend( wxMenuItem
* pItem
, 
 251     wxMenu
*    pSubmenu 
= pItem
->GetSubMenu(); 
 252     MENUITEM
&  rItem 
= (pSubmenu 
!= NULL
)?pSubmenu
->m_vMenuData
: 
 260 #endif // wxUSE_ACCEL 
 263     // If "Break" has just been called, insert a menu break before this item 
 264     // (and don't forget to reset the flag) 
 268         rItem
.afStyle 
|= MIS_BREAK
; 
 273     // Id is the numeric id for normal menu items and HMENU for submenus as 
 274     // required by ::MM_INSERTITEM message API 
 276     if (pSubmenu 
!= NULL
) 
 278         wxASSERT_MSG(pSubmenu
->GetHMenu(), wxT("invalid submenu")); 
 279         pSubmenu
->SetParent(this); 
 281         rItem
.iPosition 
= 0; // submenus have a 0 position 
 282         rItem
.id        
= (USHORT
)pSubmenu
->GetHMenu(); 
 283         rItem
.afStyle  
|= MIS_SUBMENU 
| MIS_TEXT
; 
 287         rItem
.id 
= (USHORT
)pItem
->GetId(); 
 292 #if wxUSE_OWNER_DRAWN 
 293     if (pItem
->IsOwnerDrawn()) 
 296         // Want to get {Measure|Draw}Item messages? 
 297         // item draws itself, passing pointer to data doesn't work in OS/2 
 298         // Will eventually need to set the image handle somewhere into vItem.hItem 
 300         rItem
.afStyle             
|= MIS_OWNERDRAW
; 
 302         rItem
.hItem                
= (HBITMAP
)pItem
->GetBitmap().GetHBITMAP(); 
 303         pItem
->m_vMenuData
.afStyle 
= rItem
.afStyle
; 
 304         pItem
->m_vMenuData
.hItem   
= rItem
.hItem
; 
 308     if (pItem
->IsSeparator()) 
 310         rItem
.afStyle 
= MIS_SEPARATOR
; 
 314         if (pItem
->GetId() == idMenuTitle
) 
 316             // Item is an unselectable title to be passed via pData 
 317             rItem
.afStyle 
= MIS_STATIC
; 
 322             // Menu is just a normal string (passed in data parameter) 
 324             rItem
.afStyle 
|= MIS_TEXT
; 
 326         pData 
= (char*) pItem
->GetItemLabel().wx_str(); 
 329     if (nPos 
== (size_t)-1) 
 331         rItem
.iPosition 
= MIT_END
; 
 335         rItem
.iPosition 
= (SHORT
)nPos
; 
 340     rc 
= (APIRET
)::WinSendMsg( GetHmenu() 
 345 #if wxUSE_OWNER_DRAWN 
 346     if (pItem
->IsOwnerDrawn()) 
 350         ::WinSendMsg( GetHmenu() 
 352                      ,MPFROM2SHORT( (USHORT
)pItem
->GetId() 
 360     if (rc 
== (APIRET
)MIT_MEMERROR 
|| rc 
== (APIRET
)MIT_ERROR
) 
 362         vError 
= ::WinGetLastError(vHabmain
); 
 363         sError 
= wxPMErrorToStr(vError
); 
 364         wxLogError(wxT("Error inserting or appending a menuitem. Error: %s\n"), sError
.c_str()); 
 365         wxLogLastError(wxT("Insert or AppendMenu")); 
 370     // If we're already attached to the menubar, we must update it 
 372     if (IsAttached() && GetMenuBar()->IsAttached()) 
 374         GetMenuBar()->Refresh(); 
 378 } // end of wxMenu::DoInsertOrAppend 
 380 void wxMenu::EndRadioGroup() 
 383     // We're not inside a radio group any longer 
 385     m_nStartRadioGroup 
= -1; 
 386 } // end of wxMenu::EndRadioGroup 
 388 wxMenuItem
* wxMenu::DoAppend( wxMenuItem
* pItem 
) 
 390     wxCHECK_MSG( pItem
, NULL
, wxT("NULL item in wxMenu::DoAppend") ); 
 394     if (pItem
->GetKind() == wxITEM_RADIO
) 
 396         int                         nCount 
= GetMenuItemCount(); 
 398         if (m_nStartRadioGroup 
== -1) 
 401             // Start a new radio group 
 403             m_nStartRadioGroup 
= nCount
; 
 406             // For now it has just one element 
 408             pItem
->SetAsRadioGroupStart(); 
 409             pItem
->SetRadioGroupEnd(m_nStartRadioGroup
); 
 412             // Ensure that we have a checked item in the radio group 
 416         else // extend the current radio group 
 419             // We need to update its end item 
 421             pItem
->SetRadioGroupStart(m_nStartRadioGroup
); 
 423             wxMenuItemList::compatibility_iterator node 
= GetMenuItems().Item(m_nStartRadioGroup
); 
 427                 node
->GetData()->SetRadioGroupEnd(nCount
); 
 431                 wxFAIL_MSG( wxT("where is the radio group start item?") ); 
 435     else // not a radio item 
 440     if (!wxMenuBase::DoAppend(pItem
) || !DoInsertOrAppend(pItem
)) 
 447         // Check the item initially 
 452 } // end of wxMenu::DoAppend 
 454 wxMenuItem
* wxMenu::DoInsert( 
 459     if ( wxMenuBase::DoInsert( nPos
 
 461              DoInsertOrAppend( pItem
 
 467 } // end of wxMenu::DoInsert 
 469 wxMenuItem
* wxMenu::DoRemove( 
 474     // We need to find the items position in the child list 
 477     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 479     for (nPos 
= 0; node
; nPos
++) 
 481         if (node
->GetData() == pItem
) 
 483         node 
= node
->GetNext(); 
 487     // DoRemove() (unlike Remove) can only be called for existing item! 
 489     wxCHECK_MSG(node
, NULL
, wxT("bug in wxMenu::Remove logic")); 
 493     // Remove the corresponding accel from the accel table 
 495     int                             n 
= FindAccel(pItem
->GetId()); 
 497     if (n 
!= wxNOT_FOUND
) 
 500         m_vAccels
.RemoveAt(n
); 
 503 #endif // wxUSE_ACCEL 
 505     // Remove the item from the menu 
 507     ::WinSendMsg( GetHmenu() 
 509                  ,MPFROM2SHORT(pItem
->GetId(), TRUE
) 
 512     if (IsAttached() && GetMenuBar()->IsAttached()) 
 515         // Otherwise, the chane won't be visible 
 517         GetMenuBar()->Refresh(); 
 521     // And from internal data structures 
 523     return wxMenuBase::DoRemove(pItem
); 
 524 } // end of wxMenu::DoRemove 
 526 // --------------------------------------------------------------------------- 
 527 // accelerator helpers 
 528 // --------------------------------------------------------------------------- 
 533 // Create the wxAcceleratorEntries for our accels and put them into provided 
 534 // array - return the number of accels we have 
 536 size_t wxMenu::CopyAccels( 
 537   wxAcceleratorEntry
*               pAccels
 
 540     size_t                          nCount 
= GetAccelCount(); 
 542     for (size_t n 
= 0; n 
< nCount
; n
++) 
 544         *pAccels
++ = *m_vAccels
[n
]; 
 547 } // end of wxMenu::CopyAccels 
 549 #endif // wxUSE_ACCEL 
 551 // --------------------------------------------------------------------------- 
 553 // --------------------------------------------------------------------------- 
 555 void wxMenu::SetTitle( const wxString
& rLabel 
) 
 557     bool bHasNoTitle 
= m_title
.empty(); 
 558     HWND hMenu 
= GetHmenu(); 
 565             if (!::WinSetWindowText(hMenu
, rLabel
.c_str())) 
 567                 wxLogLastError(wxT("SetMenuTitle")); 
 575             ::WinSendMsg( GetHmenu() 
 577                          ,MPFROM2SHORT(hMenu
, TRUE
) 
 586             if (!::WinSetWindowText(hMenu
, rLabel
.c_str())) 
 588                 wxLogLastError(wxT("SetMenuTitle")); 
 592 } // end of wxMenu::SetTitle 
 594 // --------------------------------------------------------------------------- 
 596 // --------------------------------------------------------------------------- 
 598 bool wxMenu::OS2Command( 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
[] 
 700 , long                              WXUNUSED(lStyle
) 
 705     m_titles
.Alloc(nCount
); 
 706     for ( int i 
= 0; i 
< nCount
; i
++ ) 
 708         m_menus
.Append(vMenus
[i
]); 
 709         m_titles
.Add(sTitles
[i
]); 
 710         vMenus
[i
]->Attach(this); 
 712 } // end of wxMenuBar::wxMenuBar 
 714 wxMenuBar::~wxMenuBar() 
 717     // We should free PM's resources only if PM doesn't do it for us 
 718     // which happens if we're attached to a frame 
 720     if (m_hMenu 
&& !IsAttached()) 
 722         ::WinDestroyWindow((HMENU
)m_hMenu
); 
 723         m_hMenu 
= (WXHMENU
)NULL
; 
 725 } // end of wxMenuBar::~wxMenuBar 
 727 // --------------------------------------------------------------------------- 
 729 // --------------------------------------------------------------------------- 
 731 void wxMenuBar::Refresh() 
 733     wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") ); 
 735     WinSendMsg(GetWinHwnd(m_menuBarFrame
), WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0); 
 736 } // end of wxMenuBar::Refresh 
 738 WXHMENU 
wxMenuBar::Create() 
 745     wxCHECK_MSG(!m_hMenu
, TRUE
, wxT("menubar already created")); 
 748     // Menubars should be associated with a frame otherwise they are popups 
 750     if (m_menuBarFrame 
!= NULL
) 
 751         hFrame 
= GetWinHwnd(m_menuBarFrame
); 
 753         hFrame 
= HWND_DESKTOP
; 
 755     // Create an empty menu and then fill it with insertions 
 757     if ((m_hMenu 
=  ::WinCreateWindow( hFrame
 
 760                                       ,MS_ACTIONBAR 
| WS_SYNCPAINT 
| WS_VISIBLE
 
 772         wxLogLastError(wxT("WinLoadMenu")); 
 776         size_t nCount 
= GetMenuCount(), i
; 
 777         wxMenuList::iterator it
; 
 778         for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
 786             // Set the parent and owner of the submenues to be the menubar, not the desktop 
 788             hSubMenu 
= (*it
)->m_vMenuData
.hwndSubMenu
; 
 789             if (!::WinSetParent((*it
)->m_vMenuData
.hwndSubMenu
, m_hMenu
, FALSE
)) 
 791                 vError 
= ::WinGetLastError(vHabmain
); 
 792                 sError 
= wxPMErrorToStr(vError
); 
 793                 wxLogError(wxT("Error setting parent for submenu. Error: %s\n"), sError
.c_str()); 
 797             if (!::WinSetOwner((*it
)->m_vMenuData
.hwndSubMenu
, m_hMenu
)) 
 799                 vError 
= ::WinGetLastError(vHabmain
); 
 800                 sError 
= wxPMErrorToStr(vError
); 
 801                 wxLogError(wxT("Error setting parent for submenu. Error: %s\n"), sError
.c_str()); 
 805             (*it
)->m_vMenuData
.iPosition 
= (SHORT
)i
; 
 807             rc 
= (APIRET
)::WinSendMsg(m_hMenu
, MM_INSERTITEM
, (MPARAM
)&(*it
)->m_vMenuData
, (MPARAM
)m_titles
[i
].wx_str()); 
 808             if (rc 
== (APIRET
)MIT_MEMERROR 
|| rc 
== (APIRET
)MIT_ERROR
) 
 810                 vError 
= ::WinGetLastError(vHabmain
); 
 811                 sError 
= wxPMErrorToStr(vError
); 
 812                 wxLogError(wxT("Error inserting or appending a menuitem. Error: %s\n"), sError
.c_str()); 
 818 } // end of wxMenuBar::Create 
 820 // --------------------------------------------------------------------------- 
 821 // wxMenuBar functions to work with the top level submenus 
 822 // --------------------------------------------------------------------------- 
 825 // NB: we don't support owner drawn top level items for now, if we do these 
 826 //     functions would have to be changed to use wxMenuItem as well 
 828 void wxMenuBar::EnableTop( 
 833     wxCHECK_RET(IsAttached(), wxT("doesn't work with unattached menubars")); 
 838        uFlag 
= MIA_DISABLED
; 
 840     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 841     if (nId 
== MIT_ERROR
) 
 843         wxLogLastError(wxT("LogLastError")); 
 846     ::WinSendMsg((HWND
)m_hMenu
, MM_SETITEMATTR
, MPFROM2SHORT(nId
, TRUE
), MPFROM2SHORT(MIA_DISABLED
, uFlag
)); 
 848 } // end of wxMenuBar::EnableTop 
 850 void wxMenuBar::SetMenuLabel( 
 852 , const wxString
&                   rLabel
 
 858     wxCHECK_RET(nPos 
< GetMenuCount(), wxT("invalid menu index")); 
 859     m_titles
[nPos
] = rLabel
; 
 866     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 867     if (nId 
== MIT_ERROR
) 
 869         wxLogLastError(wxT("LogLastError")); 
 872     if(!::WinSendMsg( (HWND
)m_hMenu
 
 874                      ,MPFROM2SHORT(nId
, TRUE
) 
 878         wxLogLastError(wxT("QueryItem")); 
 882     if (::WinSendMsg(GetHmenu(), MM_SETITEMTEXT
, MPFROMSHORT(nId
), (MPARAM
)rLabel
.wx_str())); 
 884         wxLogLastError(wxT("ModifyMenu")); 
 887 } // end of wxMenuBar::SetMenuLabel 
 889 wxString 
wxMenuBar::GetMenuLabel( 
 893     wxCHECK_MSG( nPos 
< GetMenuCount(), wxEmptyString
, 
 894                  wxT("invalid menu index in wxMenuBar::GetMenuLabel") ); 
 895     return m_titles
[nPos
]; 
 896 } // end of wxMenuBar::GetMenuLabel 
 898 // --------------------------------------------------------------------------- 
 899 // wxMenuBar construction 
 900 // --------------------------------------------------------------------------- 
 902 wxMenu
* wxMenuBar::Replace( 
 905 , const wxString
&                    rTitle
 
 909     wxString                         sTitle 
= wxPMTextToLabel(rTitle
); 
 910     wxMenu
*                          pMenuOld 
= wxMenuBarBase::Replace( nPos
 
 916     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 917     if (nId 
== MIT_ERROR
) 
 919         wxLogLastError(wxT("LogLastError")); 
 924     m_titles
[nPos
] = sTitle
; 
 927         ::WinSendMsg((HWND
)m_hMenu
, MM_REMOVEITEM
, MPFROM2SHORT(nId
, TRUE
), (MPARAM
)0); 
 928         ::WinSendMsg((HWND
)m_hMenu
, MM_INSERTITEM
, (MPARAM
)&pMenu
->m_vMenuData
, (MPARAM
)sTitle
.wx_str()); 
 931         if (pMenuOld
->HasAccels() || pMenu
->HasAccels()) 
 934             // Need to rebuild accell table 
 938 #endif // wxUSE_ACCEL 
 942 } // end of wxMenuBar::Replace 
 944 bool wxMenuBar::Insert( size_t          nPos
, 
 946                         const wxString
& rTitle 
) 
 948     wxString sTitle 
= wxPMTextToLabel(rTitle
); 
 950     if (!wxMenuBarBase::Insert( nPos
, pMenu
, sTitle 
)) 
 953     m_titles
.Insert( sTitle
, nPos 
); 
 957         pMenu
->m_vMenuData
.iPosition 
= (SHORT
)nPos
; 
 958         ::WinSendMsg( (HWND
)m_hMenu
 
 960                      ,(MPARAM
)&pMenu
->m_vMenuData
 
 961                      ,(MPARAM
)sTitle
.wx_str() 
 964         if (pMenu
->HasAccels()) 
 966             // need to rebuild accell table 
 969 #endif // wxUSE_ACCEL 
 974 } // end of wxMenuBar::Insert 
 976 bool wxMenuBar::Append( wxMenu
* pMenu
, 
 977                         const wxString
& rsTitle 
) 
 979     WXHMENU hSubmenu 
= pMenu 
? pMenu
->GetHMenu() : 0; 
 981     wxCHECK_MSG(hSubmenu
, false, wxT("can't append invalid menu to menubar")); 
 983     wxString sTitle 
= wxPMTextToLabel(rsTitle
); 
 985     if (!wxMenuBarBase::Append(pMenu
, sTitle
)) 
 988     m_titles
.Add(sTitle
); 
 992         pMenu
->m_vMenuData
.iPosition 
= MIT_END
; 
 993         ::WinSendMsg((HWND
)m_hMenu
, MM_INSERTITEM
, (MPARAM
)&pMenu
->m_vMenuData
, (MPARAM
)sTitle
.wx_str()); 
 995         if (pMenu
->HasAccels()) 
 998             // Need to rebuild accell table 
1000             RebuildAccelTable(); 
1002 #endif // wxUSE_ACCEL 
1006 } // end of wxMenuBar::Append 
1008 wxMenu
* wxMenuBar::Remove( 
1012     wxMenu
*                         pMenu 
= wxMenuBarBase::Remove(nPos
); 
1018     nId 
= SHORT1FROMMR(::WinSendMsg( (HWND
)GetHmenu() 
1019                                     ,MM_ITEMIDFROMPOSITION
 
1023     if (nId 
== MIT_ERROR
) 
1025         wxLogLastError(wxT("LogLastError")); 
1030         ::WinSendMsg( (HWND
)GetHmenu() 
1032                      ,MPFROM2SHORT(nId
, TRUE
) 
1037         if (pMenu
->HasAccels()) 
1040             // Need to rebuild accell table 
1042             RebuildAccelTable(); 
1044 #endif // wxUSE_ACCEL 
1047     m_titles
.RemoveAt(nPos
); 
1049 } // end of wxMenuBar::Remove 
1053 void wxMenuBar::RebuildAccelTable() 
1056     // Merge the accelerators of all menus into one accel table 
1058     size_t                          nAccelCount 
= 0; 
1060     size_t                          nCount 
= GetMenuCount(); 
1061     wxMenuList::iterator it
; 
1062     for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1064         nAccelCount 
+= (*it
)->GetAccelCount(); 
1069         wxAcceleratorEntry
*         pAccelEntries 
= new wxAcceleratorEntry
[nAccelCount
]; 
1072         for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1074             nAccelCount 
+= (*it
)->CopyAccels(&pAccelEntries
[nAccelCount
]); 
1076         m_vAccelTable 
= wxAcceleratorTable( nAccelCount
 
1079         delete [] pAccelEntries
; 
1081 } // end of wxMenuBar::RebuildAccelTable 
1083 #endif // wxUSE_ACCEL 
1085 void wxMenuBar::Attach( 
1089     wxMenuBarBase::Attach(pFrame
); 
1092     RebuildAccelTable(); 
1094     // Ensure the accelerator table is set to the frame (not the client!) 
1096     if (!::WinSetAccelTable( vHabmain
 
1097                             ,m_vAccelTable
.GetHACCEL() 
1098                             ,(HWND
)pFrame
->GetFrame() 
1101         wxLogLastError(wxT("WinSetAccelTable")); 
1103 #endif // wxUSE_ACCEL 
1104 } // end of wxMenuBar::Attach 
1106 void wxMenuBar::Detach() 
1108     ::WinDestroyWindow((HWND
)m_hMenu
); 
1109     m_hMenu 
= (WXHMENU
)NULL
; 
1110     m_menuBarFrame 
= NULL
; 
1111 } // end of wxMenuBar::Detach 
1113 // --------------------------------------------------------------------------- 
1114 // wxMenuBar searching for menu items 
1115 // --------------------------------------------------------------------------- 
1118 // Find the itemString in menuString, and return the item id or wxNOT_FOUND 
1120 int wxMenuBar::FindMenuItem( 
1121   const wxString
&                   rMenuString
 
1122 , const wxString
&                   rItemString
 
1125     wxString                        sMenuLabel 
= wxStripMenuCodes(rMenuString
); 
1126     size_t                          nCount 
= GetMenuCount(), i
; 
1127     wxMenuList::const_iterator it
; 
1128     for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1130         wxString                    sTitle 
= wxStripMenuCodes(m_titles
[i
]); 
1132         if (rMenuString 
== sTitle
) 
1133             return (*it
)->FindItem(rItemString
); 
1136 } // end of wxMenuBar::FindMenuItem 
1138 wxMenuItem
* wxMenuBar::FindItem( 
1140 , wxMenu
**                          ppItemMenu
 
1146     wxMenuItem
*                     pItem 
= NULL
; 
1147     size_t                          nCount 
= GetMenuCount(), i
; 
1148     wxMenuList::const_iterator it
; 
1149     for (i 
= 0, it 
= m_menus
.begin(); !pItem 
&& (i 
< nCount
); i
++, it
++) 
1151         pItem 
= (*it
)->FindItem( nId
 
1156 } // end of wxMenuBar::FindItem 
1158 wxMenuItem
* wxMenuBar::FindItem( 
1161 , wxMenu
**                          ppItemMenu
 
1167     wxMenuItem
*                     pItem 
= NULL
; 
1168     size_t                          nCount 
= GetMenuCount(), i
; 
1169     wxMenuList::const_iterator it
; 
1170     for (i 
= 0, it 
= m_menus
.begin(); !pItem 
&& (i 
< nCount
); i
++, it
++) 
1172         pItem 
= (*it
)->FindItem( nId
 
1178 } // end of wxMenuBar::FindItem