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