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