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