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 // ============================================================================ 
  60 // ============================================================================ 
  62 // --------------------------------------------------------------------------- 
  63 // wxMenu construction, adding and removing menu items 
  64 // --------------------------------------------------------------------------- 
  67 // Construct a menu with optional title (then use append) 
  72     m_nStartRadioGroup 
= -1; 
  75     // Create the menu (to be used as a submenu or a popup) 
  77     if ((m_hMenu 
=  ::WinCreateWindow( HWND_DESKTOP
 
  92         wxLogLastError(wxT("WinLoadMenu")); 
  94     m_vMenuData
.iPosition   
= 0; 
  95     m_vMenuData
.afStyle     
= MIS_SUBMENU 
| MIS_TEXT
; 
  96     m_vMenuData
.afAttribute 
= (USHORT
)0; 
  97     m_vMenuData
.id          
= m_nextMenuId
++; 
  98     m_vMenuData
.hwndSubMenu 
= m_hMenu
; 
  99     m_vMenuData
.hItem       
= NULLHANDLE
; 
 102     // If we have a title, insert it in the beginning of the menu 
 104     if (!m_title
.empty()) 
 113 } // end of wxMenu::Init 
 116 // The wxWindow destructor will take care of deleting the submenus. 
 121     // We should free PM resources only if PM doesn't do it for us 
 122     // which happens if we're attached to a menubar or a submenu of another 
 124     if (!IsAttached() && !GetParent()) 
 126         if (!::WinDestroyWindow((HWND
)GetHmenu()) ) 
 128             wxLogLastError(wxT("WinDestroyWindow")); 
 136     WX_CLEAR_ARRAY(m_vAccels
); 
 137 #endif // wxUSE_ACCEL 
 138 } // end of wxMenu::~wxMenu 
 142     // this will take effect during the next call to Append() 
 144 } // end of wxMenu::Break 
 147   wxMenuBarBase
*                    pMenubar
 
 150     wxMenuBase::Attach(pMenubar
); 
 152 } // end of wxMenu::Break; 
 156 int wxMenu::FindAccel( 
 161     size_t                          nCount 
= m_vAccels
.GetCount(); 
 163     for (n 
= 0; n 
< nCount
; n
++) 
 164         if (m_vAccels
[n
]->m_command 
== nId
) 
 167 } // end of wxMenu::FindAccel 
 169 void wxMenu::UpdateAccel( 
 173     if (pItem
->IsSubMenu()) 
 175         wxMenu
*                     pSubmenu 
= pItem
->GetSubMenu(); 
 176         wxMenuItemList::compatibility_iterator node 
= pSubmenu
->GetMenuItems().GetFirst(); 
 180             UpdateAccel(node
->GetData()); 
 181             node 
= node
->GetNext(); 
 184     else if (!pItem
->IsSeparator()) 
 187         // Recurse upwards: we should only modify m_accels of the top level 
 188         // menus, not of the submenus as wxMenuBar doesn't look at them 
 189         // (alternative and arguable cleaner solution would be to recurse 
 190         // downwards in GetAccelCount() and CopyAccels()) 
 194             GetParent()->UpdateAccel(pItem
); 
 199         // Find the (new) accel for this item 
 201         wxAcceleratorEntry
*         pAccel 
= wxAcceleratorEntry::Create(pItem
->GetItemLabel()); 
 204             pAccel
->m_command 
= pItem
->GetId(); 
 209         size_t                      n 
= FindAccel(pItem
->GetId()); 
 211         if (n 
== (size_t)wxNOT_FOUND
) 
 214             // No old, add new if any 
 217                 m_vAccels
.Add(pAccel
); 
 224             // Replace old with new or just remove the old one if no new 
 228                 m_vAccels
[n
] = pAccel
; 
 230                 m_vAccels
.RemoveAt(n
); 
 235             GetMenuBar()->RebuildAccelTable(); 
 238 } // wxMenu::UpdateAccel 
 240 #endif // wxUSE_ACCEL 
 243 // Append a new item or submenu to the menu 
 245 bool wxMenu::DoInsertOrAppend( wxMenuItem
* pItem
, 
 248     wxMenu
*    pSubmenu 
= pItem
->GetSubMenu(); 
 249     MENUITEM
&  rItem 
= (pSubmenu 
!= NULL
)?pSubmenu
->m_vMenuData
: 
 257 #endif // wxUSE_ACCEL 
 260     // If "Break" has just been called, insert a menu break before this item 
 261     // (and don't forget to reset the flag) 
 265         rItem
.afStyle 
|= MIS_BREAK
; 
 270     // Id is the numeric id for normal menu items and HMENU for submenus as 
 271     // required by ::MM_INSERTITEM message API 
 273     if (pSubmenu 
!= NULL
) 
 275         wxASSERT_MSG(pSubmenu
->GetHMenu(), wxT("invalid submenu")); 
 276         pSubmenu
->SetParent(this); 
 278         rItem
.iPosition 
= 0; // submenus have a 0 position 
 279         rItem
.id        
= (USHORT
)pSubmenu
->GetHMenu(); 
 280         rItem
.afStyle  
|= MIS_SUBMENU 
| MIS_TEXT
; 
 284         rItem
.id 
= (USHORT
)pItem
->GetId(); 
 289 #if wxUSE_OWNER_DRAWN 
 290     if (pItem
->IsOwnerDrawn()) 
 293         // Want to get {Measure|Draw}Item messages? 
 294         // item draws itself, passing pointer to data doesn't work in OS/2 
 295         // Will eventually need to set the image handle somewhere into vItem.hItem 
 297         rItem
.afStyle             
|= MIS_OWNERDRAW
; 
 299         rItem
.hItem                
= (HBITMAP
)pItem
->GetBitmap().GetHBITMAP(); 
 300         pItem
->m_vMenuData
.afStyle 
= rItem
.afStyle
; 
 301         pItem
->m_vMenuData
.hItem   
= rItem
.hItem
; 
 305     if (pItem
->IsSeparator()) 
 307         rItem
.afStyle 
= MIS_SEPARATOR
; 
 311         if (pItem
->GetId() == idMenuTitle
) 
 313             // Item is an unselectable title to be passed via pData 
 314             rItem
.afStyle 
= MIS_STATIC
; 
 319             // Menu is just a normal string (passed in data parameter) 
 321             rItem
.afStyle 
|= MIS_TEXT
; 
 323         pData 
= (char*) pItem
->GetItemLabel().wx_str(); 
 326     if (nPos 
== (size_t)-1) 
 328         rItem
.iPosition 
= MIT_END
; 
 332         rItem
.iPosition 
= (SHORT
)nPos
; 
 337     rc 
= (APIRET
)::WinSendMsg( GetHmenu() 
 342 #if wxUSE_OWNER_DRAWN 
 343     if (pItem
->IsOwnerDrawn()) 
 347         ::WinSendMsg( GetHmenu() 
 349                      ,MPFROM2SHORT( (USHORT
)pItem
->GetId() 
 357     if (rc 
== (APIRET
)MIT_MEMERROR 
|| rc 
== (APIRET
)MIT_ERROR
) 
 359         vError 
= ::WinGetLastError(vHabmain
); 
 360         sError 
= wxPMErrorToStr(vError
); 
 361         wxLogError(wxT("Error inserting or appending a menuitem. Error: %s\n"), sError
.c_str()); 
 362         wxLogLastError(wxT("Insert or AppendMenu")); 
 367     // If we're already attached to the menubar, we must update it 
 369     if (IsAttached() && GetMenuBar()->IsAttached()) 
 371         GetMenuBar()->Refresh(); 
 375 } // end of wxMenu::DoInsertOrAppend 
 377 void wxMenu::EndRadioGroup() 
 380     // We're not inside a radio group any longer 
 382     m_nStartRadioGroup 
= -1; 
 383 } // end of wxMenu::EndRadioGroup 
 385 wxMenuItem
* wxMenu::DoAppend( wxMenuItem
* pItem 
) 
 387     wxCHECK_MSG( pItem
, NULL
, wxT("NULL item in wxMenu::DoAppend") ); 
 391     if (pItem
->GetKind() == wxITEM_RADIO
) 
 393         int                         nCount 
= GetMenuItemCount(); 
 395         if (m_nStartRadioGroup 
== -1) 
 398             // Start a new radio group 
 400             m_nStartRadioGroup 
= nCount
; 
 403             // For now it has just one element 
 405             pItem
->SetAsRadioGroupStart(); 
 406             pItem
->SetRadioGroupEnd(m_nStartRadioGroup
); 
 409             // Ensure that we have a checked item in the radio group 
 413         else // extend the current radio group 
 416             // We need to update its end item 
 418             pItem
->SetRadioGroupStart(m_nStartRadioGroup
); 
 420             wxMenuItemList::compatibility_iterator node 
= GetMenuItems().Item(m_nStartRadioGroup
); 
 424                 node
->GetData()->SetRadioGroupEnd(nCount
); 
 428                 wxFAIL_MSG( wxT("where is the radio group start item?") ); 
 432     else // not a radio item 
 437     if (!wxMenuBase::DoAppend(pItem
) || !DoInsertOrAppend(pItem
)) 
 444         // Check the item initially 
 449 } // end of wxMenu::DoAppend 
 451 wxMenuItem
* wxMenu::DoInsert( 
 456     if ( wxMenuBase::DoInsert( nPos
 
 458              DoInsertOrAppend( pItem
 
 464 } // end of wxMenu::DoInsert 
 466 wxMenuItem
* wxMenu::DoRemove( 
 471     // We need to find the items position in the child list 
 474     wxMenuItemList::compatibility_iterator node 
= GetMenuItems().GetFirst(); 
 476     for (nPos 
= 0; node
; nPos
++) 
 478         if (node
->GetData() == pItem
) 
 480         node 
= node
->GetNext(); 
 484     // DoRemove() (unlike Remove) can only be called for existing item! 
 486     wxCHECK_MSG(node
, NULL
, wxT("bug in wxMenu::Remove logic")); 
 490     // Remove the corresponding accel from the accel table 
 492     int                             n 
= FindAccel(pItem
->GetId()); 
 494     if (n 
!= wxNOT_FOUND
) 
 497         m_vAccels
.RemoveAt(n
); 
 500 #endif // wxUSE_ACCEL 
 502     // Remove the item from the menu 
 504     ::WinSendMsg( GetHmenu() 
 506                  ,MPFROM2SHORT(pItem
->GetId(), TRUE
) 
 509     if (IsAttached() && GetMenuBar()->IsAttached()) 
 512         // Otherwise, the chane won't be visible 
 514         GetMenuBar()->Refresh(); 
 518     // And from internal data structures 
 520     return wxMenuBase::DoRemove(pItem
); 
 521 } // end of wxMenu::DoRemove 
 523 // --------------------------------------------------------------------------- 
 524 // accelerator helpers 
 525 // --------------------------------------------------------------------------- 
 530 // Create the wxAcceleratorEntries for our accels and put them into provided 
 531 // array - return the number of accels we have 
 533 size_t wxMenu::CopyAccels( 
 534   wxAcceleratorEntry
*               pAccels
 
 537     size_t                          nCount 
= GetAccelCount(); 
 539     for (size_t n 
= 0; n 
< nCount
; n
++) 
 541         *pAccels
++ = *m_vAccels
[n
]; 
 544 } // end of wxMenu::CopyAccels 
 546 #endif // wxUSE_ACCEL 
 548 // --------------------------------------------------------------------------- 
 550 // --------------------------------------------------------------------------- 
 552 void wxMenu::SetTitle( const wxString
& rLabel 
) 
 554     bool bHasNoTitle 
= m_title
.empty(); 
 555     HWND hMenu 
= GetHmenu(); 
 562             if (!::WinSetWindowText(hMenu
, rLabel
.c_str())) 
 564                 wxLogLastError(wxT("SetMenuTitle")); 
 572             ::WinSendMsg( GetHmenu() 
 574                          ,MPFROM2SHORT(hMenu
, TRUE
) 
 583             if (!::WinSetWindowText(hMenu
, rLabel
.c_str())) 
 585                 wxLogLastError(wxT("SetMenuTitle")); 
 589 } // end of wxMenu::SetTitle 
 591 // --------------------------------------------------------------------------- 
 593 // --------------------------------------------------------------------------- 
 595 bool wxMenu::OS2Command( WXUINT 
WXUNUSED(uParam
), 
 599     // Ignore commands from the menu title 
 602     if (vId 
!= (WXWORD
)idMenuTitle
) 
 605                   ,(int)::WinSendMsg( GetHmenu() 
 613 } // end of wxMenu::OS2Command 
 615 // --------------------------------------------------------------------------- 
 617 // --------------------------------------------------------------------------- 
 619 wxWindow
* wxMenu::GetWindow() const 
 621     if (m_invokingWindow 
!= NULL
) 
 622         return m_invokingWindow
; 
 623     else if ( GetMenuBar() != NULL
) 
 624         return GetMenuBar()->GetFrame(); 
 627 } // end of wxMenu::GetWindow 
 629 // recursive search for item by id 
 630 wxMenuItem
* wxMenu::FindItem( 
 633 , wxMenu
**                          ppItemMenu
 
 639     wxMenuItem
*                     pItem 
= NULL
; 
 641     for ( wxMenuItemList::compatibility_iterator node 
= m_items
.GetFirst(); 
 643           node 
= node
->GetNext() ) 
 645         pItem 
= node
->GetData(); 
 647         if ( pItem
->GetId() == nItemId 
&& pItem
->m_vMenuData
.hItem 
== hItem
) 
 650                 *ppItemMenu 
= (wxMenu 
*)this; 
 652         else if ( pItem
->IsSubMenu() ) 
 654             pItem 
= pItem
->GetSubMenu()->FindItem( nItemId
 
 663             // don't exit the loop 
 668 } // end of wxMenu::FindItem 
 670 // --------------------------------------------------------------------------- 
 672 // --------------------------------------------------------------------------- 
 674 void wxMenuBar::Init() 
 676     m_eventHandler 
= this; 
 677     m_menuBarFrame 
= NULL
; 
 679 } // end of wxMenuBar::Init 
 681 wxMenuBar::wxMenuBar() 
 684 } // end of wxMenuBar::wxMenuBar 
 686 wxMenuBar::wxMenuBar( 
 687  long                               WXUNUSED(lStyle
) 
 691 } // end of wxMenuBar::wxMenuBar 
 693 wxMenuBar::wxMenuBar( 
 696 , const wxString                    sTitles
[] 
 697 , long                              WXUNUSED(lStyle
) 
 702     m_titles
.Alloc(nCount
); 
 703     for ( int i 
= 0; i 
< nCount
; i
++ ) 
 705         m_menus
.Append(vMenus
[i
]); 
 706         m_titles
.Add(sTitles
[i
]); 
 707         vMenus
[i
]->Attach(this); 
 709 } // end of wxMenuBar::wxMenuBar 
 711 wxMenuBar::~wxMenuBar() 
 714     // We should free PM's resources only if PM doesn't do it for us 
 715     // which happens if we're attached to a frame 
 717     if (m_hMenu 
&& !IsAttached()) 
 719         ::WinDestroyWindow((HMENU
)m_hMenu
); 
 720         m_hMenu 
= (WXHMENU
)NULL
; 
 722 } // end of wxMenuBar::~wxMenuBar 
 724 // --------------------------------------------------------------------------- 
 726 // --------------------------------------------------------------------------- 
 728 void wxMenuBar::Refresh() 
 730     wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") ); 
 732     WinSendMsg(GetWinHwnd(m_menuBarFrame
), WM_UPDATEFRAME
, (MPARAM
)FCF_MENU
, (MPARAM
)0); 
 733 } // end of wxMenuBar::Refresh 
 735 WXHMENU 
wxMenuBar::Create() 
 742     wxCHECK_MSG(!m_hMenu
, TRUE
, wxT("menubar already created")); 
 745     // Menubars should be associated with a frame otherwise they are popups 
 747     if (m_menuBarFrame 
!= NULL
) 
 748         hFrame 
= GetWinHwnd(m_menuBarFrame
); 
 750         hFrame 
= HWND_DESKTOP
; 
 752     // Create an empty menu and then fill it with insertions 
 754     if ((m_hMenu 
=  ::WinCreateWindow( hFrame
 
 757                                       ,MS_ACTIONBAR 
| WS_SYNCPAINT 
| WS_VISIBLE
 
 769         wxLogLastError(wxT("WinLoadMenu")); 
 773         size_t nCount 
= GetMenuCount(), i
; 
 774         wxMenuList::iterator it
; 
 775         for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
 783             // Set the parent and owner of the submenues to be the menubar, not the desktop 
 785             hSubMenu 
= (*it
)->m_vMenuData
.hwndSubMenu
; 
 786             if (!::WinSetParent((*it
)->m_vMenuData
.hwndSubMenu
, m_hMenu
, FALSE
)) 
 788                 vError 
= ::WinGetLastError(vHabmain
); 
 789                 sError 
= wxPMErrorToStr(vError
); 
 790                 wxLogError(wxT("Error setting parent for submenu. Error: %s\n"), sError
.c_str()); 
 794             if (!::WinSetOwner((*it
)->m_vMenuData
.hwndSubMenu
, m_hMenu
)) 
 796                 vError 
= ::WinGetLastError(vHabmain
); 
 797                 sError 
= wxPMErrorToStr(vError
); 
 798                 wxLogError(wxT("Error setting parent for submenu. Error: %s\n"), sError
.c_str()); 
 802             (*it
)->m_vMenuData
.iPosition 
= (SHORT
)i
; 
 804             rc 
= (APIRET
)::WinSendMsg(m_hMenu
, MM_INSERTITEM
, (MPARAM
)&(*it
)->m_vMenuData
, (MPARAM
)m_titles
[i
].wx_str()); 
 805             if (rc 
== (APIRET
)MIT_MEMERROR 
|| rc 
== (APIRET
)MIT_ERROR
) 
 807                 vError 
= ::WinGetLastError(vHabmain
); 
 808                 sError 
= wxPMErrorToStr(vError
); 
 809                 wxLogError(wxT("Error inserting or appending a menuitem. Error: %s\n"), sError
.c_str()); 
 815 } // end of wxMenuBar::Create 
 817 // --------------------------------------------------------------------------- 
 818 // wxMenuBar functions to work with the top level submenus 
 819 // --------------------------------------------------------------------------- 
 822 // NB: we don't support owner drawn top level items for now, if we do these 
 823 //     functions would have to be changed to use wxMenuItem as well 
 825 void wxMenuBar::EnableTop( 
 830     wxCHECK_RET(IsAttached(), wxT("doesn't work with unattached menubars")); 
 835        uFlag 
= MIA_DISABLED
; 
 837     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 838     if (nId 
== MIT_ERROR
) 
 840         wxLogLastError(wxT("LogLastError")); 
 843     ::WinSendMsg((HWND
)m_hMenu
, MM_SETITEMATTR
, MPFROM2SHORT(nId
, TRUE
), MPFROM2SHORT(MIA_DISABLED
, uFlag
)); 
 845 } // end of wxMenuBar::EnableTop 
 847 void wxMenuBar::SetMenuLabel( 
 849 , const wxString
&                   rLabel
 
 855     wxCHECK_RET(nPos 
< GetMenuCount(), wxT("invalid menu index")); 
 856     m_titles
[nPos
] = rLabel
; 
 863     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 864     if (nId 
== MIT_ERROR
) 
 866         wxLogLastError(wxT("LogLastError")); 
 869     if(!::WinSendMsg( (HWND
)m_hMenu
 
 871                      ,MPFROM2SHORT(nId
, TRUE
) 
 875         wxLogLastError(wxT("QueryItem")); 
 879     if (::WinSendMsg(GetHmenu(), MM_SETITEMTEXT
, MPFROMSHORT(nId
), (MPARAM
)rLabel
.wx_str())); 
 881         wxLogLastError(wxT("ModifyMenu")); 
 884 } // end of wxMenuBar::SetMenuLabel 
 886 wxString 
wxMenuBar::GetMenuLabel( 
 890     wxCHECK_MSG( nPos 
< GetMenuCount(), wxEmptyString
, 
 891                  wxT("invalid menu index in wxMenuBar::GetMenuLabel") ); 
 892     return m_titles
[nPos
]; 
 893 } // end of wxMenuBar::GetMenuLabel 
 895 // --------------------------------------------------------------------------- 
 896 // wxMenuBar construction 
 897 // --------------------------------------------------------------------------- 
 899 wxMenu
* wxMenuBar::Replace( 
 902 , const wxString
&                    rTitle
 
 906     wxString                         sTitle 
= wxPMTextToLabel(rTitle
); 
 907     wxMenu
*                          pMenuOld 
= wxMenuBarBase::Replace( nPos
 
 913     nId 
= SHORT1FROMMR(::WinSendMsg((HWND
)m_hMenu
, MM_ITEMIDFROMPOSITION
, MPFROMSHORT(nPos
), (MPARAM
)0)); 
 914     if (nId 
== MIT_ERROR
) 
 916         wxLogLastError(wxT("LogLastError")); 
 921     m_titles
[nPos
] = sTitle
; 
 924         ::WinSendMsg((HWND
)m_hMenu
, MM_REMOVEITEM
, MPFROM2SHORT(nId
, TRUE
), (MPARAM
)0); 
 925         ::WinSendMsg((HWND
)m_hMenu
, MM_INSERTITEM
, (MPARAM
)&pMenu
->m_vMenuData
, (MPARAM
)sTitle
.wx_str()); 
 928         if (pMenuOld
->HasAccels() || pMenu
->HasAccels()) 
 931             // Need to rebuild accell table 
 935 #endif // wxUSE_ACCEL 
 939 } // end of wxMenuBar::Replace 
 941 bool wxMenuBar::Insert( size_t          nPos
, 
 943                         const wxString
& rTitle 
) 
 945     wxString sTitle 
= wxPMTextToLabel(rTitle
); 
 947     if (!wxMenuBarBase::Insert( nPos
, pMenu
, sTitle 
)) 
 950     m_titles
.Insert( sTitle
, nPos 
); 
 954         pMenu
->m_vMenuData
.iPosition 
= (SHORT
)nPos
; 
 955         ::WinSendMsg( (HWND
)m_hMenu
 
 957                      ,(MPARAM
)&pMenu
->m_vMenuData
 
 958                      ,(MPARAM
)sTitle
.wx_str() 
 961         if (pMenu
->HasAccels()) 
 963             // need to rebuild accell table 
 966 #endif // wxUSE_ACCEL 
 971 } // end of wxMenuBar::Insert 
 973 bool wxMenuBar::Append( wxMenu
* pMenu
, 
 974                         const wxString
& rsTitle 
) 
 976     WXHMENU hSubmenu 
= pMenu 
? pMenu
->GetHMenu() : 0; 
 978     wxCHECK_MSG(hSubmenu
, false, wxT("can't append invalid menu to menubar")); 
 980     wxString sTitle 
= wxPMTextToLabel(rsTitle
); 
 982     if (!wxMenuBarBase::Append(pMenu
, sTitle
)) 
 985     m_titles
.Add(sTitle
); 
 989         pMenu
->m_vMenuData
.iPosition 
= MIT_END
; 
 990         ::WinSendMsg((HWND
)m_hMenu
, MM_INSERTITEM
, (MPARAM
)&pMenu
->m_vMenuData
, (MPARAM
)sTitle
.wx_str()); 
 992         if (pMenu
->HasAccels()) 
 995             // Need to rebuild accell table 
 999 #endif // wxUSE_ACCEL 
1003 } // end of wxMenuBar::Append 
1005 wxMenu
* wxMenuBar::Remove( 
1009     wxMenu
*                         pMenu 
= wxMenuBarBase::Remove(nPos
); 
1015     nId 
= SHORT1FROMMR(::WinSendMsg( (HWND
)GetHmenu() 
1016                                     ,MM_ITEMIDFROMPOSITION
 
1020     if (nId 
== MIT_ERROR
) 
1022         wxLogLastError(wxT("LogLastError")); 
1027         ::WinSendMsg( (HWND
)GetHmenu() 
1029                      ,MPFROM2SHORT(nId
, TRUE
) 
1034         if (pMenu
->HasAccels()) 
1037             // Need to rebuild accell table 
1039             RebuildAccelTable(); 
1041 #endif // wxUSE_ACCEL 
1044     m_titles
.RemoveAt(nPos
); 
1046 } // end of wxMenuBar::Remove 
1050 void wxMenuBar::RebuildAccelTable() 
1053     // Merge the accelerators of all menus into one accel table 
1055     size_t                          nAccelCount 
= 0; 
1057     size_t                          nCount 
= GetMenuCount(); 
1058     wxMenuList::iterator it
; 
1059     for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1061         nAccelCount 
+= (*it
)->GetAccelCount(); 
1066         wxAcceleratorEntry
*         pAccelEntries 
= new wxAcceleratorEntry
[nAccelCount
]; 
1069         for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1071             nAccelCount 
+= (*it
)->CopyAccels(&pAccelEntries
[nAccelCount
]); 
1073         m_vAccelTable 
= wxAcceleratorTable( nAccelCount
 
1076         delete [] pAccelEntries
; 
1078 } // end of wxMenuBar::RebuildAccelTable 
1080 #endif // wxUSE_ACCEL 
1082 void wxMenuBar::Attach( 
1086     wxMenuBarBase::Attach(pFrame
); 
1089     RebuildAccelTable(); 
1091     // Ensure the accelerator table is set to the frame (not the client!) 
1093     if (!::WinSetAccelTable( vHabmain
 
1094                             ,m_vAccelTable
.GetHACCEL() 
1095                             ,(HWND
)pFrame
->GetFrame() 
1098         wxLogLastError(wxT("WinSetAccelTable")); 
1100 #endif // wxUSE_ACCEL 
1101 } // end of wxMenuBar::Attach 
1103 void wxMenuBar::Detach() 
1105     ::WinDestroyWindow((HWND
)m_hMenu
); 
1106     m_hMenu 
= (WXHMENU
)NULL
; 
1107     m_menuBarFrame 
= NULL
; 
1108 } // end of wxMenuBar::Detach 
1110 // --------------------------------------------------------------------------- 
1111 // wxMenuBar searching for menu items 
1112 // --------------------------------------------------------------------------- 
1115 // Find the itemString in menuString, and return the item id or wxNOT_FOUND 
1117 int wxMenuBar::FindMenuItem( 
1118   const wxString
&                   rMenuString
 
1119 , const wxString
&                   rItemString
 
1122     wxString                        sMenuLabel 
= wxStripMenuCodes(rMenuString
); 
1123     size_t                          nCount 
= GetMenuCount(), i
; 
1124     wxMenuList::const_iterator it
; 
1125     for (i 
= 0, it 
= m_menus
.begin(); i 
< nCount
; i
++, it
++) 
1127         wxString                    sTitle 
= wxStripMenuCodes(m_titles
[i
]); 
1129         if (rMenuString 
== sTitle
) 
1130             return (*it
)->FindItem(rItemString
); 
1133 } // end of wxMenuBar::FindMenuItem 
1135 wxMenuItem
* wxMenuBar::FindItem( 
1137 , wxMenu
**                          ppItemMenu
 
1143     wxMenuItem
*                     pItem 
= NULL
; 
1144     size_t                          nCount 
= GetMenuCount(), i
; 
1145     wxMenuList::const_iterator it
; 
1146     for (i 
= 0, it 
= m_menus
.begin(); !pItem 
&& (i 
< nCount
); i
++, it
++) 
1148         pItem 
= (*it
)->FindItem( nId
 
1153 } // end of wxMenuBar::FindItem 
1155 wxMenuItem
* wxMenuBar::FindItem( 
1158 , wxMenu
**                          ppItemMenu
 
1164     wxMenuItem
*                     pItem 
= NULL
; 
1165     size_t                          nCount 
= GetMenuCount(), i
; 
1166     wxMenuList::const_iterator it
; 
1167     for (i 
= 0, it 
= m_menus
.begin(); !pItem 
&& (i 
< nCount
); i
++, it
++) 
1169         pItem 
= (*it
)->FindItem( nId
 
1175 } // end of wxMenuBar::FindItem