1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ownerdrw.cpp
3 // Purpose: implementation of wxOwnerDrawn class
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
13 #pragma implementation
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
20 #include "wx/window.h"
21 #include "wx/msw/private.h"
23 #include "wx/bitmap.h"
24 #include "wx/dcmemory.h"
31 #include "wx/ownerdrw.h"
32 #include "wx/menuitem.h"
35 // ============================================================================
36 // implementation of wxOwnerDrawn class
37 // ============================================================================
43 wxOwnerDrawn::wxOwnerDrawn(
50 m_bCheckable
= bCheckable
;
51 m_bOwnerDrawn
= FALSE
;
53 m_nMarginWidth
= ms_nLastMarginWidth
;
55 m_font
= *wxNORMAL_FONT
;
56 } // end of wxOwnerDrawn::wxOwnerDrawn
58 size_t wxOwnerDrawn::ms_nDefaultMarginWidth
= 15;
60 size_t wxOwnerDrawn::ms_nLastMarginWidth
= ms_nDefaultMarginWidth
;
67 bool wxOwnerDrawn::OnMeasureItem(
74 vDC
.SetFont(GetFont());
76 wxString sStr
= wxStripMenuCodes(m_strName
);
78 vDC
.GetTextExtent( sStr
83 (*pHeight
) = (*pHeight
) + 2;
84 m_nHeight
= *pHeight
; // remember height for use in OnDrawItem
86 } // end of wxOwnerDrawn::OnMeasureItem
89 bool wxOwnerDrawn::OnDrawItem(
97 // We do nothing on focus change
99 if (eAction
== wxODFocusChanged
)
103 // Select the font and draw the text
104 // ---------------------------------
108 HPS hPS
= rDC
.GetHPS();
112 RECTL vRect
= {rRect
.x
+ 4, rRect
.y
+ 1, rRect
.x
+ (rRect
.width
- 2), rRect
.y
+ rRect
.height
};
114 memset(&vCbnd
, 0, sizeof(CHARBUNDLE
));
117 // Use default font if no font set
121 m_font
.RealizeResource();
125 ::GpiSetCharSet(hPS
, LCID_DEFAULT
);
129 // Base on the status of the menu item pick the right colors
131 if (eStatus
& wxODSelected
)
133 wxColour
vCol2("WHITE");
134 vColBack
.Set( (unsigned char)0
137 ); // no dark blue in color table
140 else if (eStatus
& wxODDisabled
)
142 vRef
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
143 ,SYSCLR_MENU
// Light gray
146 vColBack
.Set( GetRValue(vRef
)
150 vRef
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
151 ,SYSCLR_MENUDISABLEDTEXT
// dark gray
154 vColText
.Set( GetRValue(vRef
)
162 // Fall back to default colors if none explicitly specified
164 vRef
= ::WinQuerySysColor( HWND_DESKTOP
165 ,SYSCLR_MENU
// we are using gray for all our window backgrounds in wxWindows
168 vColBack
.Set( GetRValue(vRef
)
172 vRef
= ::WinQuerySysColor( HWND_DESKTOP
173 ,SYSCLR_WINDOWTEXT
// Black
176 vColText
.Set( GetRValue(vRef
)
182 rDC
.SetTextBackground(vColBack
);
183 rDC
.SetTextForeground(vColText
);
184 rDC
.SetBackgroundMode(wxTRANSPARENT
);
185 vCbnd
.lColor
= vColText
.GetPixel();
186 vCbnd
.lBackColor
= vColBack
.GetPixel();
189 ,CBB_BACK_COLOR
| CBB_COLOR
198 // Paint the background
200 ::WinFillRect(hPS
, &vRect
, vColBack
.GetPixel());
203 // Determine where to draw and leave space for a check-mark.
205 int nX
= rRect
.x
+ GetMarginWidth();
208 // Unfortunately, unlike Win32, PM has no owner drawn specific text
209 // drawing methods like ::DrawState that can cleanly handle accel
210 // pneumonics and deal, automatically, with various states, so we have
211 // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn
212 // strings either. We cannot handle mneumonics either. We display
213 // it, though, in hopes we can figure it out some day.
217 // Display main text and accel text separately to allign better
219 wxString sTgt
= "\t";
220 wxString sFullString
= m_strName
; // need to save the original text
226 bool bFoundMneumonic
= FALSE
;
227 bool bFoundAccel
= FALSE
;
230 // Deal with the tab, extracting the Accel text
232 nIndex
= sFullString
.Find(sTgt
.c_str());
236 sAccel
= sFullString
.Mid(nIndex
+ 1);
237 sFullString
.Remove(nIndex
);
241 // Deal with the mneumonic character
244 nIndex
= sFullString
.Find(sTgt
.c_str());
247 wxString sTmp
= sFullString
;
249 bFoundMneumonic
= TRUE
;
251 rDC
.GetTextExtent( sTmp
255 sTmp
= sFullString
[nIndex
+ 1];
256 rDC
.GetTextExtent( sTmp
260 sFullString
.Replace(sTgt
.c_str(), "", TRUE
);
264 // Draw the main item text sans the accel text
266 POINTL vPntStart
= {nX
, rRect
.y
+ 4};
267 ::GpiCharStringAt( rDC
.GetHPS()
269 ,sFullString
.length()
270 ,(PCH
)sFullString
.c_str()
275 // Underline the mneumonic -- still won't work, but at least it "looks" right
278 POINTL vPntEnd
= {nX
+ nWidth
+ nCharWidth
- 3, rRect
.y
+ 2}; //CharWidth is bit wide
280 vPntStart
.x
= nX
+ nWidth
- 1;
281 vPntStart
.y
= rRect
.y
+ 2; // Make it look pretty!
282 vPen
= wxPen(vColText
, 1, wxSOLID
); // Assuming we are always black
284 ::GpiMove(hPS
, &vPntStart
);
285 ::GpiLine(hPS
, &vPntEnd
);
289 // Now draw the accel text
296 rDC
.GetTextExtent( sAccel
301 // Back off the starting position from the right edge
303 vPntStart
.x
= rRect
.width
- (nWidth
+ 7);
304 vPntStart
.y
= rRect
.y
+ 4;
305 ::GpiCharStringAt( rDC
.GetHPS()
316 if (IsCheckable() && !m_bmpChecked
.Ok())
318 if (eStatus
& wxODChecked
)
321 HBITMAP hBmpCheck
= ::WinGetSysBitmap(HWND_DESKTOP
, SBMP_MENUCHECK
);
323 vRect
.xLeft
= rRect
.x
;
324 vRect
.xRight
= rRect
.x
+ GetMarginWidth();
325 vRect
.yBottom
= rRect
.y
;
326 vRect
.yTop
= rRect
.y
+ m_nHeight
- 3;
328 ::WinDrawBitmap( hPS
// PS for this menuitem
329 ,hBmpCheck
// system checkmark
330 ,NULL
// draw the whole bitmap
331 ,(PPOINTL
)&vRect
// destination -- bottom left corner of the menuitem area
334 ,DBM_NORMAL
// draw normal size
341 // For uncheckable item we use only the 'checked' bitmap
343 wxBitmap
vBmp(GetBitmap(IsCheckable() ? ((eStatus
& wxODChecked
) != 0) : TRUE
));
348 wxMemoryDC
vDCMem(&rDC
);
349 wxMemoryDC
* pOldDC
= (wxMemoryDC
*)vBmp
.GetSelectedInto();
353 vBmp
.SetSelectedInto(NULL
);
355 vDCMem
.SelectObject(vBmp
);
360 int nBmpWidth
= vBmp
.GetWidth();
361 int nBmpHeight
= vBmp
.GetHeight();
364 // There should be enough space!
366 wxASSERT((nBmpWidth
<= rRect
.width
) && (nBmpHeight
<= rRect
.height
));
369 //MT: blit with mask enabled.
371 rDC
.Blit( rRect
.x
+ (GetMarginWidth() - nBmpWidth
) / 2
372 ,rRect
.y
+ (m_nHeight
- nBmpHeight
) /2
382 if (eStatus
& wxODSelected
)
384 RECT vRectBmp
= { rRect
.x
386 ,rRect
.x
+ GetMarginWidth()
389 POINTL vPnt1
= {rRect
.x
+ 1, rRect
.y
+ 3}; // Leave a little background border
390 POINTL vPnt2
= {rRect
.x
+ GetMarginWidth(), rRect
.y
+ m_nHeight
- 3};
394 vLine
.lColor
= vColBack
.GetPixel();
401 ::GpiMove(hPS
, &vPnt1
);
409 vBmp
.SetSelectedInto(NULL
);
413 } // end of wxOwnerDrawn::OnDrawItem
415 #endif //wxUSE_OWNER_DRAWN