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