]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/menu.cpp
Cured DC/GDI object leak; listbox window proc restored from debugging
[wxWidgets.git] / src / msw / menu.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: menu.cpp
3// Purpose: wxMenu, wxMenuBar, wxMenuItem
4// Author: Julian Smart
5// Modified by: Vadim Zeitlin
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12
13// ============================================================================
14// headers & declarations
15// ============================================================================
16
17// wxWindows headers
18// -----------------
19
20#ifdef __GNUG__
21#pragma implementation "menu.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28#pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32#include "wx/frame.h"
33#include "wx/menu.h"
34#include "wx/utils.h"
35#endif
36
37#if USE_OWNER_DRAWN
38#include "wx/ownerdrw.h"
39#endif
40
41#include "wx/msw/private.h"
42#include "wx/msw/menu.h"
43#include "wx/menuitem.h"
44#include "wx/log.h"
45
46// other standard headers
47// ----------------------
48#include <string.h>
49
50#if !USE_SHARED_LIBRARY
51IMPLEMENT_DYNAMIC_CLASS(wxMenu, wxWindow)
52IMPLEMENT_DYNAMIC_CLASS(wxMenuBar, wxWindow)
53#endif
54
55// ============================================================================
56// implementation
57// ============================================================================
58
59// Menus
60
61// Construct a menu with optional title (then use append)
62wxMenu::wxMenu(const wxString& Title, const wxFunction func)
63{
64 m_title = Title;
65 m_parent = NULL;
66 m_eventHandler = this;
67 m_pInvokingWindow = NULL;
68 m_doBreak = FALSE ;
69 m_noItems = 0;
70 m_menuBar = NULL;
71 m_hMenu = (WXHMENU) CreatePopupMenu();
72 m_savehMenu = 0 ;
73 m_topLevelMenu = this;
74 if (m_title != "")
75 {
76 Append(-2, m_title) ;
77 AppendSeparator() ;
78 }
79
80 Callback(func);
81}
82
83// The wxWindow destructor will take care of deleting the submenus.
84wxMenu::~wxMenu(void)
85{
86 if (m_hMenu)
87 DestroyMenu((HMENU) m_hMenu);
88 m_hMenu = 0;
89
90 // Windows seems really bad on Menu de-allocation...
91 // After many try, here is what I do: RemoveMenu() will ensure
92 // that popup are "disconnected" from their parent; then call
93 // delete method on each child (which in turn do a recursive job),
94 // and finally, DestroyMenu()
95 //
96 // With that, BoundCheckers is happy, and no complaints...
97/*
98 int N = 0 ;
99 if (m_hMenu)
100 N = GetMenuItemCount(m_hMenu);
101 int i;
102 for (i = N-1; i >= 0; i--)
103 RemoveMenu(m_hMenu, i, MF_BYPOSITION);
104*/
105
106 // How is deleting submenus in this loop any different from deleting
107 // the submenus in the children list, via ~wxWindow ?
108 // I'll reinstate this deletion for now and remove addition
109 // from children list (which doesn't exist now)
110 // Julian 1/3/97
111 wxNode *node = m_menuItems.First();
112 while (node)
113 {
114 wxMenuItem *item = (wxMenuItem *)node->Data();
115
116 // Delete child menus.
117 // Beware: they must not be appended to children list!!!
118 // (because order of delete is significant)
119 if (item->GetSubMenu())
120 item->DeleteSubMenu();
121
122 wxNode *next = node->Next();
123 delete item;
124 delete node;
125 node = next;
126 }
127/*
128 if (m_hMenu)
129 DestroyMenu(m_hMenu);
130 m_hMenu = 0;
131*/
132}
133
134void wxMenu::Break(void)
135{
136 m_doBreak = TRUE ;
137}
138
139// function appends a new item or submenu to the menu
140void wxMenu::Append(wxMenuItem *pItem)
141{
142 wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" );
143
144 m_menuItems.Append(pItem);
145
146 UINT flags = 0;
147
148 if ( m_doBreak ) {
149 flags |= MF_MENUBREAK;
150 m_doBreak = FALSE;
151 }
152
153 if ( pItem->IsSeparator() ) {
154 flags |= MF_SEPARATOR;
155 }
156
157 // id is the numeric id for normal menu items and HMENU for submenus
158 UINT id;
159 wxMenu *SubMenu = pItem->GetSubMenu();
160 if ( SubMenu != NULL ) {
161 wxASSERT( SubMenu->m_hMenu != NULL );
162
163 id = (UINT)SubMenu->m_hMenu;
164
165 SubMenu->m_topLevelMenu = m_topLevelMenu;
166 SubMenu->m_parent = this;
167 SubMenu->m_savehMenu = (WXHMENU)id;
168 SubMenu->m_hMenu = 0;
169
170 flags |= MF_POPUP;
171 }
172 else {
173 id = pItem->GetId();
174 }
175
176 LPCSTR pData;
177 wxString name("");
178
179#if USE_OWNER_DRAWN
180 if ( pItem->IsOwnerDrawn() ) { // want to get {Measure|Draw}Item messages?
181 // item draws itself, pass pointer to it in data parameter
182 flags |= MF_OWNERDRAW;
183 pData = (LPCSTR)pItem;
184 }
185 else
186#endif
187 {
188 // menu is just a normal string (passed in data parameter)
189 flags |= MF_STRING;
190 name = pItem->GetName();
191 pData = (const char*) name;
192 }
193
194 // VZ: what does this magic -2 mean? I just copied the code but have no idea
195 // about what it does... ###
196 if ( pItem->GetId() == -2 ) {
197 flags |= MF_DISABLED | MF_GRAYED;
198 }
199
200 HMENU hMenu = (HMENU)((m_hMenu == 0) ? m_savehMenu : m_hMenu);
201
202 if ( !AppendMenu(hMenu, flags, id, pData) )
203 {
204 // wxLogLastError("AppendMenu");
205 }
206
207 m_noItems++;
208}
209
210void wxMenu::AppendSeparator(void)
211{
212 Append(new wxMenuItem(this, ID_SEPARATOR));
213}
214
215// Pullright item
216void wxMenu::Append(int Id, const wxString& label, wxMenu *SubMenu,
217 const wxString& helpString)
218{
219 Append(new wxMenuItem(this, Id, label, helpString, FALSE, SubMenu));
220}
221
222// Ordinary menu item
223void wxMenu::Append(int Id, const wxString& label,
224 const wxString& helpString, bool checkable)
225{
226 // 'checkable' parameter is useless for Windows.
227 Append(new wxMenuItem(this, Id, label, helpString, checkable));
228}
229
230void wxMenu::Delete(int id)
231{
232 wxNode *node;
233 wxMenuItem *item;
234 int pos;
235 HMENU menu;
236
237 for (pos = 0, node = m_menuItems.First(); node; node = node->Next(), pos++) {
238 item = (wxMenuItem *)node->Data();
239 if (item->GetId() == id)
240 break;
241 }
242
243 if (!node)
244 return;
245
246 menu = (HMENU)(m_hMenu ? m_hMenu : m_savehMenu);
247
248 wxMenu *pSubMenu = item->GetSubMenu();
249 if ( pSubMenu != NULL ) {
250 RemoveMenu(menu, (UINT)pos, MF_BYPOSITION);
251 pSubMenu->m_hMenu = pSubMenu->m_savehMenu;
252 pSubMenu->m_savehMenu = 0;
253 pSubMenu->m_parent = NULL;
254 // RemoveChild(item->subMenu);
255 pSubMenu->m_topLevelMenu = NULL;
256 // TODO: Why isn't subMenu deleted here???
257 // Will put this in for now. Assuming this is supposed
258 // to delete the menu, not just remove it.
259 item->DeleteSubMenu();
260 }
261 else {
262 DeleteMenu(menu, (UINT)pos, MF_BYPOSITION);
263 }
264
265 m_menuItems.DeleteNode(node);
266 delete item;
267}
268
269void wxMenu::Enable(int Id, bool Flag)
270{
271 wxMenuItem *item = FindItemForId(Id);
272 wxCHECK_RET( item != NULL, "can't enable non-existing menu item" );
273
274 item->Enable(Flag);
275}
276
277bool wxMenu::Enabled(int Id) const
278{
279 wxMenuItem *item = FindItemForId(Id);
280 wxCHECK( item != NULL, FALSE );
281
282 return item->IsEnabled();
283}
284
285void wxMenu::Check(int Id, bool Flag)
286{
287 wxMenuItem *item = FindItemForId(Id);
288 wxCHECK_RET( item != NULL, "can't get status of non-existing menu item" );
289
290 item->Check(Flag);
291}
292
293bool wxMenu::Checked(int Id) const
294{
295 wxMenuItem *item = FindItemForId(Id);
296 wxCHECK( item != NULL, FALSE );
297
298 return item->IsChecked();
299}
300
301void wxMenu::SetTitle(const wxString& label)
302{
303 m_title = label ;
304 if (m_hMenu)
305 ModifyMenu((HMENU)m_hMenu, 0,
306 MF_BYPOSITION | MF_STRING | MF_DISABLED,
307 (UINT)-2, (const char *)m_title);
308 else if (m_savehMenu)
309 ModifyMenu((HMENU)m_savehMenu, 0,
310 MF_BYPOSITION | MF_STRING | MF_DISABLED,
311 (UINT)-2, (const char *)m_title);
312}
313
314const wxString& wxMenu::GetTitle() const
315{
316 return m_title;
317}
318
319void wxMenu::SetLabel(int Id, const wxString& label)
320{
321 wxMenuItem *item = FindItemForId(Id) ;
322 if (item==NULL)
323 return;
324
325 if (item->GetSubMenu()==NULL)
326 {
327 if (m_hMenu)
328 {
329 UINT was_flag = GetMenuState((HMENU)m_hMenu,Id,MF_BYCOMMAND) ;
330 ModifyMenu((HMENU)m_hMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
331 }
332 else if (m_savehMenu)
333 {
334 UINT was_flag = GetMenuState((HMENU)m_savehMenu,Id,MF_BYCOMMAND) ;
335 ModifyMenu((HMENU)m_savehMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
336 }
337 }
338 else
339 {
340 wxMenu *father = item->GetSubMenu()->m_topLevelMenu ;
341 wxNode *node = father->m_menuItems.First() ;
342 int i = 0 ;
343 while (node)
344 {
345 wxMenuItem *matched = (wxMenuItem*)node->Data() ;
346 if (matched==item)
347 break ;
348 i++ ;
349 node = node->Next() ;
350 }
351 // Here, we have the position.
352 ModifyMenu((HMENU)father->m_savehMenu,i,
353 MF_BYPOSITION|MF_STRING|MF_POPUP,
354 (UINT)item->GetSubMenu()->m_savehMenu,(const char *)label) ;
355 }
356 item->SetName(label);
357}
358
359wxString wxMenu::GetLabel(int Id) const
360{
361 static char tmp[128] ;
362 int len;
363 if (m_hMenu)
364 len = GetMenuString((HMENU)m_hMenu,Id,tmp,WXSIZEOF(tmp) - 1,MF_BYCOMMAND);
365 else if (m_savehMenu)
366 len = GetMenuString((HMENU)m_savehMenu,Id,tmp,WXSIZEOF(tmp) - 1,MF_BYCOMMAND);
367 else
368 len = 0 ;
369 tmp[len] = '\0' ;
370 return wxString(tmp) ;
371}
372
373bool wxMenu::MSWCommand(const WXUINT WXUNUSED(param), const WXWORD id)
374{
375 wxCommandEvent event(wxEVENT_TYPE_MENU_COMMAND);
376 event.SetEventObject( this );
377 event.SetId( id );
378 event.SetInt( id );
379 ProcessCommand(event);
380 return TRUE;
381}
382
383// Finds the item id matching the given string, -1 if not found.
384int wxMenu::FindItem (const wxString& itemString) const
385{
386 char buf1[200];
387 char buf2[200];
388 wxStripMenuCodes ((char *)(const char *)itemString, buf1);
389
390 for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
391 {
392 wxMenuItem *item = (wxMenuItem *) node->Data ();
393 if (item->GetSubMenu())
394 {
395 int ans = item->GetSubMenu()->FindItem(itemString);
396 if (ans > -1)
397 return ans;
398 }
399 if ( !item->IsSeparator() )
400 {
401 wxStripMenuCodes((char *)item->GetName().c_str(), buf2);
402 if (strcmp(buf1, buf2) == 0)
403 return item->GetId();
404 }
405 }
406
407 return -1;
408}
409
410wxMenuItem *wxMenu::FindItemForId(const int itemId, wxMenu ** itemMenu) const
411{
412 if (itemMenu)
413 *itemMenu = NULL;
414 for (wxNode * node = m_menuItems.First (); node; node = node->Next ())
415 {
416 wxMenuItem *item = (wxMenuItem *) node->Data ();
417
418 if (item->GetId() == itemId)
419 {
420 if (itemMenu)
421 *itemMenu = (wxMenu *) this;
422 return item;
423 }
424
425 if (item->GetSubMenu())
426 {
427 wxMenuItem *ans = item->GetSubMenu()->FindItemForId (itemId, itemMenu);
428 if (ans)
429 return ans;
430 }
431 }
432
433 if (itemMenu)
434 *itemMenu = NULL;
435 return NULL;
436}
437
438void wxMenu::SetHelpString(const int itemId, const wxString& helpString)
439{
440 wxMenuItem *item = FindItemForId (itemId);
441 if (item)
442 item->SetHelp(helpString);
443}
444
445wxString wxMenu::GetHelpString (const int itemId) const
446{
447 wxMenuItem *item = FindItemForId (itemId);
448 wxString str("");
449 return (item == NULL) ? str : item->GetHelp();
450}
451
452void wxMenu::ProcessCommand(wxCommandEvent & event)
453{
454 bool processed = FALSE;
455
456 // Try a callback
457 if (m_callback)
458 {
459 (void) (*(m_callback)) (*this, event);
460 processed = TRUE;
461 }
462
463 // Try the menu's event handler
464 if ( !processed && GetEventHandler())
465 {
466 processed = GetEventHandler()->ProcessEvent(event);
467 }
468
469 // Try the window the menu was popped up from (and up
470 // through the hierarchy)
471 if ( !processed && GetInvokingWindow())
472 processed = GetInvokingWindow()->ProcessEvent(event);
473}
474
475extern wxMenu *wxCurrentPopupMenu;
476bool wxWindow::PopupMenu(wxMenu *menu, const int x, const int y)
477{
478 menu->SetInvokingWindow(this);
479
480 HWND hWnd = (HWND) GetHWND();
481 HMENU hMenu = (HMENU)menu->m_hMenu;
482 POINT point;
483 point.x = x;
484 point.y = y;
485 ::ClientToScreen(hWnd, &point);
486 wxCurrentPopupMenu = menu;
487 ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
488 wxYield();
489 wxCurrentPopupMenu = NULL;
490
491 menu->SetInvokingWindow(NULL);
492
493 return TRUE;
494}
495
496// Menu Bar
497wxMenuBar::wxMenuBar(void)
498{
499 m_eventHandler = this;
500
501 m_menuCount = 0;
502 m_menus = NULL;
503 m_titles = NULL;
504 m_menuBarFrame = NULL;
505 m_hMenu = 0;
506}
507
508wxMenuBar::wxMenuBar(const int N, wxMenu *Menus[], const wxString Titles[])
509{
510 m_eventHandler = this;
511 m_menuCount = N;
512 m_menus = Menus;
513 m_titles = new wxString[N];
514 int i;
515 for ( i = 0; i < N; i++ )
516 m_titles[i] = Titles[i];
517 m_menuBarFrame = NULL;
518 for (i = 0; i < N; i++)
519 m_menus[i]->m_menuBar = (wxMenuBar *) this;
520
521 m_hMenu = 0;
522}
523
524wxMenuBar::~wxMenuBar(void)
525{
526 // In fact, don't want menu to be destroyed before MDI
527 // shuffling has taken place. Let it be destroyed
528 // automatically when the window is destroyed.
529
530// DestroyMenu(menu);
531// m_hMenu = NULL;
532
533 int i;
534/*
535 // See remarks in ::~wxMenu() method
536 // BEWARE - this may interfere with MDI fixes, so
537 // may need to remove
538 int N = 0 ;
539
540 if (m_menuBarFrame && ((m_menuBarFrame->GetWindowStyleFlag() & wxSDI) == wxSDI))
541 {
542 if (menu)
543 N = GetMenuItemCount(menu) ;
544 for (i = N-1; i >= 0; i--)
545 RemoveMenu(menu, i, MF_BYPOSITION);
546 }
547*/
548 for (i = 0; i < m_menuCount; i++)
549 {
550 delete m_menus[i];
551 }
552 delete[] m_menus;
553 delete[] m_titles;
554
555/* Don't destroy menu here, in case we're MDI and
556 need to do some shuffling with VALID menu handles.
557 if (menu)
558 DestroyMenu(menu);
559 m_hMenu = 0;
560*/
561}
562
563// Must only be used AFTER menu has been attached to frame,
564// otherwise use individual menus to enable/disable items
565void wxMenuBar::Enable(const int Id, const bool Flag)
566{
567 int ms_flag;
568 if (Flag)
569 ms_flag = MF_ENABLED;
570 else
571 ms_flag = MF_GRAYED;
572
573 wxMenu *itemMenu = NULL;
574 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
575 if (!item)
576 return;
577
578 if (itemMenu->m_hMenu)
579 EnableMenuItem((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND | ms_flag);
580 else if (itemMenu->m_savehMenu)
581 EnableMenuItem((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND | ms_flag);
582
583}
584
585void wxMenuBar::EnableTop(const int pos, const bool flag)
586{
587 int ms_flag;
588 if (flag)
589 ms_flag = MF_ENABLED;
590 else
591 ms_flag = MF_GRAYED;
592
593 EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | ms_flag);
594 DrawMenuBar((HWND) m_menuBarFrame->GetHWND()) ;
595}
596
597// Must only be used AFTER menu has been attached to frame,
598// otherwise use individual menus
599void wxMenuBar::Check(const int Id, const bool Flag)
600{
601 wxMenu *itemMenu = NULL;
602 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
603 if (!item)
604 return;
605
606 if (!item->IsCheckable())
607 return ;
608 int ms_flag;
609 if (Flag)
610 ms_flag = MF_CHECKED;
611 else
612 ms_flag = MF_UNCHECKED;
613
614 if (itemMenu->m_hMenu)
615 CheckMenuItem((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND | ms_flag);
616 else if (itemMenu->m_savehMenu)
617 CheckMenuItem((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND | ms_flag);
618
619// CheckMenuItem((HMENU)m_hMenu, Id, MF_BYCOMMAND | ms_flag);
620}
621
622bool wxMenuBar::Checked(const int Id) const
623{
624 wxMenu *itemMenu = NULL;
625 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
626 if (!item)
627 return FALSE;
628
629 int Flag ;
630
631 if (itemMenu->m_hMenu)
632 Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ;
633 else if (itemMenu->m_savehMenu)
634 Flag=GetMenuState((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND) ;
635
636// Flag=GetMenuState((HMENU)m_hMenu, Id, MF_BYCOMMAND) ;
637
638 if (Flag&MF_CHECKED)
639 return TRUE ;
640 else
641 return FALSE ;
642}
643
644bool wxMenuBar::Enabled(const int Id) const
645{
646 wxMenu *itemMenu = NULL;
647 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
648 if (!item)
649 return FALSE;
650
651 int Flag ;
652
653 if (itemMenu->m_hMenu)
654 Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ;
655 else if (itemMenu->m_savehMenu)
656 Flag=GetMenuState((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND) ;
657
658 if (Flag&MF_ENABLED)
659 return TRUE ;
660 else
661 return FALSE ;
662}
663
664
665void wxMenuBar::SetLabel(const int Id, const wxString& label)
666{
667 wxMenu *itemMenu = NULL;
668 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
669
670 if (!item)
671 return;
672
673 if (itemMenu->m_hMenu)
674 {
675 UINT was_flag = GetMenuState((HMENU)itemMenu->m_hMenu,Id,MF_BYCOMMAND) ;
676 ModifyMenu((HMENU)itemMenu->m_hMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
677 }
678 else if (itemMenu->m_savehMenu)
679 {
680 UINT was_flag = GetMenuState((HMENU)itemMenu->m_savehMenu,Id,MF_BYCOMMAND) ;
681 ModifyMenu((HMENU)itemMenu->m_savehMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
682 }
683}
684
685wxString wxMenuBar::GetLabel(const int Id) const
686{
687 wxMenu *itemMenu = NULL;
688 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
689
690 if (!item)
691 return wxString("");
692
693 static char tmp[128] ;
694 int len = 0;
695 if (itemMenu->m_hMenu)
696 {
697 len = GetMenuString((HMENU)itemMenu->m_hMenu,Id,tmp,127,MF_BYCOMMAND) ;
698 }
699 else if (itemMenu->m_savehMenu)
700 {
701 len = GetMenuString((HMENU)itemMenu->m_savehMenu,Id,tmp,127,MF_BYCOMMAND) ;
702 }
703
704// int len = GetMenuString((HMENU)m_hMenu,Id,tmp,127,MF_BYCOMMAND) ;
705 tmp[len] = '\0' ;
706 return wxString(tmp) ;
707}
708
709void wxMenuBar::SetLabelTop(const int pos, const wxString& label)
710{
711 UINT was_flag = GetMenuState((HMENU)m_hMenu,pos,MF_BYPOSITION) ;
712 if (was_flag&MF_POPUP)
713 {
714 was_flag &= 0xff ;
715 HMENU popup = GetSubMenu((HMENU)m_hMenu,pos) ;
716 ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,(UINT)popup,(const char *)label) ;
717 }
718 else
719 ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,pos,(const char *)label) ;
720}
721
722wxString wxMenuBar::GetLabelTop(const int pos) const
723{
724 static char tmp[128] ;
725 int len = GetMenuString((HMENU)m_hMenu,pos,tmp,127,MF_BYPOSITION) ;
726 tmp[len] = '\0' ;
727 return wxString(tmp);
728}
729
730bool wxMenuBar::OnDelete(wxMenu *a_menu, const int pos)
731{
732 if (!m_menuBarFrame)
733 return TRUE;
734
735 if (RemoveMenu((HMENU)m_hMenu, (UINT)pos, MF_BYPOSITION)) {
736 m_menus[pos]->m_hMenu = m_menus[pos]->m_savehMenu;
737 m_menus[pos]->m_savehMenu = 0;
738
739 if (m_menuBarFrame) {
740 DrawMenuBar((HWND) m_menuBarFrame->GetHWND()) ;
741 }
742
743 return TRUE;
744 }
745
746 return FALSE;
747}
748
749bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
750{
751 if (!a_menu->m_hMenu)
752 return FALSE;
753
754 if (!m_menuBarFrame)
755 return TRUE;
756
757 a_menu->m_savehMenu = a_menu->m_hMenu;
758 a_menu->m_hMenu = 0;
759
760 AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING, (UINT)a_menu->m_savehMenu, title);
761
762 DrawMenuBar((HWND) m_menuBarFrame->GetHWND());
763
764 return TRUE;
765}
766
767void wxMenuBar::Append (wxMenu * menu, const wxString& title)
768{
769 if (!OnAppend(menu, title))
770 return;
771
772 m_menuCount ++;
773 wxMenu **new_menus = new wxMenu *[m_menuCount];
774 wxString *new_titles = new wxString[m_menuCount];
775 int i;
776
777 for (i = 0; i < m_menuCount - 1; i++)
778 {
779 new_menus[i] = m_menus[i];
780 m_menus[i] = NULL;
781 new_titles[i] = m_titles[i];
782 m_titles[i] = "";
783 }
784 if (m_menus)
785 {
786 delete[]m_menus;
787 delete[]m_titles;
788 }
789 m_menus = new_menus;
790 m_titles = new_titles;
791
792 m_menus[m_menuCount - 1] = (wxMenu *)menu;
793 m_titles[m_menuCount - 1] = title;
794
795 ((wxMenu *)menu)->m_menuBar = (wxMenuBar *) this;
796 ((wxMenu *)menu)->SetParent(this);
797}
798
799void wxMenuBar::Delete(wxMenu * menu, const int i)
800{
801 int j;
802 int ii = (int) i;
803
804 if (menu != 0) {
805 for (ii = 0; ii < m_menuCount; ii++) {
806 if (m_menus[ii] == menu)
807 break;
808 }
809 if (ii >= m_menuCount)
810 return;
811 } else {
812 if (ii < 0 || ii >= m_menuCount)
813 return;
814 menu = m_menus[ii];
815 }
816
817 if (!OnDelete(menu, ii))
818 return;
819
820 menu->SetParent(NULL);
821
822 -- m_menuCount;
823 for (j = ii; j < m_menuCount; j++) {
824 m_menus[j] = m_menus[j + 1];
825 m_titles[j] = m_titles[j + 1];
826 }
827}
828
829// Find the menu menuString, item itemString, and return the item id.
830// Returns -1 if none found.
831int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const
832{
833 char buf1[200];
834 char buf2[200];
835 wxStripMenuCodes ((char *)(const char *)menuString, buf1);
836 int i;
837 for (i = 0; i < m_menuCount; i++)
838 {
839 wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2);
840 if (strcmp (buf1, buf2) == 0)
841 return m_menus[i]->FindItem (itemString);
842 }
843 return -1;
844}
845
846wxMenuItem *wxMenuBar::FindItemForId (const int Id, wxMenu ** itemMenu) const
847{
848 if (itemMenu)
849 *itemMenu = NULL;
850
851 wxMenuItem *item = NULL;
852 int i;
853 for (i = 0; i < m_menuCount; i++)
854 if ((item = m_menus[i]->FindItemForId (Id, itemMenu)))
855 return item;
856 return NULL;
857}
858
859void wxMenuBar::SetHelpString (const int Id, const wxString& helpString)
860{
861 int i;
862 for (i = 0; i < m_menuCount; i++)
863 {
864 if (m_menus[i]->FindItemForId (Id))
865 {
866 m_menus[i]->SetHelpString (Id, helpString);
867 return;
868 }
869 }
870}
871
872wxString wxMenuBar::GetHelpString (const int Id) const
873{
874 int i;
875 for (i = 0; i < m_menuCount; i++)
876 {
877 if (m_menus[i]->FindItemForId (Id))
878 return wxString(m_menus[i]->GetHelpString (Id));
879 }
880 return wxString("");
881}
882
883wxWindow *wxMenu::GetWindow() const
884{
885 if ( m_pInvokingWindow != NULL )
886 return m_pInvokingWindow;
887 if ( m_menuBar != NULL)
888 return m_menuBar->m_menuBarFrame;
889 return NULL;
890}
891
892WXHMENU wxMenu::GetHMenu() const
893{
894 if ( m_hMenu != 0 )
895 return m_hMenu;
896 else if ( m_savehMenu != 0 )
897 return m_savehMenu;
898
899 return 0;
900}
901