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