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