]> git.saurik.com Git - wxWidgets.git/blame - src/os2/menuitem.cpp
Add virtual ~wxAnyScrollHelperBase() to fix compiler warning.
[wxWidgets.git] / src / os2 / menuitem.cpp
CommitLineData
0e320a79 1///////////////////////////////////////////////////////////////////////////////
e4db172a 2// Name: src/os2/menuitem.cpp
0e320a79 3// Purpose: wxMenuItem implementation
75f11ad7
DW
4// Author: David Webster
5// Modified by:
6// Created: 10/10/98
75f11ad7 7// Copyright: (c) David Webster
65571936 8// Licence: wxWindows licence
0e320a79
DW
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// headers & declarations
13// ============================================================================
14
75f11ad7
DW
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
e4db172a 18#include "wx/menuitem.h"
ee0a94cf 19#include "wx/stockitem.h"
e4db172a 20
75f11ad7
DW
21#ifndef WX_PRECOMP
22 #include "wx/font.h"
23 #include "wx/bitmap.h"
24 #include "wx/settings.h"
75f11ad7
DW
25 #include "wx/window.h"
26 #include "wx/accel.h"
27 #include "wx/menu.h"
28 #include "wx/string.h"
e4db172a 29 #include "wx/log.h"
75f11ad7
DW
30#endif
31
c5fb56c0
DW
32#if wxUSE_ACCEL
33 #include "wx/accel.h"
34#endif // wxUSE_ACCEL
35
75f11ad7
DW
36#include "wx/os2/private.h"
37
38// ---------------------------------------------------------------------------
c5fb56c0 39// macro
75f11ad7
DW
40// ---------------------------------------------------------------------------
41
c5fb56c0 42// hide the ugly cast
75f11ad7 43#define GetHMenuOf(menu) ((HMENU)menu->GetHMenu())
0e320a79 44
c5fb56c0
DW
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
0e320a79
DW
52// ============================================================================
53// implementation
54// ============================================================================
55
56// ----------------------------------------------------------------------------
57// dynamic classes implementation
58// ----------------------------------------------------------------------------
59
0e320a79
DW
60// ----------------------------------------------------------------------------
61// wxMenuItem
62// ----------------------------------------------------------------------------
63
64// ctor & dtor
65// -----------
66
22e90769
DW
67wxMenuItem::wxMenuItem(
68 wxMenu* pParentMenu
69, int nId
ab4fece8
DW
70, const wxString& rsText
71, const wxString& rsHelp
72, wxItemKind eKind
22e90769
DW
73, wxMenu* pSubMenu
74)
ab4fece8
DW
75: wxMenuItemBase( pParentMenu
76 ,nId
3a7c1253 77 ,wxPMTextToLabel(rsText)
ab4fece8
DW
78 ,rsHelp
79 ,eKind
80 ,pSubMenu
81 )
0e320a79 82{
22e90769 83 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
8635b0db
DW
84 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
85 m_vMenuData.id = (USHORT)nId;
75f11ad7 86
f95255e2
DW
87 Init();
88} // end of wxMenuItem::wxMenuItem
89
90wxMenuItem::wxMenuItem(
91 wxMenu* pParentMenu
92, int nId
ab4fece8
DW
93, const wxString& rsText
94, const wxString& rsHelp
f95255e2
DW
95, bool bIsCheckable
96, wxMenu* pSubMenu
97)
ab4fece8
DW
98: wxMenuItemBase( pParentMenu
99 ,nId
3a7c1253 100 ,wxPMTextToLabel(rsText)
ab4fece8
DW
101 ,rsHelp
102 ,bIsCheckable ? wxITEM_CHECK : wxITEM_NORMAL
103 ,pSubMenu
104 )
f95255e2
DW
105{
106 wxASSERT_MSG(pParentMenu != NULL, wxT("a menu item should have a parent"));
938aa9c4
DW
107 memset(&m_vMenuData, '\0', sizeof(m_vMenuData));
108 m_vMenuData.id = (USHORT)nId;
f95255e2
DW
109
110 Init();
111} // end of wxMenuItem::wxMenuItem
112
113void wxMenuItem::Init()
114{
ab4fece8
DW
115 m_vRadioGroup.m_nStart = -1;
116 m_bIsRadioGroupStart = FALSE;
22e90769 117
f95255e2 118#if wxUSE_OWNER_DRAWN
ab4fece8
DW
119 //
120 // Set default menu colors
121 //
98fbab9e
VZ
122 SetTextColour(wxNullColour);
123 SetBackgroundColour(wxNullColour);
75f11ad7 124
ab4fece8
DW
125 //
126 // We don't want normal items be owner-drawn
127 //
98fbab9e 128 SetOwnerDrawn(false);
f95255e2 129#endif // wxUSE_OWNER_DRAWN
ab4fece8 130} // end of wxMenuItem::Init
0e320a79 131
75f11ad7 132wxMenuItem::~wxMenuItem()
0e320a79 133{
22e90769 134} // end of wxMenuItem::~wxMenuItem
0e320a79 135
22e90769
DW
136//
137// Misc
0e320a79
DW
138// ----
139
22e90769
DW
140//
141// Return the id for calling Win32 API functions
142//
75f11ad7
DW
143int wxMenuItem::GetRealId() const
144{
c5fb56c0 145 return m_subMenu ? (int)m_subMenu->GetHMenu() : GetId();
22e90769 146} // end of wxMenuItem::GetRealId
c5fb56c0 147
22e90769
DW
148//
149// Get item state
c5fb56c0 150// --------------
c5fb56c0
DW
151bool wxMenuItem::IsChecked() const
152{
6670f564
WS
153 USHORT uFlag = SHORT1FROMMR(::WinSendMsg( GetHMenuOf(m_parentMenu)
154 ,MM_QUERYITEMATTR
155 ,MPFROM2SHORT(GetId(), TRUE)
156 ,MPFROMSHORT(MIA_CHECKED)
157 ));
22e90769 158
6670f564 159 return (uFlag & MIA_CHECKED) == MIA_CHECKED ;
22e90769
DW
160} // end of wxMenuItem::IsChecked
161
52af3158 162wxString wxMenuItemBase::GetLabelText(
c9667cda 163 const wxString& rsText
22e90769 164)
c5fb56c0 165{
c9667cda
DW
166 wxString sLabel;
167
0fba44b4 168 for (const wxChar* zPc = rsText.c_str(); *zPc; zPc++)
2b33b728 169 {
c9667cda 170 if (*zPc == wxT('~') || *zPc == wxT('&'))
2b33b728 171 {
c9667cda
DW
172 //
173 // '~' is the escape character for OS/2PM and '&' is the one for
77ffb593 174 // wxWidgets - skip both of them
c9667cda 175 //
2b33b728
SN
176 continue;
177 }
c9667cda 178 sLabel += *zPc;
2b33b728 179 }
c9667cda 180 return sLabel;
52af3158 181} // end of wxMenuItemBase::GetLabelText
75f11ad7 182
598d8cac
DW
183//
184// Radio group stuff
f95255e2 185// -----------------
598d8cac 186//
f95255e2
DW
187void wxMenuItem::SetAsRadioGroupStart()
188{
6670f564 189 m_bIsRadioGroupStart = true;
f95255e2
DW
190} // end of wxMenuItem::SetAsRadioGroupStart
191
192void wxMenuItem::SetRadioGroupStart(
193 int nStart
194)
195{
598d8cac 196 wxASSERT_MSG( !m_bIsRadioGroupStart
9a83f860 197 ,wxT("should only be called for the next radio items")
598d8cac 198 );
f95255e2
DW
199
200 m_vRadioGroup.m_nStart = nStart;
598d8cac 201} // wxMenuItem::SetRadioGroupStart
f95255e2
DW
202
203void wxMenuItem::SetRadioGroupEnd(
204 int nEnd
205)
206{
598d8cac 207 wxASSERT_MSG( m_bIsRadioGroupStart
9a83f860 208 ,wxT("should only be called for the first radio item")
598d8cac 209 );
f95255e2
DW
210 m_vRadioGroup.m_nEnd = nEnd;
211} // end of wxMenuItem::SetRadioGroupEnd
212
0e320a79
DW
213// change item state
214// -----------------
215
22e90769
DW
216void wxMenuItem::Enable(
217 bool bEnable
218)
0e320a79 219{
22e90769 220 bool bOk;
75f11ad7 221
22e90769
DW
222 if (m_isEnabled == bEnable)
223 return;
224 if (bEnable)
914589c2
DW
225 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
226 ,MM_SETITEMATTR
227 ,MPFROM2SHORT(GetRealId(), TRUE)
f6bcfd97 228 ,MPFROM2SHORT(MIA_DISABLED, FALSE)
914589c2 229 );
22e90769 230 else
914589c2
DW
231 bOk = (bool)::WinSendMsg( GetHMenuOf(m_parentMenu)
232 ,MM_SETITEMATTR
233 ,MPFROM2SHORT(GetRealId(), TRUE)
f6bcfd97 234 ,MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)
914589c2 235 );
22e90769
DW
236 if (!bOk)
237 {
2173b18f 238 wxLogLastError(wxT("EnableMenuItem"));
0e320a79 239 }
22e90769
DW
240 wxMenuItemBase::Enable(bEnable);
241} // end of wxMenuItem::Enable
0e320a79 242
22e90769
DW
243void wxMenuItem::Check(
244 bool bCheck
245)
0e320a79 246{
22e90769 247 bool bOk;
75f11ad7 248
d65c269b 249 wxCHECK_RET( IsCheckable(), wxT("only checkable items may be checked") );
22e90769 250 if (m_isChecked == bCheck)
c5fb56c0 251 return;
f95255e2 252
50b39f8f 253 HMENU hMenu = GetHmenuOf(m_parentMenu);
598d8cac
DW
254
255 if (GetKind() == wxITEM_RADIO)
ab4fece8
DW
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);
ab4fece8 268
598d8cac 269 wxCHECK_RET( nPos != wxNOT_FOUND
9a83f860 270 ,wxT("menuitem not found in the menu items list?")
598d8cac 271 );
ab4fece8
DW
272
273 //
274 // Get the radio group range
275 //
598d8cac
DW
276 int nStart;
277 int nEnd;
ab4fece8
DW
278
279 if (m_bIsRadioGroupStart)
280 {
598d8cac
DW
281 //
282 // We already have all information we need
283 //
ab4fece8 284 nStart = nPos;
598d8cac 285 nEnd = m_vRadioGroup.m_nEnd;
ab4fece8 286 }
598d8cac 287 else // next radio group item
ab4fece8
DW
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 //
2461cfa0 299 wxMenuItemList::compatibility_iterator node = rItems.Item(nStart);
ab4fece8 300
2461cfa0 301 for (int n = nStart; n <= nEnd && node; n++)
ab4fece8 302 {
ab4fece8
DW
303 if (n == nPos)
304 {
598d8cac
DW
305 ::WinSendMsg( hMenu
306 ,MM_SETITEMATTR
307 ,MPFROM2SHORT(n, TRUE)
308 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
309 );
ab4fece8 310 }
598d8cac 311 if (n != nPos)
ab4fece8 312 {
2461cfa0 313 node->GetData()->m_isChecked = FALSE;
598d8cac
DW
314 ::WinSendMsg( hMenu
315 ,MM_SETITEMATTR
316 ,MPFROM2SHORT(n, TRUE)
317 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
318 );
ab4fece8 319 }
2461cfa0 320 node = node->GetNext();
ab4fece8
DW
321 }
322 }
323 else // check item
324 {
325 if (bCheck)
50b39f8f 326 bOk = (bool)::WinSendMsg( hMenu
ab4fece8
DW
327 ,MM_SETITEMATTR
328 ,MPFROM2SHORT(GetRealId(), TRUE)
329 ,MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)
330 );
331 else
50b39f8f 332 bOk = (bool)::WinSendMsg( hMenu
ab4fece8
DW
333 ,MM_SETITEMATTR
334 ,MPFROM2SHORT(GetRealId(), TRUE)
335 ,MPFROM2SHORT(MIA_CHECKED, FALSE)
336 );
337 }
22e90769
DW
338 if (!bOk)
339 {
2173b18f 340 wxLogLastError(wxT("CheckMenuItem"));
75f11ad7 341 }
22e90769
DW
342 wxMenuItemBase::Check(bCheck);
343} // end of wxMenuItem::Check
75f11ad7 344
52af3158 345void wxMenuItem::SetItemLabel( const wxString& rText )
75f11ad7 346{
22e90769
DW
347 //
348 // Don't do anything if label didn't change
349 //
2b33b728 350
3a7c1253 351 wxString sText = wxPMTextToLabel(rText);
50b39f8f 352 if (m_text == sText)
75f11ad7
DW
353 return;
354
345319d6 355 // wxMenuItemBase will do stock ID checks
52af3158 356 wxMenuItemBase::SetItemLabel(sText);
345319d6 357
98fbab9e 358 HWND hMenu = GetHmenuOf(m_parentMenu);
22e90769
DW
359
360 wxCHECK_RET(hMenu, wxT("menuitem without menu"));
75f11ad7 361
c5fb56c0
DW
362#if wxUSE_ACCEL
363 m_parentMenu->UpdateAccel(this);
364#endif // wxUSE_ACCEL
75f11ad7 365
6670f564
WS
366 USHORT uId = (USHORT)GetRealId();
367 MENUITEM vItem;
368 USHORT uFlagsOld;
914589c2 369
22e90769
DW
370 if (!::WinSendMsg( hMenu
371 ,MM_QUERYITEM
372 ,MPFROM2SHORT(uId, TRUE)
373 ,(MPARAM)&vItem
374 ))
75f11ad7 375 {
2173b18f 376 wxLogLastError(wxT("GetMenuState"));
75f11ad7
DW
377 }
378 else
379 {
22e90769
DW
380 uFlagsOld = vItem.afStyle;
381 if (IsSubMenu())
75f11ad7 382 {
22e90769 383 uFlagsOld |= MIS_SUBMENU;
75f11ad7
DW
384 }
385
f450b5cf 386 char* pData;
c5fb56c0 387
75f11ad7 388#if wxUSE_OWNER_DRAWN
22e90769 389 if (IsOwnerDrawn())
75f11ad7 390 {
22e90769 391 uFlagsOld |= MIS_OWNERDRAW;
f450b5cf 392 pData = (char*)this;
75f11ad7
DW
393 }
394 else
395#endif //owner drawn
396 {
22e90769 397 uFlagsOld |= MIS_TEXT;
404aba09 398 pData = (char*) m_text.wx_str();
22e90769
DW
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"));
75f11ad7
DW
411 }
412
22e90769
DW
413 //
414 // Set the text
415 //
416 if (::WinSendMsg( hMenu
417 ,MM_SETITEMTEXT
418 ,MPFROMSHORT(uId)
419 ,(MPARAM)pData
420 ))
75f11ad7
DW
421 {
422 wxLogLastError(wxT("ModifyMenu"));
423 }
424 }
22e90769 425} // end of wxMenuItem::SetText
0e320a79 426
98fbab9e
VZ
427#if wxUSE_OWNER_DRAWN
428
429wxString wxMenuItem::GetName() const
430{
431 return GetItemLabelText();
432}
433
434bool 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 //
a1b806b9 491 if (m_bmpChecked.IsOk())
98fbab9e
VZ
492 {
493 //
d13b34d3 494 // Is BMP height larger than text height?
98fbab9e
VZ
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
536bool wxMenuItem::OnDrawItem( wxDC& rDC,
537 const wxRect& rRect,
538 wxODAction eAction,
539 wxODStatus eStatus )
c5fb56c0 540{
98fbab9e
VZ
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 //
a1b806b9 697 if (IsCheckable() && !m_bmpChecked.IsOk())
98fbab9e
VZ
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
a1b806b9 726 if (vBmp.IsOk())
98fbab9e
VZ
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
c5fb56c0
DW
791
792// ----------------------------------------------------------------------------
793// wxMenuItemBase
794// ----------------------------------------------------------------------------
795
22e90769
DW
796wxMenuItem* wxMenuItemBase::New(
797 wxMenu* pParentMenu
798, int nId
799, const wxString& rName
800, const wxString& rHelp
d65c269b 801, wxItemKind kind
22e90769
DW
802, wxMenu* pSubMenu
803)
c5fb56c0 804{
22e90769
DW
805 return new wxMenuItem( pParentMenu
806 ,nId
807 ,rName
808 ,rHelp
d65c269b 809 ,kind
22e90769
DW
810 ,pSubMenu
811 );
812} // end of wxMenuItemBase::New