Merge in from trunk r67662 to r64801
[wxWidgets.git] / src / os2 / menuitem.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/os2/menuitem.cpp
3 // Purpose: wxMenuItem implementation
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/10/98
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // headers & declarations
14 // ============================================================================
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #include "wx/menuitem.h"
20 #include "wx/stockitem.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/font.h"
24 #include "wx/bitmap.h"
25 #include "wx/settings.h"
26 #include "wx/window.h"
27 #include "wx/accel.h"
28 #include "wx/menu.h"
29 #include "wx/string.h"
30 #include "wx/log.h"
31 #endif
32
33 #if wxUSE_ACCEL
34 #include "wx/accel.h"
35 #endif // wxUSE_ACCEL
36
37 #include "wx/os2/private.h"
38
39 // ---------------------------------------------------------------------------
40 // macro
41 // ---------------------------------------------------------------------------
42
43 // hide the ugly cast
44 #define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
45
46 // conditional compilation
47 #if wxUSE_OWNER_DRAWN
48 #define OWNER_DRAWN_ONLY( code ) if ( IsOwnerDrawn() ) code
49 #else // !wxUSE_OWNER_DRAWN
50 #define OWNER_DRAWN_ONLY( code )
51 #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
52
53 // ============================================================================
54 // implementation
55 // ============================================================================
56
57 // ----------------------------------------------------------------------------
58 // dynamic classes implementation
59 // ----------------------------------------------------------------------------
60
61 // ----------------------------------------------------------------------------
62 // wxMenuItem
63 // ----------------------------------------------------------------------------
64
65 // ctor & dtor
66 // -----------
67
68 wxMenuItem::wxMenuItem(
69 wxMenu* pParentMenu
70 , int nId
71 , const wxString& rsText
72 , const wxString& rsHelp
73 , wxItemKind eKind
74 , wxMenu* pSubMenu
75 )
76 : wxMenuItemBase( pParentMenu
77 ,nId
78 ,wxPMTextToLabel(rsText)
79 ,rsHelp
80 ,eKind
81 ,pSubMenu
82 )
83 {
84 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
85 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
86 m_vMenuData.id = (USHORT)nId;
87
88 Init();
89 } // end of wxMenuItem::wxMenuItem
90
91 wxMenuItem::wxMenuItem(
92 wxMenu* pParentMenu
93 , int nId
94 , const wxString& rsText
95 , const wxString& rsHelp
96 , bool bIsCheckable
97 , wxMenu* pSubMenu
98 )
99 : wxMenuItemBase( pParentMenu
100 ,nId
101 ,wxPMTextToLabel(rsText)
102 ,rsHelp
103 ,bIsCheckable ? wxITEM_CHECK : wxITEM_NORMAL
104 ,pSubMenu
105 )
106 {
107 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
108 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
109 m_vMenuData.id = (USHORT)nId;
110
111 Init();
112 } // end of wxMenuItem::wxMenuItem
113
114 void wxMenuItem::Init()
115 {
116 m_vRadioGroup.m_nStart = -1;
117 m_bIsRadioGroupStart = FALSE;
118
119 #if wxUSE_OWNER_DRAWN
120 //
121 // Set default menu colors
122 //
123 SetTextColour(wxNullColour);
124 SetBackgroundColour(wxNullColour);
125
126 //
127 // We don't want normal items be owner-drawn
128 //
129 SetOwnerDrawn(false);
130 #endif // wxUSE_OWNER_DRAWN
131 } // end of wxMenuItem::Init
132
133 wxMenuItem::~wxMenuItem()
134 {
135 } // end of wxMenuItem::~wxMenuItem
136
137 //
138 // Misc
139 // ----
140
141 //
142 // Return the id for calling Win32 API functions
143 //
144 int wxMenuItem::GetRealId() const
145 {
146 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
147 } // end of wxMenuItem::GetRealId
148
149 //
150 // Get item state
151 // --------------
152 bool wxMenuItem::IsChecked() const
153 {
154 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
155 ,MM_QUERYITEMATTR
156 ,MPFROM2SHORT(GetId(), TRUE)
157 ,MPFROMSHORT(MIA_CHECKED)
158 ));
159
160 return (uFlag & MIA_CHECKED) == MIA_CHECKED ;
161 } // end of wxMenuItem::IsChecked
162
163 wxString wxMenuItemBase::GetLabelText(
164 const wxString& rsText
165 )
166 {
167 wxString sLabel;
168
169 for (const wxChar* zPc = rsText.c_str(); *zPc; zPc++)
170 {
171 if (*zPc == wxT('~') || *zPc == wxT('&'))
172 {
173 //
174 // '~' is the escape character for OS/2PM and '&' is the one for
175 // wxWidgets - skip both of them
176 //
177 continue;
178 }
179 sLabel += *zPc;
180 }
181 return sLabel;
182 } // end of wxMenuItemBase::GetLabelText
183
184 //
185 // Radio group stuff
186 // -----------------
187 //
188 void wxMenuItem::SetAsRadioGroupStart()
189 {
190 m_bIsRadioGroupStart = true;
191 } // end of wxMenuItem::SetAsRadioGroupStart
192
193 void wxMenuItem::SetRadioGroupStart(
194 int nStart
195 )
196 {
197 wxASSERT_MSG( !m_bIsRadioGroupStart
198 ,wxT("should only be called for the next radio items")
199 );
200
201 m_vRadioGroup.m_nStart = nStart;
202 } // wxMenuItem::SetRadioGroupStart
203
204 void wxMenuItem::SetRadioGroupEnd(
205 int nEnd
206 )
207 {
208 wxASSERT_MSG( m_bIsRadioGroupStart
209 ,wxT("should only be called for the first radio item")
210 );
211 m_vRadioGroup.m_nEnd = nEnd;
212 } // end of wxMenuItem::SetRadioGroupEnd
213
214 // change item state
215 // -----------------
216
217 void wxMenuItem::Enable(
218 bool bEnable
219 )
220 {
221 bool bOk;
222
223 if (m_isEnabled == bEnable)
224 return;
225 if (bEnable)
226 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
227 ,MM_SETITEMATTR
228 ,MPFROM2SHORT(GetRealId(), TRUE)
229 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
230 );
231 else
232 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
233 ,MM_SETITEMATTR
234 ,MPFROM2SHORT(GetRealId(), TRUE)
235 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
236 );
237 if (!bOk)
238 {
239 wxLogLastError(wxT("EnableMenuItem"));
240 }
241 wxMenuItemBase::Enable(bEnable);
242 } // end of wxMenuItem::Enable
243
244 void wxMenuItem::Check(
245 bool bCheck
246 )
247 {
248 bool bOk;
249
250 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
251 if (m_isChecked == bCheck)
252 return;
253
254 HMENU hMenu = GetHmenuOf(m_parentMenu);
255
256 if (GetKind() == wxITEM_RADIO)
257 {
258 //
259 // It doesn't make sense to uncheck a radio item - what would this do?
260 //
261 if (!bCheck)
262 return;
263
264 //
265 // Get the index of this item in the menu
266 //
267 const wxMenuItemList& rItems = m_parentMenu->GetMenuItems();
268 int nPos = rItems.IndexOf(this);
269
270 wxCHECK_RET( nPos != wxNOT_FOUND
271 ,wxT("menuitem not found in the menu items list?")
272 );
273
274 //
275 // Get the radio group range
276 //
277 int nStart;
278 int nEnd;
279
280 if (m_bIsRadioGroupStart)
281 {
282 //
283 // We already have all information we need
284 //
285 nStart = nPos;
286 nEnd = m_vRadioGroup.m_nEnd;
287 }
288 else // next radio group item
289 {
290 //
291 // Get the radio group end from the start item
292 //
293 nStart = m_vRadioGroup.m_nStart;
294 nEnd = rItems.Item(nStart)->GetData()->m_vRadioGroup.m_nEnd;
295 }
296
297 //
298 // Also uncheck all the other items in this radio group
299 //
300 wxMenuItemList::compatibility_iterator node = rItems.Item(nStart);
301
302 for (int n = nStart; n <= nEnd && node; n++)
303 {
304 if (n == nPos)
305 {
306 ::WinSendMsg( hMenu
307 ,MM_SETITEMATTR
308 ,MPFROM2SHORT(n, TRUE)
309 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
310 );
311 }
312 if (n != nPos)
313 {
314 node->GetData()->m_isChecked = FALSE;
315 ::WinSendMsg( hMenu
316 ,MM_SETITEMATTR
317 ,MPFROM2SHORT(n, TRUE)
318 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
319 );
320 }
321 node = node->GetNext();
322 }
323 }
324 else // check item
325 {
326 if (bCheck)
327 bOk = (bool)::WinSendMsg( hMenu
328 ,MM_SETITEMATTR
329 ,MPFROM2SHORT(GetRealId(), TRUE)
330 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
331 );
332 else
333 bOk = (bool)::WinSendMsg( hMenu
334 ,MM_SETITEMATTR
335 ,MPFROM2SHORT(GetRealId(), TRUE)
336 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
337 );
338 }
339 if (!bOk)
340 {
341 wxLogLastError(wxT("CheckMenuItem"));
342 }
343 wxMenuItemBase::Check(bCheck);
344 } // end of wxMenuItem::Check
345
346 void wxMenuItem::SetItemLabel( const wxString& rText )
347 {
348 //
349 // Don't do anything if label didn't change
350 //
351
352 wxString sText = wxPMTextToLabel(rText);
353 if (m_text == sText)
354 return;
355
356 // wxMenuItemBase will do stock ID checks
357 wxMenuItemBase::SetItemLabel(sText);
358
359 HWND hMenu = GetHmenuOf(m_parentMenu);
360
361 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
362
363 #if wxUSE_ACCEL
364 m_parentMenu->UpdateAccel(this);
365 #endif // wxUSE_ACCEL
366
367 USHORT uId = (USHORT)GetRealId();
368 MENUITEM vItem;
369 USHORT uFlagsOld;
370
371 if (!::WinSendMsg( hMenu
372 ,MM_QUERYITEM
373 ,MPFROM2SHORT(uId, TRUE)
374 ,(MPARAM)&vItem
375 ))
376 {
377 wxLogLastError(wxT("GetMenuState"));
378 }
379 else
380 {
381 uFlagsOld = vItem.afStyle;
382 if (IsSubMenu())
383 {
384 uFlagsOld |= MIS_SUBMENU;
385 }
386
387 char* pData;
388
389 #if wxUSE_OWNER_DRAWN
390 if (IsOwnerDrawn())
391 {
392 uFlagsOld |= MIS_OWNERDRAW;
393 pData = (char*)this;
394 }
395 else
396 #endif //owner drawn
397 {
398 uFlagsOld |= MIS_TEXT;
399 pData = (char*) m_text.wx_str();
400 }
401
402 //
403 // Set the style
404 //
405 if (!::WinSendMsg( hMenu
406 ,MM_SETITEM
407 ,MPFROM2SHORT(uId, TRUE)
408 ,(MPARAM)&vItem
409 ))
410 {
411 wxLogLastError(wxT("ModifyMenu"));
412 }
413
414 //
415 // Set the text
416 //
417 if (::WinSendMsg( hMenu
418 ,MM_SETITEMTEXT
419 ,MPFROMSHORT(uId)
420 ,(MPARAM)pData
421 ))
422 {
423 wxLogLastError(wxT("ModifyMenu"));
424 }
425 }
426 } // end of wxMenuItem::SetText
427
428 #if wxUSE_OWNER_DRAWN
429
430 wxString wxMenuItem::GetName() const
431 {
432 return GetItemLabelText();
433 }
434
435 bool wxMenuItem::OnMeasureItem( size_t* pWidth, size_t* pHeight )
436 {
437 wxMemoryDC vDC;
438
439 wxString sStr = GetName();
440
441 //
442 // If we have a valid accel string, then pad out
443 // the menu string so that the menu and accel string are not
444 // placed on top of each other.
445 wxString accel = GetItemLabel().AfterFirst(wxT('\t'));
446 if (!accel.empty() )
447 {
448 sStr.Pad(sStr.length()%8);
449 sStr += accel;
450 }
451 vDC.SetFont(GetFont());
452 vDC.GetTextExtent( sStr
453 ,(wxCoord *)pWidth
454 ,(wxCoord *)pHeight
455 );
456 if (!accel.empty())
457 {
458 //
459 // Measure the accelerator string, and add its width to
460 // the total item width, plus 16 (Accelerators are right justified,
461 // with the right edge of the text rectangle 16 pixels left of
462 // the right edge of the menu)
463 //
464 int nAccelWidth;
465 int nAccelHeight;
466
467 vDC.GetTextExtent( m_strAccel
468 ,&nAccelWidth
469 ,&nAccelHeight
470 );
471 *pWidth += nAccelWidth;
472 }
473
474 //
475 // Add space at the end of the menu for the submenu expansion arrow.
476 // This will also allow offsetting the accel string from the right edge
477 //
478 *pWidth = (size_t)(*pWidth + GetDefaultMarginWidth() * 1.5);
479
480 //
481 // JACS: items still look too tightly packed, so adding 5 pixels.
482 //
483 (*pHeight) += 5;
484
485 //
486 // Ray Gilbert's changes - Corrects the problem of a BMP
487 // being placed next to text in a menu item, and the BMP does
488 // not match the size expected by the system. This will
489 // resize the space so the BMP will fit. Without this, BMPs
490 // must be no larger or smaller than 16x16.
491 //
492 if (m_bmpChecked.IsOk())
493 {
494 //
495 // Is BMP height larger than text height?
496 //
497 size_t nAdjustedHeight = m_bmpChecked.GetHeight() +
498 wxSystemSettings::GetMetric(wxSYS_EDGE_Y);
499 if (*pHeight < nAdjustedHeight)
500 *pHeight = nAdjustedHeight;
501
502 //
503 // Does BMP encroach on default check menu position?
504 //
505 size_t nAdjustedWidth = m_bmpChecked.GetWidth() +
506 (wxSystemSettings::GetMetric(wxSYS_EDGE_X) * 2);
507
508 //
509 // Do we need to widen margin to fit BMP?
510 //
511 if ((size_t)GetMarginWidth() < nAdjustedWidth)
512 SetMarginWidth(nAdjustedWidth);
513
514 //
515 // Add the size of the bitmap to our total size...
516 //
517 *pWidth += GetMarginWidth();
518 }
519
520 //
521 // Add the size of the bitmap to our total size - even if we don't have
522 // a bitmap we leave room for one...
523 //
524 *pWidth += GetMarginWidth();
525
526 //
527 // Make sure that this item is at least as
528 // tall as the user's system settings specify
529 //
530 const size_t heightStd = 6; // FIXME: get value from the system
531 if ( *pHeight < heightStd )
532 *pHeight = heightStd;
533 m_nHeight = *pHeight; // remember height for use in OnDrawItem
534 return true;
535 } // end of wxOwnerDrawn::OnMeasureItem
536
537 bool wxMenuItem::OnDrawItem( wxDC& rDC,
538 const wxRect& rRect,
539 wxODAction eAction,
540 wxODStatus eStatus )
541 {
542
543 //
544 // Select the font and draw the text
545 // ---------------------------------
546 //
547
548 CHARBUNDLE vCbnd;
549 wxPMDCImpl *impl = (wxPMDCImpl*) rDC.GetImpl();
550 HPS hPS= impl->GetHPS();
551 wxFont vFont;
552 wxColour vColBack;
553 wxColour vColText;
554 COLORREF vRef;
555 RECTL vRect = {rRect.x + 4, rRect.y + 1, rRect.x + (rRect.width - 2), rRect.y + rRect.height};
556
557 memset(&vCbnd, 0, sizeof(CHARBUNDLE));
558
559 GetFontToUse(vFont);
560 GetColourToUse(eStatus, vColText, vColBack);
561
562 rDC.SetFont(vFont);
563 rDC.SetTextBackground(vColBack);
564 rDC.SetTextForeground(vColText);
565 rDC.SetBackgroundMode(wxTRANSPARENT);
566
567 vCbnd.lColor = vColText.GetPixel();
568 vCbnd.lBackColor = vColBack.GetPixel();
569 ::GpiSetAttrs( hPS
570 ,PRIM_CHAR
571 ,CBB_BACK_COLOR | CBB_COLOR
572 ,0
573 ,&vCbnd
574 );
575 ::GpiSetBackMix( hPS
576 ,BM_LEAVEALONE
577 );
578
579 //
580 // Paint the background
581 //
582 ::WinFillRect(hPS, &vRect, vColBack.GetPixel());
583
584 //
585 // Determine where to draw and leave space for a check-mark.
586 //
587 int nX = rRect.x + GetMarginWidth();
588
589 //
590 // Unfortunately, unlike Win32, PM has no owner drawn specific text
591 // drawing methods like ::DrawState that can cleanly handle accel
592 // mnemonics and deal, automatically, with various states, so we have
593 // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn
594 // strings either. We cannot handle mnemonics either. We display
595 // them, though, in the hope we can figure them out some day.
596 //
597
598 //
599 // Display main text and accel text separately to align better
600 //
601 wxString sTgt = wxT("\t");
602 wxString sFullString = GetItemLabel(); // need to save the original text
603 wxString sAccel;
604 int nIndex;
605 size_t nWidth;
606 size_t nCharWidth;
607 size_t nHeight;
608 bool bFoundMnemonic = false;
609 bool bFoundAccel = false;
610
611 //
612 // Deal with the tab, extracting the Accel text
613 //
614 nIndex = sFullString.Find(sTgt);
615 if (nIndex != -1)
616 {
617 bFoundAccel = true;
618 sAccel = sFullString.Mid(nIndex + 1);
619 sFullString.Remove(nIndex);
620 }
621
622 //
623 // Deal with the mnemonic character
624 //
625 sTgt = wxT("~");
626 nIndex = sFullString.Find(sTgt);
627 if (nIndex != -1)
628 {
629 wxString sTmp = sFullString;
630
631 bFoundMnemonic = true;
632 sTmp.Remove(nIndex);
633 rDC.GetTextExtent( sTmp
634 ,(wxCoord *)&nWidth
635 ,(wxCoord *)&nHeight
636 );
637 sTmp = sFullString[(size_t)(nIndex + 1)];
638 rDC.GetTextExtent( sTmp
639 ,(wxCoord *)&nCharWidth
640 ,(wxCoord *)&nHeight
641 );
642 sFullString.Replace(sTgt.c_str(), wxEmptyString, true);
643 }
644
645 //
646 // Draw the main item text sans the accel text
647 //
648 POINTL vPntStart = {nX, rRect.y + 4};
649 ::GpiCharStringAt( impl->GetHPS()
650 ,&vPntStart
651 ,sFullString.length()
652 ,sFullString.char_str()
653 );
654 if (bFoundMnemonic)
655 {
656 //
657 // Underline the mnemonic -- still won't work, but at least it "looks" right
658 //
659 wxPen vPen;
660 POINTL vPntEnd = {nX + nWidth + nCharWidth - 3, rRect.y + 2}; //CharWidth is bit wide
661
662 vPntStart.x = nX + nWidth - 1;
663 vPntStart.y = rRect.y + 2; // Make it look pretty!
664 vPen = wxPen(vColText, 1, wxSOLID); // Assuming we are always black
665 rDC.SetPen(vPen);
666 ::GpiMove(hPS, &vPntStart);
667 ::GpiLine(hPS, &vPntEnd);
668 }
669
670 //
671 // Now draw the accel text
672 //
673 if (bFoundAccel)
674 {
675 size_t nWidth;
676 size_t nHeight;
677
678 rDC.GetTextExtent( sAccel
679 ,(wxCoord *)&nWidth
680 ,(wxCoord *)&nHeight
681 );
682 //
683 // Back off the starting position from the right edge
684 //
685 vPntStart.x = rRect.width - (nWidth + 7);
686 vPntStart.y = rRect.y + 4;
687 ::GpiCharStringAt( impl->GetHPS()
688 ,&vPntStart
689 ,sAccel.length()
690 ,sAccel.char_str()
691 );
692 }
693
694 //
695 // Draw the bitmap
696 // ---------------
697 //
698 if (IsCheckable() && !m_bmpChecked.IsOk())
699 {
700 if (eStatus & wxODChecked)
701 {
702 RECTL vRect;
703 HBITMAP hBmpCheck = ::WinGetSysBitmap(HWND_DESKTOP, SBMP_MENUCHECK);
704
705 vRect.xLeft = rRect.x;
706 vRect.xRight = rRect.x + GetMarginWidth();
707 vRect.yBottom = rRect.y;
708 vRect.yTop = rRect.y + m_nHeight - 3;
709
710 ::WinDrawBitmap( hPS // PS for this menuitem
711 ,hBmpCheck // system checkmark
712 ,NULL // draw the whole bitmap
713 ,(PPOINTL)&vRect // destination -- bottom left corner of the menuitem area
714 ,0L // ignored
715 ,0L // draw a bitmap
716 ,DBM_NORMAL // draw normal size
717 );
718 }
719 }
720 else
721 {
722 //
723 // For uncheckable item we use only the 'checked' bitmap
724 //
725 wxBitmap vBmp(GetBitmap(IsCheckable() ? ((eStatus & wxODChecked) != 0) : TRUE));
726
727 if (vBmp.IsOk())
728 {
729
730 wxMemoryDC vDCMem(&rDC);
731 wxMemoryDC* pOldDC = (wxMemoryDC*)vBmp.GetSelectedInto();
732
733 if(pOldDC != NULL)
734 {
735 vBmp.SetSelectedInto(NULL);
736 }
737 vDCMem.SelectObject(vBmp);
738
739 //
740 // Center bitmap
741 //
742 int nBmpWidth = vBmp.GetWidth();
743 int nBmpHeight = vBmp.GetHeight();
744
745 //
746 // There should be enough space!
747 //
748 wxASSERT((nBmpWidth <= rRect.width) && (nBmpHeight <= rRect.height));
749
750 int nHeightDiff = m_nHeight - nBmpHeight;
751
752 rDC.Blit( rRect.x + (GetMarginWidth() - nBmpWidth) / 2
753 ,rRect.y + nHeightDiff / 2
754 ,nBmpWidth
755 ,nBmpHeight
756 ,&vDCMem
757 ,0
758 ,0
759 ,wxCOPY
760 ,true
761 );
762
763 if (eStatus & wxODSelected)
764 {
765 POINTL vPnt1 = {rRect.x + 1, rRect.y + 3}; // Leave a little background border
766 POINTL vPnt2 = {rRect.x + GetMarginWidth(), rRect.y + m_nHeight - 3};
767
768 LINEBUNDLE vLine;
769
770 vLine.lColor = vColBack.GetPixel();
771 ::GpiSetAttrs( hPS
772 ,PRIM_LINE
773 ,LBB_COLOR
774 ,0
775 ,&vLine
776 );
777 ::GpiMove(hPS, &vPnt1);
778 ::GpiBox( hPS
779 ,DRO_OUTLINE
780 ,&vPnt2
781 ,0L
782 ,0L
783 );
784 }
785 vBmp.SetSelectedInto(NULL);
786 }
787 }
788 return true;
789 } // end of wxOwnerDrawn::OnDrawItem
790
791 #endif // wxUSE_OWNER_DRAWN
792
793 // ----------------------------------------------------------------------------
794 // wxMenuItemBase
795 // ----------------------------------------------------------------------------
796
797 wxMenuItem* wxMenuItemBase::New(
798 wxMenu* pParentMenu
799 , int nId
800 , const wxString& rName
801 , const wxString& rHelp
802 , wxItemKind kind
803 , wxMenu* pSubMenu
804 )
805 {
806 return new wxMenuItem( pParentMenu
807 ,nId
808 ,rName
809 ,rHelp
810 ,kind
811 ,pSubMenu
812 );
813 } // end of wxMenuItemBase::New