]> git.saurik.com Git - wxWidgets.git/blob - src/msw/menu.cpp
A few resize bugs removed
[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(wxEVT_COMMAND_MENU_SELECTED);
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 if (item)
490 return item->GetHelp();
491 else
492 return wxEmptyString;
493 }
494
495 void wxMenu::ProcessCommand(wxCommandEvent & event)
496 {
497 bool processed = FALSE;
498
499 // Try a callback
500 if (m_callback)
501 {
502 (void)(*(m_callback))(*this, event);
503 processed = TRUE;
504 }
505
506 // Try the menu's event handler
507 if ( !processed && GetEventHandler())
508 {
509 processed = GetEventHandler()->ProcessEvent(event);
510 }
511
512 // Try the window the menu was popped up from (and up
513 // through the hierarchy)
514 if ( !processed && GetInvokingWindow())
515 processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
516 }
517
518 extern wxMenu *wxCurrentPopupMenu;
519 bool wxWindow::PopupMenu(wxMenu *menu, int x, int y)
520 {
521 menu->SetInvokingWindow(this);
522
523 HWND hWnd = (HWND) GetHWND();
524 HMENU hMenu = (HMENU)menu->m_hMenu;
525 POINT point;
526 point.x = x;
527 point.y = y;
528 ::ClientToScreen(hWnd, &point);
529 wxCurrentPopupMenu = menu;
530 ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
531 wxYield();
532 wxCurrentPopupMenu = NULL;
533
534 menu->SetInvokingWindow(NULL);
535
536 return TRUE;
537 }
538
539 // Menu Bar
540 wxMenuBar::wxMenuBar()
541 {
542 m_eventHandler = this;
543
544 m_menuCount = 0;
545 m_menus = NULL;
546 m_titles = NULL;
547 m_menuBarFrame = NULL;
548 m_hMenu = 0;
549 }
550
551 wxMenuBar::wxMenuBar(int N, wxMenu *Menus[], const wxString Titles[])
552 {
553 m_eventHandler = this;
554 m_menuCount = N;
555 m_menus = Menus;
556 m_titles = new wxString[N];
557 int i;
558 for ( i = 0; i < N; i++ )
559 m_titles[i] = Titles[i];
560 m_menuBarFrame = NULL;
561 for (i = 0; i < N; i++)
562 m_menus[i]->m_menuBar = (wxMenuBar *) this;
563
564 m_hMenu = 0;
565 }
566
567 wxMenuBar::~wxMenuBar()
568 {
569 // In fact, don't want menu to be destroyed before MDI
570 // shuffling has taken place. Let it be destroyed
571 // automatically when the window is destroyed.
572
573 // DestroyMenu(menu);
574 // m_hMenu = NULL;
575
576 int i;
577 /*
578 // See remarks in ::~wxMenu() method
579 // BEWARE - this may interfere with MDI fixes, so
580 // may need to remove
581 int N = 0 ;
582
583 if (m_menuBarFrame && ((m_menuBarFrame->GetWindowStyleFlag() & wxSDI) == wxSDI))
584 {
585 if (menu)
586 N = GetMenuItemCount(menu) ;
587 for (i = N-1; i >= 0; i--)
588 RemoveMenu(menu, i, MF_BYPOSITION);
589 }
590 */
591 for (i = 0; i < m_menuCount; i++)
592 {
593 delete m_menus[i];
594 }
595 delete[] m_menus;
596 delete[] m_titles;
597
598 /* Don't destroy menu here, in case we're MDI and
599 need to do some shuffling with VALID menu handles.
600 if (menu)
601 DestroyMenu(menu);
602 m_hMenu = 0;
603 */
604 }
605
606 // Must only be used AFTER menu has been attached to frame,
607 // otherwise use individual menus to enable/disable items
608 void wxMenuBar::Enable(int Id, bool Flag)
609 {
610 int ms_flag;
611 if (Flag)
612 ms_flag = MF_ENABLED;
613 else
614 ms_flag = MF_GRAYED;
615
616 wxMenu *itemMenu = NULL;
617 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
618 if (!item)
619 return;
620
621 if (itemMenu->m_hMenu)
622 EnableMenuItem((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND | ms_flag);
623 else if (itemMenu->m_savehMenu)
624 EnableMenuItem((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND | ms_flag);
625
626 }
627
628 void wxMenuBar::EnableTop(int pos, bool flag)
629 {
630 int ms_flag;
631 if (flag)
632 ms_flag = MF_ENABLED;
633 else
634 ms_flag = MF_GRAYED;
635
636 EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | ms_flag);
637 DrawMenuBar((HWND) m_menuBarFrame->GetHWND()) ;
638 }
639
640 // Must only be used AFTER menu has been attached to frame,
641 // otherwise use individual menus
642 void wxMenuBar::Check(int Id, bool Flag)
643 {
644 wxMenu *itemMenu = NULL;
645 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
646 if (!item)
647 return;
648
649 if (!item->IsCheckable())
650 return ;
651 int ms_flag;
652 if (Flag)
653 ms_flag = MF_CHECKED;
654 else
655 ms_flag = MF_UNCHECKED;
656
657 if (itemMenu->m_hMenu)
658 CheckMenuItem((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND | ms_flag);
659 else if (itemMenu->m_savehMenu)
660 CheckMenuItem((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND | ms_flag);
661
662 // CheckMenuItem((HMENU)m_hMenu, Id, MF_BYCOMMAND | ms_flag);
663 }
664
665 bool wxMenuBar::Checked(int Id) const
666 {
667 wxMenu *itemMenu = NULL;
668 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
669 if (!item)
670 return FALSE;
671
672 int Flag = 0;
673
674 if (itemMenu->m_hMenu)
675 Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ;
676 else if (itemMenu->m_savehMenu)
677 Flag=GetMenuState((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND) ;
678
679 // Flag=GetMenuState((HMENU)m_hMenu, Id, MF_BYCOMMAND) ;
680
681 if (Flag&MF_CHECKED)
682 return TRUE ;
683 else
684 return FALSE ;
685 }
686
687 bool wxMenuBar::Enabled(int Id) const
688 {
689 wxMenu *itemMenu = NULL;
690 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
691 if (!item)
692 return FALSE;
693
694 int Flag ;
695
696 if (itemMenu->m_hMenu)
697 Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ;
698 else if (itemMenu->m_savehMenu)
699 Flag=GetMenuState((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND) ;
700
701 if (Flag&MF_ENABLED)
702 return TRUE ;
703 else
704 return FALSE ;
705 }
706
707
708 void wxMenuBar::SetLabel(int Id, const wxString& label)
709 {
710 wxMenu *itemMenu = NULL;
711 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
712
713 if (!item)
714 return;
715
716 if (itemMenu->m_hMenu)
717 {
718 UINT was_flag = GetMenuState((HMENU)itemMenu->m_hMenu,Id,MF_BYCOMMAND) ;
719 ModifyMenu((HMENU)itemMenu->m_hMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
720 }
721 else if (itemMenu->m_savehMenu)
722 {
723 UINT was_flag = GetMenuState((HMENU)itemMenu->m_savehMenu,Id,MF_BYCOMMAND) ;
724 ModifyMenu((HMENU)itemMenu->m_savehMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
725 }
726 }
727
728 wxString wxMenuBar::GetLabel(int Id) const
729 {
730 wxMenu *itemMenu = NULL;
731 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
732
733 if (!item)
734 return wxString("");
735
736 static char tmp[128] ;
737 int len = 0;
738 if (itemMenu->m_hMenu)
739 {
740 len = GetMenuString((HMENU)itemMenu->m_hMenu,Id,tmp,127,MF_BYCOMMAND) ;
741 }
742 else if (itemMenu->m_savehMenu)
743 {
744 len = GetMenuString((HMENU)itemMenu->m_savehMenu,Id,tmp,127,MF_BYCOMMAND) ;
745 }
746
747 // int len = GetMenuString((HMENU)m_hMenu,Id,tmp,127,MF_BYCOMMAND) ;
748 tmp[len] = '\0' ;
749 return wxString(tmp) ;
750 }
751
752 void wxMenuBar::SetLabelTop(int pos, const wxString& label)
753 {
754 UINT was_flag = GetMenuState((HMENU)m_hMenu,pos,MF_BYPOSITION) ;
755 if (was_flag&MF_POPUP)
756 {
757 was_flag &= 0xff ;
758 HMENU popup = GetSubMenu((HMENU)m_hMenu,pos) ;
759 ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,(UINT)popup,(const char *)label) ;
760 }
761 else
762 ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,pos,(const char *)label) ;
763 }
764
765 wxString wxMenuBar::GetLabelTop(int pos) const
766 {
767 static char tmp[128] ;
768 int len = GetMenuString((HMENU)m_hMenu,pos,tmp,127,MF_BYPOSITION) ;
769 tmp[len] = '\0' ;
770 return wxString(tmp);
771 }
772
773 bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos)
774 {
775 if (!m_menuBarFrame)
776 return TRUE;
777
778 if (RemoveMenu((HMENU)m_hMenu, (UINT)pos, MF_BYPOSITION)) {
779 m_menus[pos]->m_hMenu = m_menus[pos]->m_savehMenu;
780 m_menus[pos]->m_savehMenu = 0;
781
782 if (m_menuBarFrame) {
783 DrawMenuBar((HWND) m_menuBarFrame->GetHWND()) ;
784 }
785
786 return TRUE;
787 }
788
789 return FALSE;
790 }
791
792 bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
793 {
794 if (!a_menu->m_hMenu)
795 return FALSE;
796
797 if (!m_menuBarFrame)
798 return TRUE;
799
800 a_menu->m_savehMenu = a_menu->m_hMenu;
801 a_menu->m_hMenu = 0;
802
803 AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING, (UINT)a_menu->m_savehMenu, title);
804
805 DrawMenuBar((HWND) m_menuBarFrame->GetHWND());
806
807 return TRUE;
808 }
809
810 void wxMenuBar::Append (wxMenu * menu, const wxString& title)
811 {
812 if (!OnAppend(menu, title))
813 return;
814
815 m_menuCount ++;
816 wxMenu **new_menus = new wxMenu *[m_menuCount];
817 wxString *new_titles = new wxString[m_menuCount];
818 int i;
819
820 for (i = 0; i < m_menuCount - 1; i++)
821 {
822 new_menus[i] = m_menus[i];
823 m_menus[i] = NULL;
824 new_titles[i] = m_titles[i];
825 m_titles[i] = "";
826 }
827 if (m_menus)
828 {
829 delete[]m_menus;
830 delete[]m_titles;
831 }
832 m_menus = new_menus;
833 m_titles = new_titles;
834
835 m_menus[m_menuCount - 1] = (wxMenu *)menu;
836 m_titles[m_menuCount - 1] = title;
837
838 ((wxMenu *)menu)->m_menuBar = (wxMenuBar *) this;
839 ((wxMenu *)menu)->SetParent(this);
840 }
841
842 void wxMenuBar::Delete(wxMenu * menu, int i)
843 {
844 int j;
845 int ii = (int) i;
846
847 if (menu != 0) {
848 for (ii = 0; ii < m_menuCount; ii++) {
849 if (m_menus[ii] == menu)
850 break;
851 }
852 if (ii >= m_menuCount)
853 return;
854 } else {
855 if (ii < 0 || ii >= m_menuCount)
856 return;
857 menu = m_menus[ii];
858 }
859
860 if (!OnDelete(menu, ii))
861 return;
862
863 menu->SetParent(NULL);
864
865 -- m_menuCount;
866 for (j = ii; j < m_menuCount; j++) {
867 m_menus[j] = m_menus[j + 1];
868 m_titles[j] = m_titles[j + 1];
869 }
870 }
871
872 // Find the menu menuString, item itemString, and return the item id.
873 // Returns -1 if none found.
874 int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const
875 {
876 char buf1[200];
877 char buf2[200];
878 wxStripMenuCodes ((char *)(const char *)menuString, buf1);
879 int i;
880 for (i = 0; i < m_menuCount; i++)
881 {
882 wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2);
883 if (strcmp (buf1, buf2) == 0)
884 return m_menus[i]->FindItem (itemString);
885 }
886 return -1;
887 }
888
889 wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
890 {
891 if (itemMenu)
892 *itemMenu = NULL;
893
894 wxMenuItem *item = NULL;
895 int i;
896 for (i = 0; i < m_menuCount; i++)
897 {
898 item = m_menus[i]->FindItemForId (Id, itemMenu);
899 if (item)
900 return item;
901 }
902 return NULL;
903 }
904
905 void wxMenuBar::SetHelpString (int Id, const wxString& helpString)
906 {
907 int i;
908 for (i = 0; i < m_menuCount; i++)
909 {
910 if (m_menus[i]->FindItemForId (Id))
911 {
912 m_menus[i]->SetHelpString (Id, helpString);
913 return;
914 }
915 }
916 }
917
918 wxString wxMenuBar::GetHelpString (int Id) const
919 {
920 int i;
921 for (i = 0; i < m_menuCount; i++)
922 {
923 if (m_menus[i]->FindItemForId (Id))
924 return wxString(m_menus[i]->GetHelpString (Id));
925 }
926 return wxString("");
927 }
928
929 wxWindow *wxMenu::GetWindow() const
930 {
931 if ( m_pInvokingWindow != NULL )
932 return m_pInvokingWindow;
933 if ( m_menuBar != NULL)
934 return m_menuBar->m_menuBarFrame;
935 return NULL;
936 }
937
938 WXHMENU wxMenu::GetHMenu() const
939 {
940 if ( m_hMenu != 0 )
941 return m_hMenu;
942 else if ( m_savehMenu != 0 )
943 return m_savehMenu;
944
945 return 0;
946 }
947