]> git.saurik.com Git - wxWidgets.git/blame - src/msw/menu.cpp
Dialog Editor corrections for latest wxWin changes; removed wxProp files
[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;
3dd4e4e0
JS
76 m_clientData = (void*) NULL;
77
2bda0e17
KB
78 if (m_title != "")
79 {
b8d3a4f1 80 Append(idMenuTitle, m_title) ;
2bda0e17
KB
81 AppendSeparator() ;
82 }
83
84 Callback(func);
85}
86
87// The wxWindow destructor will take care of deleting the submenus.
b8d3a4f1 88wxMenu::~wxMenu()
2bda0e17
KB
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
b8d3a4f1 138void wxMenu::Break()
2bda0e17
KB
139{
140 m_doBreak = TRUE ;
141}
142
143// function appends a new item or submenu to the menu
144void wxMenu::Append(wxMenuItem *pItem)
145{
1311c7a9 146 wxCHECK_RET( pItem != NULL, "can't append NULL item to the menu" );
2bda0e17
KB
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 ) {
cfe780fb 165 wxASSERT( SubMenu->m_hMenu != (WXHMENU) NULL );
2bda0e17
KB
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;
2bda0e17 181
47d67540 182#if wxUSE_OWNER_DRAWN
2bda0e17
KB
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;
b8d3a4f1 193 pData = pItem->GetName();
2bda0e17
KB
194 }
195
b8d3a4f1
VZ
196 // visually select the menu title
197 if ( id == idMenuTitle )
198 {
199 // TODO use SetMenuItemInfo(MFS_DEFAULT) to put it in bold face
2bda0e17
KB
200 }
201
202 HMENU hMenu = (HMENU)((m_hMenu == 0) ? m_savehMenu : m_hMenu);
2bda0e17
KB
203 if ( !AppendMenu(hMenu, flags, id, pData) )
204 {
b8d3a4f1 205 wxLogLastError("AppendMenu");
2bda0e17
KB
206 }
207
208 m_noItems++;
209}
210
b8d3a4f1 211void wxMenu::AppendSeparator()
2bda0e17
KB
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;
2bda0e17
KB
234 int pos;
235 HMENU menu;
236
fd3f686c 237 wxMenuItem *item = NULL;
2bda0e17
KB
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);
1311c7a9 273 wxCHECK_RET( item != NULL, "can't enable non-existing menu item" );
2bda0e17
KB
274
275 item->Enable(Flag);
276}
277
278bool wxMenu::Enabled(int Id) const
279{
280 wxMenuItem *item = FindItemForId(Id);
1311c7a9 281 wxCHECK( item != NULL, FALSE );
2bda0e17
KB
282
283 return item->IsEnabled();
284}
285
286void wxMenu::Check(int Id, bool Flag)
287{
288 wxMenuItem *item = FindItemForId(Id);
1311c7a9 289 wxCHECK_RET( item != NULL, "can't get status of non-existing menu item" );
2bda0e17
KB
290
291 item->Check(Flag);
292}
293
294bool wxMenu::Checked(int Id) const
295{
296 wxMenuItem *item = FindItemForId(Id);
1311c7a9 297 wxCHECK( item != NULL, FALSE );
2bda0e17
KB
298
299 return item->IsChecked();
300}
301
302void wxMenu::SetTitle(const wxString& label)
303{
b8d3a4f1
VZ
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 {
fd3f686c
VZ
313 if ( !InsertMenu(hMenu, 0u, MF_BYPOSITION | MF_STRING,
314 (unsigned)idMenuTitle, m_title) ||
315 !InsertMenu(hMenu, 1u, MF_BYPOSITION, (unsigned)-1, NULL) )
b8d3a4f1
VZ
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
fd3f686c 335 if ( !ModifyMenu(hMenu, 0u,
b8d3a4f1 336 MF_BYPOSITION | MF_STRING,
fd3f686c 337 (unsigned)idMenuTitle, m_title) )
b8d3a4f1
VZ
338 {
339 wxLogLastError("ModifyMenu");
340 }
341 }
342 }
343
344 // TODO use SetMenuItemInfo(MFS_DEFAULT) to put it in bold face
2bda0e17
KB
345}
346
f7387de5 347const wxString wxMenu::GetTitle() const
2bda0e17
KB
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
47bc1060 392wxString wxMenu::GetLabel(int id) const
2bda0e17 393{
47bc1060 394/*
2bda0e17
KB
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) ;
47bc1060
JS
405
406*/
407 wxMenuItem *pItem = FindItemForId(id) ;
408 if (pItem)
409 return pItem->GetName() ;
410 else
411 return wxEmptyString;
2bda0e17
KB
412}
413
debe6624 414bool wxMenu::MSWCommand(WXUINT WXUNUSED(param), WXWORD id)
2bda0e17 415{
f5419957 416 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED);
2bda0e17
KB
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
debe6624 451wxMenuItem *wxMenu::FindItemForId(int itemId, wxMenu ** itemMenu) const
2bda0e17
KB
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
debe6624 479void wxMenu::SetHelpString(int itemId, const wxString& helpString)
2bda0e17
KB
480{
481 wxMenuItem *item = FindItemForId (itemId);
482 if (item)
483 item->SetHelp(helpString);
484}
485
debe6624 486wxString wxMenu::GetHelpString (int itemId) const
2bda0e17
KB
487{
488 wxMenuItem *item = FindItemForId (itemId);
489 wxString str("");
490 return (item == NULL) ? str : item->GetHelp();
491}
492
493void wxMenu::ProcessCommand(wxCommandEvent & event)
494{
495 bool processed = FALSE;
496
497 // Try a callback
498 if (m_callback)
499 {
b8d3a4f1 500 (void)(*(m_callback))(*this, event);
2bda0e17
KB
501 processed = TRUE;
502 }
503
504 // Try the menu's event handler
505 if ( !processed && GetEventHandler())
506 {
507 processed = GetEventHandler()->ProcessEvent(event);
508 }
509
510 // Try the window the menu was popped up from (and up
511 // through the hierarchy)
512 if ( !processed && GetInvokingWindow())
02800301 513 processed = GetInvokingWindow()->GetEventHandler()->ProcessEvent(event);
2bda0e17
KB
514}
515
516extern wxMenu *wxCurrentPopupMenu;
debe6624 517bool wxWindow::PopupMenu(wxMenu *menu, int x, int y)
2bda0e17
KB
518{
519 menu->SetInvokingWindow(this);
520
521 HWND hWnd = (HWND) GetHWND();
522 HMENU hMenu = (HMENU)menu->m_hMenu;
523 POINT point;
524 point.x = x;
525 point.y = y;
526 ::ClientToScreen(hWnd, &point);
527 wxCurrentPopupMenu = menu;
528 ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
529 wxYield();
530 wxCurrentPopupMenu = NULL;
531
532 menu->SetInvokingWindow(NULL);
533
534 return TRUE;
535}
536
537// Menu Bar
b8d3a4f1 538wxMenuBar::wxMenuBar()
2bda0e17
KB
539{
540 m_eventHandler = this;
541
542 m_menuCount = 0;
543 m_menus = NULL;
544 m_titles = NULL;
545 m_menuBarFrame = NULL;
546 m_hMenu = 0;
547}
548
debe6624 549wxMenuBar::wxMenuBar(int N, wxMenu *Menus[], const wxString Titles[])
2bda0e17
KB
550{
551 m_eventHandler = this;
552 m_menuCount = N;
553 m_menus = Menus;
554 m_titles = new wxString[N];
555 int i;
556 for ( i = 0; i < N; i++ )
557 m_titles[i] = Titles[i];
558 m_menuBarFrame = NULL;
559 for (i = 0; i < N; i++)
560 m_menus[i]->m_menuBar = (wxMenuBar *) this;
561
562 m_hMenu = 0;
563}
564
b8d3a4f1 565wxMenuBar::~wxMenuBar()
2bda0e17
KB
566{
567 // In fact, don't want menu to be destroyed before MDI
568 // shuffling has taken place. Let it be destroyed
569 // automatically when the window is destroyed.
570
571// DestroyMenu(menu);
572// m_hMenu = NULL;
573
574 int i;
575/*
576 // See remarks in ::~wxMenu() method
577 // BEWARE - this may interfere with MDI fixes, so
578 // may need to remove
579 int N = 0 ;
580
581 if (m_menuBarFrame && ((m_menuBarFrame->GetWindowStyleFlag() & wxSDI) == wxSDI))
582 {
583 if (menu)
584 N = GetMenuItemCount(menu) ;
585 for (i = N-1; i >= 0; i--)
586 RemoveMenu(menu, i, MF_BYPOSITION);
587 }
588*/
589 for (i = 0; i < m_menuCount; i++)
590 {
591 delete m_menus[i];
592 }
593 delete[] m_menus;
594 delete[] m_titles;
595
596/* Don't destroy menu here, in case we're MDI and
597 need to do some shuffling with VALID menu handles.
598 if (menu)
599 DestroyMenu(menu);
600 m_hMenu = 0;
601*/
602}
603
604// Must only be used AFTER menu has been attached to frame,
605// otherwise use individual menus to enable/disable items
debe6624 606void wxMenuBar::Enable(int Id, bool Flag)
2bda0e17
KB
607{
608 int ms_flag;
609 if (Flag)
610 ms_flag = MF_ENABLED;
611 else
612 ms_flag = MF_GRAYED;
613
614 wxMenu *itemMenu = NULL;
615 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
616 if (!item)
617 return;
618
619 if (itemMenu->m_hMenu)
620 EnableMenuItem((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND | ms_flag);
621 else if (itemMenu->m_savehMenu)
622 EnableMenuItem((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND | ms_flag);
623
624}
625
debe6624 626void wxMenuBar::EnableTop(int pos, bool flag)
2bda0e17
KB
627{
628 int ms_flag;
629 if (flag)
630 ms_flag = MF_ENABLED;
631 else
632 ms_flag = MF_GRAYED;
633
634 EnableMenuItem((HMENU)m_hMenu, pos, MF_BYPOSITION | ms_flag);
635 DrawMenuBar((HWND) m_menuBarFrame->GetHWND()) ;
636}
637
638// Must only be used AFTER menu has been attached to frame,
639// otherwise use individual menus
debe6624 640void wxMenuBar::Check(int Id, bool Flag)
2bda0e17
KB
641{
642 wxMenu *itemMenu = NULL;
643 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
644 if (!item)
645 return;
646
647 if (!item->IsCheckable())
648 return ;
649 int ms_flag;
650 if (Flag)
651 ms_flag = MF_CHECKED;
652 else
653 ms_flag = MF_UNCHECKED;
654
655 if (itemMenu->m_hMenu)
656 CheckMenuItem((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND | ms_flag);
657 else if (itemMenu->m_savehMenu)
658 CheckMenuItem((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND | ms_flag);
659
660// CheckMenuItem((HMENU)m_hMenu, Id, MF_BYCOMMAND | ms_flag);
661}
662
debe6624 663bool wxMenuBar::Checked(int Id) const
2bda0e17
KB
664{
665 wxMenu *itemMenu = NULL;
666 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
667 if (!item)
668 return FALSE;
669
fd3f686c 670 int Flag = 0;
2bda0e17
KB
671
672 if (itemMenu->m_hMenu)
673 Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ;
674 else if (itemMenu->m_savehMenu)
675 Flag=GetMenuState((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND) ;
676
677// Flag=GetMenuState((HMENU)m_hMenu, Id, MF_BYCOMMAND) ;
678
679 if (Flag&MF_CHECKED)
680 return TRUE ;
681 else
682 return FALSE ;
683}
684
debe6624 685bool wxMenuBar::Enabled(int Id) const
2bda0e17
KB
686{
687 wxMenu *itemMenu = NULL;
688 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
689 if (!item)
690 return FALSE;
691
692 int Flag ;
693
694 if (itemMenu->m_hMenu)
695 Flag=GetMenuState((HMENU)itemMenu->m_hMenu, Id, MF_BYCOMMAND) ;
696 else if (itemMenu->m_savehMenu)
697 Flag=GetMenuState((HMENU)itemMenu->m_savehMenu, Id, MF_BYCOMMAND) ;
698
699 if (Flag&MF_ENABLED)
700 return TRUE ;
701 else
702 return FALSE ;
703}
704
705
debe6624 706void wxMenuBar::SetLabel(int Id, const wxString& label)
2bda0e17
KB
707{
708 wxMenu *itemMenu = NULL;
709 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
710
711 if (!item)
712 return;
713
714 if (itemMenu->m_hMenu)
715 {
716 UINT was_flag = GetMenuState((HMENU)itemMenu->m_hMenu,Id,MF_BYCOMMAND) ;
717 ModifyMenu((HMENU)itemMenu->m_hMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
718 }
719 else if (itemMenu->m_savehMenu)
720 {
721 UINT was_flag = GetMenuState((HMENU)itemMenu->m_savehMenu,Id,MF_BYCOMMAND) ;
722 ModifyMenu((HMENU)itemMenu->m_savehMenu,Id,MF_BYCOMMAND|MF_STRING|was_flag,Id,(const char *)label) ;
723 }
724}
725
debe6624 726wxString wxMenuBar::GetLabel(int Id) const
2bda0e17
KB
727{
728 wxMenu *itemMenu = NULL;
729 wxMenuItem *item = FindItemForId(Id, &itemMenu) ;
730
731 if (!item)
732 return wxString("");
733
734 static char tmp[128] ;
735 int len = 0;
736 if (itemMenu->m_hMenu)
737 {
738 len = GetMenuString((HMENU)itemMenu->m_hMenu,Id,tmp,127,MF_BYCOMMAND) ;
739 }
740 else if (itemMenu->m_savehMenu)
741 {
742 len = GetMenuString((HMENU)itemMenu->m_savehMenu,Id,tmp,127,MF_BYCOMMAND) ;
743 }
744
745// int len = GetMenuString((HMENU)m_hMenu,Id,tmp,127,MF_BYCOMMAND) ;
746 tmp[len] = '\0' ;
747 return wxString(tmp) ;
748}
749
debe6624 750void wxMenuBar::SetLabelTop(int pos, const wxString& label)
2bda0e17
KB
751{
752 UINT was_flag = GetMenuState((HMENU)m_hMenu,pos,MF_BYPOSITION) ;
753 if (was_flag&MF_POPUP)
754 {
755 was_flag &= 0xff ;
756 HMENU popup = GetSubMenu((HMENU)m_hMenu,pos) ;
757 ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,(UINT)popup,(const char *)label) ;
758 }
759 else
760 ModifyMenu((HMENU)m_hMenu,pos,MF_BYPOSITION|MF_STRING|was_flag,pos,(const char *)label) ;
761}
762
debe6624 763wxString wxMenuBar::GetLabelTop(int pos) const
2bda0e17
KB
764{
765 static char tmp[128] ;
766 int len = GetMenuString((HMENU)m_hMenu,pos,tmp,127,MF_BYPOSITION) ;
767 tmp[len] = '\0' ;
768 return wxString(tmp);
769}
770
debe6624 771bool wxMenuBar::OnDelete(wxMenu *a_menu, int pos)
2bda0e17
KB
772{
773 if (!m_menuBarFrame)
774 return TRUE;
775
776 if (RemoveMenu((HMENU)m_hMenu, (UINT)pos, MF_BYPOSITION)) {
777 m_menus[pos]->m_hMenu = m_menus[pos]->m_savehMenu;
778 m_menus[pos]->m_savehMenu = 0;
779
780 if (m_menuBarFrame) {
781 DrawMenuBar((HWND) m_menuBarFrame->GetHWND()) ;
782 }
783
784 return TRUE;
785 }
786
787 return FALSE;
788}
789
790bool wxMenuBar::OnAppend(wxMenu *a_menu, const char *title)
791{
792 if (!a_menu->m_hMenu)
793 return FALSE;
794
795 if (!m_menuBarFrame)
796 return TRUE;
797
798 a_menu->m_savehMenu = a_menu->m_hMenu;
799 a_menu->m_hMenu = 0;
800
801 AppendMenu((HMENU)m_hMenu, MF_POPUP | MF_STRING, (UINT)a_menu->m_savehMenu, title);
802
803 DrawMenuBar((HWND) m_menuBarFrame->GetHWND());
804
805 return TRUE;
806}
807
808void wxMenuBar::Append (wxMenu * menu, const wxString& title)
809{
810 if (!OnAppend(menu, title))
811 return;
812
813 m_menuCount ++;
814 wxMenu **new_menus = new wxMenu *[m_menuCount];
815 wxString *new_titles = new wxString[m_menuCount];
816 int i;
817
818 for (i = 0; i < m_menuCount - 1; i++)
819 {
820 new_menus[i] = m_menus[i];
821 m_menus[i] = NULL;
822 new_titles[i] = m_titles[i];
823 m_titles[i] = "";
824 }
825 if (m_menus)
826 {
827 delete[]m_menus;
828 delete[]m_titles;
829 }
830 m_menus = new_menus;
831 m_titles = new_titles;
832
833 m_menus[m_menuCount - 1] = (wxMenu *)menu;
834 m_titles[m_menuCount - 1] = title;
835
836 ((wxMenu *)menu)->m_menuBar = (wxMenuBar *) this;
837 ((wxMenu *)menu)->SetParent(this);
838}
839
debe6624 840void wxMenuBar::Delete(wxMenu * menu, int i)
2bda0e17
KB
841{
842 int j;
843 int ii = (int) i;
844
845 if (menu != 0) {
846 for (ii = 0; ii < m_menuCount; ii++) {
847 if (m_menus[ii] == menu)
848 break;
849 }
850 if (ii >= m_menuCount)
851 return;
852 } else {
853 if (ii < 0 || ii >= m_menuCount)
854 return;
855 menu = m_menus[ii];
856 }
857
858 if (!OnDelete(menu, ii))
859 return;
860
861 menu->SetParent(NULL);
862
863 -- m_menuCount;
864 for (j = ii; j < m_menuCount; j++) {
865 m_menus[j] = m_menus[j + 1];
866 m_titles[j] = m_titles[j + 1];
867 }
868}
869
870// Find the menu menuString, item itemString, and return the item id.
871// Returns -1 if none found.
872int wxMenuBar::FindMenuItem (const wxString& menuString, const wxString& itemString) const
873{
874 char buf1[200];
875 char buf2[200];
876 wxStripMenuCodes ((char *)(const char *)menuString, buf1);
877 int i;
878 for (i = 0; i < m_menuCount; i++)
879 {
880 wxStripMenuCodes ((char *)(const char *)m_titles[i], buf2);
881 if (strcmp (buf1, buf2) == 0)
882 return m_menus[i]->FindItem (itemString);
883 }
884 return -1;
885}
886
debe6624 887wxMenuItem *wxMenuBar::FindItemForId (int Id, wxMenu ** itemMenu) const
2bda0e17
KB
888{
889 if (itemMenu)
890 *itemMenu = NULL;
891
892 wxMenuItem *item = NULL;
893 int i;
894 for (i = 0; i < m_menuCount; i++)
fd3f686c
VZ
895 {
896 item = m_menus[i]->FindItemForId (Id, itemMenu);
897 if (item)
2bda0e17 898 return item;
fd3f686c 899 }
2bda0e17
KB
900 return NULL;
901}
902
debe6624 903void wxMenuBar::SetHelpString (int Id, const wxString& helpString)
2bda0e17
KB
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
debe6624 916wxString wxMenuBar::GetHelpString (int Id) const
2bda0e17
KB
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
927wxWindow *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
936WXHMENU 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