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