]> git.saurik.com Git - wxWidgets.git/blame - src/os2/menu.cpp
Moved wxGLCanvas to more normal positions
[wxWidgets.git] / src / os2 / menu.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: menu.cpp
3// Purpose: wxMenu, wxMenuBar, wxMenuItem
75f11ad7 4// Author: David Webster
0e320a79 5// Modified by:
75f11ad7 6// Created: 10/10/99
0e320a79 7// RCS-ID: $Id$
75f11ad7
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
a4372af6
SN
12#ifdef __GNUG__
13 #pragma implementation "menu.h"
14#endif
15
75f11ad7
DW
16// For compilers that support precompilation, includes "wx.h".
17#include "wx/wxprec.h"
0e320a79 18
75f11ad7
DW
19#ifndef WX_PRECOMP
20 #include "wx/frame.h"
21 #include "wx/menu.h"
22 #include "wx/utils.h"
23 #include "wx/intl.h"
c5fb56c0 24 #include "wx/log.h"
75f11ad7 25#endif
0e320a79 26
75f11ad7
DW
27#if wxUSE_OWNER_DRAWN
28 #include "wx/ownerdrw.h"
0e320a79
DW
29#endif
30
75f11ad7 31#include "wx/os2/private.h"
0e320a79
DW
32
33// other standard headers
0e320a79
DW
34#include <string.h>
35
75f11ad7
DW
36// ----------------------------------------------------------------------------
37// global variables
38// ----------------------------------------------------------------------------
39
61243a51 40extern wxMenu* wxCurrentPopupMenu;
75f11ad7
DW
41
42// ----------------------------------------------------------------------------
43// constants
44// ----------------------------------------------------------------------------
45
61243a51
DW
46//
47// The (popup) menu title has this special id
48//
49static const int idMenuTitle = -2;
75f11ad7
DW
50
51// ----------------------------------------------------------------------------
52// macros
53// ----------------------------------------------------------------------------
54
75f11ad7
DW
55 IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxEvtHandler)
56 IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxEvtHandler)
0e320a79
DW
57
58// ============================================================================
59// implementation
60// ============================================================================
61
75f11ad7
DW
62// ---------------------------------------------------------------------------
63// wxMenu construction, adding and removing menu items
64// ---------------------------------------------------------------------------
0e320a79 65
61243a51 66//
0e320a79 67// Construct a menu with optional title (then use append)
61243a51 68//
c5fb56c0 69void wxMenu::Init()
0e320a79 70{
61243a51
DW
71 m_bDoBreak = FALSE;
72
73 //
74 // Create the menu
75 //
76 m_hMenu = ::WinCreateWindow( HWND_DESKTOP // parent
77 ,WC_MENU // type
78 ,"Menu" // a generic name
79 ,0L // no style flag
80 ,0L,0L,0L,0L // no position
81 ,NULLHANDLE // no owner
82 ,NULLHANDLE // no insertion position
83 ,0L // no ID needed for dynamic creation
84 ,NULL // no control data
85 ,NULL // no presentation params
86 );
87 if (!m_hMenu)
88 {
89 wxLogLastError("WinLoadMenu");
90 }
91
92 //
93 // If we have a title, insert it in the beginning of the menu
94 //
95 if (!!m_title)
96 {
97 Append( idMenuTitle
98 ,m_title
99 );
c5fb56c0
DW
100 AppendSeparator();
101 }
61243a51 102} // end of wxMenu::Init
0e320a79 103
61243a51 104//
0e320a79 105// The wxWindow destructor will take care of deleting the submenus.
61243a51 106//
0e320a79
DW
107wxMenu::~wxMenu()
108{
61243a51
DW
109 //
110 // We should free PM resources only if PM doesn't do it for us
c5fb56c0
DW
111 // which happens if we're attached to a menubar or a submenu of another
112 // menu
61243a51 113 if (!IsAttached() && !GetParent())
75f11ad7 114 {
61243a51 115 if (!::WinDestroyWindow((HWND)GetHmenu()) )
c5fb56c0 116 {
61243a51 117 wxLogLastError("WinDestroyWindow");
c5fb56c0 118 }
75f11ad7 119 }
0e320a79 120
c5fb56c0 121#if wxUSE_ACCEL
61243a51
DW
122 //
123 // Delete accels
124 //
125 WX_CLEAR_ARRAY(m_vAccels);
c5fb56c0 126#endif // wxUSE_ACCEL
61243a51 127} // end of wxMenu::~wxMenu
0e320a79
DW
128
129void wxMenu::Break()
130{
c5fb56c0 131 // this will take effect during the next call to Append()
61243a51
DW
132 m_bDoBreak = TRUE;
133} // end of wxMenu::Break
0e320a79 134
c5fb56c0
DW
135#if wxUSE_ACCEL
136
61243a51
DW
137int wxMenu::FindAccel(
138 int nId
139) const
0e320a79 140{
61243a51
DW
141 size_t n;
142 size_t nCount = m_vAccels.GetCount();
143
144 for (n = 0; n < nCount; n++)
c5fb56c0 145 {
61243a51 146 if (m_vAccels[n]->m_command == nId)
c5fb56c0
DW
147 return n;
148 }
c5fb56c0 149 return wxNOT_FOUND;
61243a51 150} // end of wxMenu::FindAccel
75f11ad7 151
61243a51
DW
152void wxMenu::UpdateAccel(
153 wxMenuItem* pItem
154)
c5fb56c0 155{
61243a51
DW
156 //
157 // Find the (new) accel for this item
158 //
159 wxAcceleratorEntry* pAccel = wxGetAccelFromString(pItem->GetText());
75f11ad7 160
61243a51
DW
161 if (pAccel)
162 pAccel->m_command = pItem->GetId();
163
164 //
165 // Find the old one
166 //
167 int n = FindAccel(pItem->GetId());
168
169 if (n == wxNOT_FOUND)
c5fb56c0 170 {
61243a51
DW
171 //
172 // No old, add new if any
173 //
174 if (pAccel)
175 m_vAccels.Add(pAccel);
c5fb56c0
DW
176 else
177 return; // skipping RebuildAccelTable() below
178 }
179 else
180 {
61243a51
DW
181 //
182 // Replace old with new or just remove the old one if no new
183 //
184 delete m_vAccels[n];
185
186 if (pAccel)
187 m_vAccels[n] = pAccel;
c5fb56c0 188 else
61243a51 189 m_vAccels.Remove(n);
75f11ad7 190 }
c5fb56c0 191
61243a51 192 if (IsAttached())
c5fb56c0
DW
193 {
194 m_menuBar->RebuildAccelTable();
195 }
61243a51 196} // wxMenu::UpdateAccel
c5fb56c0 197
75f11ad7 198#endif // wxUSE_ACCEL
0e320a79 199
61243a51
DW
200//
201// Append a new item or submenu to the menu
202//
203bool wxMenu::DoInsertOrAppend(
204 wxMenuItem* pItem
205, size_t nPos
206)
c5fb56c0
DW
207{
208#if wxUSE_ACCEL
209 UpdateAccel(pItem);
210#endif // wxUSE_ACCEL
0e320a79 211
61243a51
DW
212 //
213 // If "Break" has just been called, insert a menu break before this item
75f11ad7 214 // (and don't forget to reset the flag)
61243a51
DW
215 //
216 if (m_bDoBreak)
217 {
218 m_vMenuData.afStyle |= MIS_BREAK;
219 m_bDoBreak = FALSE;
75f11ad7 220 }
0e320a79 221
61243a51
DW
222 if (pItem->IsSeparator())
223 {
224 m_vMenuData.afStyle |= MIS_SEPARATOR;
75f11ad7
DW
225 }
226
61243a51
DW
227 //
228 // Id is the numeric id for normal menu items and HMENU for submenus as
229 // required by ::WinInsertMenu() API
230 //
c5fb56c0 231
61243a51
DW
232 wxMenu* pSubmenu = pItem->GetSubMenu();
233 MENUITEM vItem;
75f11ad7 234
61243a51
DW
235 if (pSubmenu != NULL )
236 {
237 wxASSERT_MSG(pSubmenu->GetHMenu(), wxT("invalid submenu"));
238 pSubmenu->SetParent(this);
75f11ad7 239
61243a51
DW
240 m_vMenuData.id = (USHORT)pSubmenu->GetHMenu();
241 m_vMenuData.afStyle |= MIS_SUBMENU;
75f11ad7 242 }
61243a51
DW
243 else
244 {
245 m_vMenuData.id = pItem->GetId();
75f11ad7
DW
246 }
247
61243a51 248 BYTE* pData;
75f11ad7
DW
249
250#if wxUSE_OWNER_DRAWN
61243a51
DW
251 if (pItem->IsOwnerDrawn())
252 {
253 //
254 // Want to get {Measure|Draw}Item messages?
75f11ad7 255 // item draws itself, pass pointer to it in data parameter
61243a51
DW
256 //
257 m_vMenuData.afStyle |= MIS_OWNERDRAW;
258 pData = (BYTE*)pItem;
75f11ad7
DW
259 }
260 else
261#endif
262 {
61243a51
DW
263 //
264 // Menu is just a normal string (passed in data parameter)
265 //
266 m_vMenuData.afStyle |= MIS_TEXT;
c5fb56c0 267 pData = (char*)pItem->GetText().c_str();
75f11ad7 268 }
c5fb56c0 269
61243a51
DW
270 BOOL bOk;
271
272 //
273 // -1 means this is a sub menu not a menuitem
274 //
275 if (nPos == (size_t)-1)
75f11ad7 276 {
61243a51
DW
277 HWND hSubMenu = ::WinCreateWindow( HWND_DESKTOP // parent
278 ,WC_MENU // type
279 ,"Menu" // a generic name
280 ,0L // no style flag
281 ,0L,0L,0L,0L // no position
282 ,NULLHANDLE // no owner
283 ,NULLHANDLE // no insertion position
284 ,0L // no ID needed for dynamic creation
285 ,NULL // no control data
286 ,NULL // no presentation params
287 );
288
289 m_vMenuData.iPosition = 0;
290 m_vMenuData.hwndSubMenu = hSubMenu;
291 m_vMenuData.hItem = NULLHANDLE;
292
293 bOk = (bool)::WinSendMsg(GetHmenu(), MM_INSERTITEM, (MPARAM)&vItem, (MPARAM)NULL);
75f11ad7
DW
294 }
295 else
296 {
61243a51
DW
297 m_vMenuData.iPosition = nPos;
298 m_vMenuData.hwndSubMenu = NULLHANDLE;
299 m_vMenuData.hItem = NULLHANDLE;
300 bOk = (bool)::WinSendMsg(GetHmenu(), MM_INSERTITEM, (MPARAM)&vItem, (MPARAM)pData);
c5fb56c0
DW
301 }
302
61243a51 303 if (!bOk)
c5fb56c0
DW
304 {
305 wxLogLastError("Insert or AppendMenu");
c5fb56c0
DW
306 return FALSE;
307 }
308 else
309 {
61243a51
DW
310 //
311 // If we're already attached to the menubar, we must update it
312 //
313 if (IsAttached())
c5fb56c0
DW
314 {
315 m_menuBar->Refresh();
316 }
c5fb56c0 317 return TRUE;
75f11ad7 318 }
c5fb56c0 319 return FALSE;
61243a51 320} // end of wxMenu::DoInsertOrAppend
0e320a79 321
61243a51
DW
322bool wxMenu::DoAppend(
323 wxMenuItem* pItem
324)
0e320a79 325{
61243a51 326 return wxMenuBase::DoAppend(pItem) && DoInsertOrAppend(pItem);
0e320a79
DW
327}
328
61243a51
DW
329bool wxMenu::DoInsert(
330 size_t nPos
331, wxMenuItem* pItem
332)
0e320a79 333{
61243a51
DW
334 return ( wxMenuBase::DoInsert( nPos
335 ,pItem) &&
336 DoInsertOrAppend( pItem
337 ,nPos
338 ));
339} // end of wxMenu::DoInsert
0e320a79 340
61243a51
DW
341wxMenuItem* wxMenu::DoRemove(
342 wxMenuItem* pItem
343)
0e320a79 344{
61243a51
DW
345 //
346 // We need to find the items position in the child list
347 //
348 size_t nPos;
349 wxMenuItemList::Node* pNode = GetMenuItems().GetFirst();
350
351 for (nPos = 0; pNode; nPos++)
75f11ad7 352 {
61243a51 353 if (pNode->GetData() == pItem)
75f11ad7 354 break;
61243a51 355 pNode = pNode->GetNext();
0e320a79
DW
356 }
357
61243a51 358 //
c5fb56c0 359 // DoRemove() (unlike Remove) can only be called for existing item!
61243a51
DW
360 //
361 wxCHECK_MSG(pNode, NULL, wxT("bug in wxMenu::Remove logic"));
75f11ad7 362
c5fb56c0 363#if wxUSE_ACCEL
61243a51
DW
364 //
365 // Remove the corresponding accel from the accel table
366 //
367 int n = FindAccel(pItem->GetId());
75f11ad7 368
61243a51 369 if (n != wxNOT_FOUND)
75f11ad7 370 {
61243a51
DW
371 delete m_vAccels[n];
372 m_vAccels.Remove(n);
c5fb56c0 373 }
61243a51
DW
374
375#endif // wxUSE_ACCEL
376 //
377 // Remove the item from the menu
378 //
379 ::WinSendMsg( GetHmenu()
380 ,MM_REMOVEITEM
381 ,MPFROM2SHORT(pItem->GetId(), TRUE)
382 ,(MPARAM)0
383 );
384 if (IsAttached())
385 {
386 //
387 // Otherwise, the chane won't be visible
388 //
c5fb56c0 389 m_menuBar->Refresh();
75f11ad7 390 }
0e320a79 391
61243a51
DW
392 //
393 // And from internal data structures
394 //
395 return wxMenuBase::DoRemove(pItem);
396} // end of wxMenu::DoRemove
0e320a79 397
75f11ad7
DW
398// ---------------------------------------------------------------------------
399// accelerator helpers
400// ---------------------------------------------------------------------------
401
c5fb56c0
DW
402#if wxUSE_ACCEL
403
61243a51
DW
404//
405// Create the wxAcceleratorEntries for our accels and put them into provided
75f11ad7 406// array - return the number of accels we have
61243a51
DW
407//
408size_t wxMenu::CopyAccels(
409 wxAcceleratorEntry* pAccels
410) const
75f11ad7 411{
61243a51
DW
412 size_t nCount = GetAccelCount();
413
414 for (size_t n = 0; n < nCount; n++)
75f11ad7 415 {
61243a51 416 *pAccels++ = *m_vAccels[n];
75f11ad7 417 }
61243a51
DW
418 return nCount;
419} // end of wxMenu::CopyAccels
0e320a79 420
75f11ad7
DW
421#endif // wxUSE_ACCEL
422
423// ---------------------------------------------------------------------------
c5fb56c0 424// set wxMenu title
75f11ad7
DW
425// ---------------------------------------------------------------------------
426
61243a51
DW
427void wxMenu::SetTitle(
428 const wxString& rLabel
429)
0e320a79 430{
61243a51
DW
431 bool bHasNoTitle = m_title.IsEmpty();
432 HWND hMenu = GetHmenu();
0e320a79 433
61243a51
DW
434 m_title = rLabel;
435 if (bHasNoTitle)
0e320a79 436 {
61243a51 437 if (!rLabel.IsEmpty())
75f11ad7 438 {
61243a51 439 if (!::WinSetWindowText(hMenu, rLabel.c_str()))
75f11ad7 440 {
61243a51 441 wxLogLastError("SetMenuTitle");
75f11ad7
DW
442 }
443 }
0e320a79 444 }
75f11ad7 445 else
0e320a79 446 {
61243a51 447 if (rLabel.IsEmpty() )
0e320a79 448 {
61243a51
DW
449 ::WinSendMsg( GetHmenu()
450 ,MM_REMOVEITEM
451 ,MPFROM2SHORT(hMenu, TRUE)
452 ,(MPARAM)0
453 );
0e320a79 454 }
75f11ad7 455 else
0e320a79 456 {
61243a51
DW
457 //
458 // Modify the title
459 //
460 if (!::WinSetWindowText(hMenu, rLabel.c_str()))
75f11ad7 461 {
61243a51 462 wxLogLastError("SetMenuTitle");
75f11ad7 463 }
0e320a79
DW
464 }
465 }
61243a51 466} // end of wxMenu::SetTitle
0e320a79 467
75f11ad7
DW
468// ---------------------------------------------------------------------------
469// event processing
470// ---------------------------------------------------------------------------
471
61243a51
DW
472bool wxMenu::OS2Command(
473 WXUINT WXUNUSED(uParam)
474, WXWORD vId
475)
0e320a79 476{
61243a51
DW
477 //
478 // Ignore commands from the menu title
479 //
75f11ad7 480
61243a51 481 if (vId != (WXWORD)idMenuTitle)
75f11ad7 482 {
61243a51 483 wxCommandEvent vEvent(wxEVT_COMMAND_MENU_SELECTED);
75f11ad7 484
61243a51
DW
485 vEvent.SetEventObject(this);
486 vEvent.SetId(vId);
487 vEvent.SetInt(vId);
488 ProcessCommand(vEvent);
489 }
75f11ad7 490 return TRUE;
61243a51 491} // end of wxMenu::OS2Command
0e320a79 492
61243a51
DW
493bool wxMenu::ProcessCommand(
494 wxCommandEvent& rEvent
495)
0e320a79 496{
61243a51 497 bool bProcessed = FALSE;
0e320a79 498
61243a51
DW
499#if wxUSE_MENU_CALLBACK
500 //
0e320a79 501 // Try a callback
61243a51 502 //
0e320a79
DW
503 if (m_callback)
504 {
61243a51
DW
505 (void)(*(m_callback))(*this, rEvent);
506 bProcessed = TRUE;
0e320a79 507 }
61243a51 508#endif // wxUSE_MENU_CALLBACK
0e320a79 509
61243a51 510 //
0e320a79 511 // Try the menu's event handler
61243a51
DW
512 //
513 if (!bProcessed && GetEventHandler())
0e320a79 514 {
61243a51 515 bProcessed = GetEventHandler()->ProcessEvent(rEvent);
0e320a79 516 }
75f11ad7 517
61243a51 518 //
75f11ad7
DW
519 // Try the window the menu was popped up from (and up through the
520 // hierarchy)
61243a51 521 wxWindow* pWin = GetInvokingWindow();
75f11ad7 522
61243a51
DW
523 if (!bProcessed && pWin)
524 bProcessed = pWin->GetEventHandler()->ProcessEvent(rEvent);
525 return bProcessed;
526} // end of wxMenu::ProcessCommand
0e320a79 527
75f11ad7
DW
528// ---------------------------------------------------------------------------
529// other
530// ---------------------------------------------------------------------------
531
61243a51
DW
532void wxMenu::Attach(
533 wxMenuBar* pMenubar
534)
0e320a79 535{
61243a51
DW
536 //
537 // Menu can be in at most one menubar because otherwise they would both
75f11ad7 538 // delete the menu pointer
61243a51
DW
539 //
540 wxASSERT_MSG(!m_menuBar, wxT("menu belongs to 2 menubars, expect a crash"));
541 m_menuBar = pMenubar;
542} // end of
75f11ad7
DW
543
544void wxMenu::Detach()
545{
546 wxASSERT_MSG( m_menuBar, wxT("can't detach menu if it's not attached") );
c5fb56c0 547 m_menuBar = NULL;
61243a51 548} // end of wxMenu::Detach
c5fb56c0 549
61243a51 550wxWindow* wxMenu::GetWindow() const
c5fb56c0 551{
61243a51 552 if (m_invokingWindow != NULL)
c5fb56c0
DW
553 return m_invokingWindow;
554 else if ( m_menuBar != NULL)
555 return m_menuBar->GetFrame();
556
557 return NULL;
61243a51 558} // end of wxMenu::GetWindow
0e320a79 559
75f11ad7 560// ---------------------------------------------------------------------------
0e320a79 561// Menu Bar
75f11ad7
DW
562// ---------------------------------------------------------------------------
563
564void wxMenuBar::Init()
0e320a79
DW
565{
566 m_eventHandler = this;
61243a51 567 m_pMenuBarFrame = NULL;
75f11ad7 568 m_hMenu = 0;
61243a51 569} // end of wxMenuBar::Init
0e320a79 570
75f11ad7
DW
571wxMenuBar::wxMenuBar()
572{
573 Init();
61243a51 574} // end of wxMenuBar::wxMenuBar
0e320a79 575
61243a51
DW
576wxMenuBar::wxMenuBar(
577 long WXUNUSED(lStyle)
578)
0e320a79 579{
75f11ad7 580 Init();
61243a51 581} // end of wxMenuBar::wxMenuBar
75f11ad7 582
61243a51
DW
583wxMenuBar::wxMenuBar(
584 int nCount
585, wxMenu* vMenus[]
586, const wxString sTitles[]
587)
75f11ad7
DW
588{
589 Init();
590
61243a51
DW
591 m_titles.Alloc(nCount);
592 for ( int i = 0; i < nCount; i++ )
c5fb56c0 593 {
61243a51
DW
594 m_menus.Append(vMenus[i]);
595 m_titles.Add(sTitles[i]);
596 vMenus[i]->Attach(this);
c5fb56c0 597 }
61243a51 598} // end of wxMenuBar::wxMenuBar
0e320a79
DW
599
600wxMenuBar::~wxMenuBar()
601{
61243a51 602} // end of wxMenuBar::~wxMenuBar
0e320a79 603
75f11ad7
DW
604// ---------------------------------------------------------------------------
605// wxMenuBar helpers
606// ---------------------------------------------------------------------------
607
61243a51 608void wxMenuBar::Refresh()
75f11ad7 609{
c5fb56c0 610 wxCHECK_RET( IsAttached(), wxT("can't refresh unatteched menubar") );
75f11ad7 611
c5fb56c0 612// DrawMenuBar(GetHwndOf(m_menuBarFrame));
75f11ad7
DW
613}
614
615WXHMENU wxMenuBar::Create()
616{
61243a51
DW
617 MENUITEM vItem;
618
75f11ad7 619 if (m_hMenu != 0 )
c5fb56c0 620 return m_hMenu;
75f11ad7 621
61243a51
DW
622 wxCHECK_MSG(!m_hMenu, TRUE, wxT("menubar already created"));
623
624 //
625 // Create an empty menu and then fill it with insertions
626 //
627 m_hMenu = ::WinCreateWindow( HWND_DESKTOP // parent
628 ,WC_MENU // type
629 ,"Menu" // a generic name
630 ,0L // no style flag
631 ,0L,0L,0L,0L // no position
632 ,NULLHANDLE // no owner
633 ,NULLHANDLE // no insertion position
634 ,0L // no ID needed for dynamic creation
635 ,NULL // no control data
636 ,NULL // no presentation params
637 );
638 if (!m_hMenu)
75f11ad7
DW
639 {
640 wxLogLastError("CreateMenu");
641 }
642 else
643 {
61243a51
DW
644 size_t nCount = GetMenuCount();
645
646 for (size_t i = 0; i < nCount; i++)
75f11ad7 647 {
61243a51
DW
648 vItem.iPosition = 0;
649 vItem.afStyle = MIS_SUBMENU | MIS_TEXT;
650 vItem.afAttribute = (USHORT)0;
651 vItem.id = (USHORT)0;
652 vItem.hwndSubMenu = m_menus[i]->GetHMenu();
653 vItem.hItem = NULLHANDLE;
654
655 ::WinSendMsg(GetHmenu(), MM_INSERTITEM, (MPARAM)&vItem, (MPARAM)m_titles[i].c_str());
75f11ad7
DW
656 }
657 }
75f11ad7 658 return m_hMenu;
61243a51 659} // end of wxMenuBar::Create
0e320a79 660
75f11ad7 661// ---------------------------------------------------------------------------
c5fb56c0 662// wxMenuBar functions to work with the top level submenus
75f11ad7
DW
663// ---------------------------------------------------------------------------
664
61243a51 665//
c5fb56c0
DW
666// NB: we don't support owner drawn top level items for now, if we do these
667// functions would have to be changed to use wxMenuItem as well
61243a51
DW
668//
669void wxMenuBar::EnableTop(
670 size_t nPos
671, bool bEnable
672)
0e320a79 673{
61243a51
DW
674 wxCHECK_RET(IsAttached(), wxT("doesn't work with unattached menubars"));
675 USHORT uFlag = 0;
676 SHORT nId;
0e320a79 677
61243a51
DW
678 if(!bEnable)
679 uFlag = MIA_DISABLED;
75f11ad7 680
61243a51
DW
681 nId = SHORT1FROMMR(::WinSendMsg((HWND)m_hMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(nPos), (MPARAM)0));
682 if (nId == MIT_ERROR)
683 {
684 wxLogLastError("LogLastError");
685 return;
686 }
687 ::WinSendMsg((HWND)m_hMenu, MM_SETITEMATTR, MPFROM2SHORT(nId, TRUE), MPFROM2SHORT(uFlag, uFlag));
c5fb56c0 688 Refresh();
61243a51 689} // end of wxMenuBar::EnableTop
75f11ad7 690
61243a51
DW
691void wxMenuBar::SetLabelTop(
692 size_t nPos
693, const wxString& rLabel
694)
75f11ad7 695{
61243a51
DW
696 SHORT nId;
697 MENUITEM vItem;
75f11ad7 698
61243a51
DW
699 wxCHECK_RET(nPos < GetMenuCount(), wxT("invalid menu index"));
700 m_titles[nPos] = rLabel;
75f11ad7 701
61243a51 702 if (!IsAttached())
c5fb56c0
DW
703 {
704 return;
705 }
75f11ad7 706
61243a51
DW
707 nId = SHORT1FROMMR(::WinSendMsg((HWND)m_hMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(nPos), (MPARAM)0));
708 if (nId == MIT_ERROR)
75f11ad7 709 {
61243a51 710 wxLogLastError("LogLastError");
75f11ad7
DW
711 return;
712 }
61243a51
DW
713 if(!::WinSendMsg( (HWND)m_hMenu
714 ,MM_QUERYITEM
715 ,MPFROM2SHORT(nId, TRUE)
716 ,MPARAM(&vItem)
717 ))
75f11ad7 718 {
61243a51 719 wxLogLastError("QueryItem");
c5fb56c0 720 }
61243a51 721 nId = vItem.id;
c5fb56c0 722
61243a51 723 if (::WinSendMsg(GetHmenu(), MM_SETITEMTEXT, MPFROMSHORT(nId), (MPARAM)rLabel.c_str()));
c5fb56c0
DW
724 {
725 wxLogLastError("ModifyMenu");
75f11ad7 726 }
c5fb56c0 727 Refresh();
61243a51 728} // end of wxMenuBar::SetLabelTop
0e320a79 729
61243a51
DW
730wxString wxMenuBar::GetLabelTop(
731 size_t nPos
732) const
0e320a79 733{
61243a51 734 wxCHECK_MSG( nPos < GetMenuCount(), wxEmptyString,
c5fb56c0 735 wxT("invalid menu index in wxMenuBar::GetLabelTop") );
61243a51
DW
736 return m_titles[nPos];
737} // end of wxMenuBar::GetLabelTop
75f11ad7 738
c5fb56c0
DW
739// ---------------------------------------------------------------------------
740// wxMenuBar construction
741// ---------------------------------------------------------------------------
75f11ad7 742
61243a51
DW
743wxMenu* wxMenuBar::Replace(
744 size_t nPos
745, wxMenu* pMenu
746, const wxString& rTitle
747)
75f11ad7 748{
61243a51
DW
749 SHORT nId;
750 wxMenu* pMenuOld = wxMenuBarBase::Replace( nPos
751 ,pMenu
752 ,rTitle
753 );
754
755
756 nId = SHORT1FROMMR(::WinSendMsg((HWND)m_hMenu, MM_ITEMIDFROMPOSITION, MPFROMSHORT(nPos), (MPARAM)0));
757 if (nId == MIT_ERROR)
758 {
759 wxLogLastError("LogLastError");
760 return NULL;
761 }
762 if (!pMenuOld)
c5fb56c0 763 return FALSE;
61243a51
DW
764 m_titles[nPos] = rTitle;
765 if (IsAttached())
75f11ad7 766 {
61243a51
DW
767 ::WinSendMsg((HWND)m_hMenu, MM_DELETEITEM, MPFROM2SHORT(nId, TRUE), (MPARAM)0);
768 ::WinSendMsg((HWND)m_hMenu, MM_INSERTITEM, (MPARAM)&pMenu->m_vMenuData, (MPARAM)rTitle.c_str());
c5fb56c0
DW
769
770#if wxUSE_ACCEL
61243a51 771 if (pMenuOld->HasAccels() || pMenu->HasAccels())
c5fb56c0 772 {
61243a51
DW
773 //
774 // Need to rebuild accell table
775 //
c5fb56c0
DW
776 RebuildAccelTable();
777 }
778#endif // wxUSE_ACCEL
c5fb56c0
DW
779 Refresh();
780 }
61243a51
DW
781 return pMenuOld;
782} // end of wxMenuBar::Replace
75f11ad7 783
61243a51
DW
784bool wxMenuBar::Insert(
785 size_t nPos
786, wxMenu* pMenu
787, const wxString& rTitle
788)
75f11ad7 789{
61243a51
DW
790 if (!wxMenuBarBase::Insert( nPos
791 ,pMenu
792 ,rTitle
793 ))
c5fb56c0 794 return FALSE;
75f11ad7 795
61243a51
DW
796 m_titles.Insert( rTitle
797 ,nPos
798 );
75f11ad7 799
61243a51 800 pMenu->Attach(this);
75f11ad7 801
61243a51
DW
802 if (IsAttached())
803 {
804 ::WinSendMsg((HWND)m_hMenu, MM_INSERTITEM, (MPARAM)&pMenu->m_vMenuData, (MPARAM)rTitle.c_str());
c5fb56c0 805#if wxUSE_ACCEL
61243a51 806 if (pMenu->HasAccels())
c5fb56c0
DW
807 {
808 // need to rebuild accell table
809 RebuildAccelTable();
810 }
811#endif // wxUSE_ACCEL
c5fb56c0 812 Refresh();
75f11ad7 813 }
c5fb56c0 814 return TRUE;
61243a51 815} // end of wxMenuBar::Insert
75f11ad7 816
61243a51
DW
817bool wxMenuBar::Append(
818 wxMenu* pMenu
819, const wxString& rTitle
820)
0e320a79 821{
61243a51
DW
822 WXHMENU hSubmenu = pMenu ? pMenu->GetHMenu() : 0;
823
824 wxCHECK_MSG(hSubmenu, FALSE, wxT("can't append invalid menu to menubar"));
0e320a79 825
61243a51 826 if (!wxMenuBarBase::Append(pMenu, rTitle))
c5fb56c0 827 return FALSE;
0e320a79 828
61243a51
DW
829 pMenu->Attach(this);
830 m_titles.Add(rTitle);
c5fb56c0 831
c5fb56c0 832 if ( IsAttached() )
0e320a79 833 {
61243a51
DW
834 pMenu->m_vMenuData.iPosition = MIT_END;
835 ::WinSendMsg((HWND)m_hMenu, MM_INSERTITEM, (MPARAM)&pMenu->m_vMenuData, (MPARAM)rTitle.c_str());
c5fb56c0 836#if wxUSE_ACCEL
61243a51 837 if (pMenu->HasAccels())
c5fb56c0 838 {
61243a51
DW
839 //
840 // Need to rebuild accell table
841 //
c5fb56c0
DW
842 RebuildAccelTable();
843 }
844#endif // wxUSE_ACCEL
c5fb56c0
DW
845 Refresh();
846 }
c5fb56c0 847 return TRUE;
61243a51 848} // end of wxMenuBar::Append
0e320a79 849
61243a51
DW
850wxMenu* wxMenuBar::Remove(
851 size_t nPos
852)
0e320a79 853{
61243a51
DW
854 wxMenu* pMenu = wxMenuBarBase::Remove(nPos);
855 SHORT nId;
856
857 if (!pMenu)
c5fb56c0 858 return NULL;
0e320a79 859
61243a51
DW
860 nId = SHORT1FROMMR(::WinSendMsg((HWND)GetHmenu(), MM_ITEMIDFROMPOSITION, MPFROMSHORT(nPos), (MPARAM)0));
861 if (nId == MIT_ERROR)
862 {
863 wxLogLastError("LogLastError");
864 return NULL;
865 }
866 if (IsAttached())
867 {
868 ::WinSendMsg((HWND)GetHmenu(), MM_DELETEITEM, MPFROM2SHORT(nId, TRUE), (MPARAM)0);
869 pMenu->Detach();
0e320a79 870
c5fb56c0 871#if wxUSE_ACCEL
61243a51 872 if (pMenu->HasAccels())
c5fb56c0 873 {
61243a51
DW
874 //
875 // Need to rebuild accell table
876 //
c5fb56c0
DW
877 RebuildAccelTable();
878 }
879#endif // wxUSE_ACCEL
c5fb56c0 880 Refresh();
0e320a79 881 }
61243a51
DW
882 m_titles.Remove(nPos);
883 return pMenu;
884} // end of wxMenuBar::Remove
75f11ad7
DW
885
886#if wxUSE_ACCEL
c5fb56c0
DW
887
888void wxMenuBar::RebuildAccelTable()
889{
61243a51
DW
890 //
891 // Merge the accelerators of all menus into one accel table
892 //
893 size_t nAccelCount = 0;
894 size_t i;
895 size_t nCount = GetMenuCount();
896
897 for (i = 0; i < nCount; i++)
75f11ad7
DW
898 {
899 nAccelCount += m_menus[i]->GetAccelCount();
900 }
901
61243a51 902 if (nAccelCount)
0e320a79 903 {
61243a51 904 wxAcceleratorEntry* pAccelEntries = new wxAcceleratorEntry[nAccelCount];
75f11ad7
DW
905
906 nAccelCount = 0;
61243a51 907 for (i = 0; i < nCount; i++)
75f11ad7 908 {
61243a51 909 nAccelCount += m_menus[i]->CopyAccels(&pAccelEntries[nAccelCount]);
75f11ad7 910 }
61243a51
DW
911 m_vAccelTable = wxAcceleratorTable( nAccelCount
912 ,pAccelEntries
913 );
914 delete [] pAccelEntries;
0e320a79 915 }
61243a51 916} // end of wxMenuBar::RebuildAccelTable
c5fb56c0
DW
917
918#endif // wxUSE_ACCEL
919
61243a51
DW
920void wxMenuBar::Attach(
921 wxFrame* pFrame
922)
c5fb56c0
DW
923{
924 wxASSERT_MSG( !IsAttached(), wxT("menubar already attached!") );
61243a51 925 m_pMenuBarFrame = pFrame;
c5fb56c0
DW
926
927#if wxUSE_ACCEL
928 RebuildAccelTable();
75f11ad7 929#endif // wxUSE_ACCEL
61243a51 930} // end of wxMenuBar::Attach
0e320a79 931
75f11ad7 932void wxMenuBar::Detach()
0e320a79 933{
61243a51 934 ::WinDestroyWindow((HWND)m_hMenu);
c5fb56c0 935 m_hMenu = (WXHMENU)NULL;
61243a51
DW
936 m_pMenuBarFrame = NULL;
937} // end of wxMenuBar::Detach
75f11ad7
DW
938
939// ---------------------------------------------------------------------------
940// wxMenuBar searching for menu items
941// ---------------------------------------------------------------------------
942
61243a51 943//
75f11ad7 944// Find the itemString in menuString, and return the item id or wxNOT_FOUND
61243a51
DW
945//
946int wxMenuBar::FindMenuItem(
947 const wxString& rMenuString
948, const wxString& rItemString
949) const
75f11ad7 950{
61243a51
DW
951 wxString sMenuLabel = wxStripMenuCodes(rMenuString);
952 size_t nCount = GetMenuCount();
953
954 for (size_t i = 0; i < nCount; i++)
75f11ad7 955 {
61243a51 956 wxString sTitle = wxStripMenuCodes(m_titles[i]);
75f11ad7 957
61243a51
DW
958 if (rMenuString == sTitle)
959 return m_menus[i]->FindItem(rItemString);
960 }
75f11ad7 961 return wxNOT_FOUND;
61243a51 962} // end of wxMenuBar::FindMenuItem
75f11ad7 963
61243a51
DW
964wxMenuItem* wxMenuBar::FindItem(
965 int nId
966, wxMenu** ppItemMenu
967) const
75f11ad7 968{
61243a51
DW
969 if (ppItemMenu)
970 *ppItemMenu = NULL;
971
972 wxMenuItem* pItem = NULL;
973 size_t nCount = GetMenuCount();
0e320a79 974
61243a51 975 for (size_t i = 0; !pItem && (i < nCount); i++)
75f11ad7 976 {
61243a51
DW
977 pItem = m_menus[i]->FindItem( nId
978 ,ppItemMenu
979 );
75f11ad7 980 }
61243a51
DW
981 return pItem;
982} // end of wxMenuBar::FindItem
75f11ad7 983