]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/menu.cpp
libjpeg not used by default (it didn't even link)
[wxWidgets.git] / src / msw / menu.cpp
... / ...
CommitLineData
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
47static 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)
64wxMenu::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.
88wxMenu::~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
138void wxMenu::Break()
139{
140 m_doBreak = TRUE ;
141}
142
143// function appends a new item or submenu to the menu
144void 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
211void wxMenu::AppendSeparator()
212{
213 Append(new wxMenuItem(this, ID_SEPARATOR));
214}
215
216// Pullright item
217void 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
224void 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
231void 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
270void 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
278bool wxMenu::Enabled(int Id) const
279{
280 wxMenuItem *item = FindItemForId(Id);
281 wxCHECK( item != NULL, FALSE );
282
283 return item->IsEnabled();
284}
285
286void 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
294bool wxMenu::Checked(int Id) const
295{
296 wxMenuItem *item = FindItemForId(Id);
297 wxCHECK( item != NULL, FALSE );
298
299 return item->IsChecked();
300}
301
302void 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
347const wxString wxMenu::GetTitle() const
348{
349 return m_title;
350}
351
352void 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
392wxString 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
414bool 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.
425int 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
451wxMenuItem *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
479void wxMenu::SetHelpString(int itemId, const wxString& helpString)
480{
481 wxMenuItem *item = FindItemForId (itemId);
482 if (item)
483 item->SetHelp(helpString);
484}
485
486wxString 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
495void 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
518extern wxMenu *wxCurrentPopupMenu;
519bool 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
540wxMenuBar::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
551wxMenuBar::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
567wxMenuBar::~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
608void 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
628void 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
642void 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
665bool 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
687bool 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
708void 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
728wxString 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
752void 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
765wxString 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
773bool 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
792bool 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
810void 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
842void 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.
874int 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
889wxMenuItem *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
905void 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
918wxString 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
929wxWindow *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
938WXHMENU 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