]>
Commit | Line | Data |
---|---|---|
63415778 DW |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Name: msw/ownerdrw.cpp | |
3 | // Purpose: implementation of wxOwnerDrawn class | |
4 | // Author: David Webster | |
fb46a9a6 | 5 | // Modified by: |
63415778 DW |
6 | // Created: 10/12/99 |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) David Webster | |
9 | // Licence: wxWindows license | |
10 | /////////////////////////////////////////////////////////////////////////////// | |
11 | ||
aa213887 SN |
12 | #ifdef __GNUG__ |
13 | #pragma implementation | |
14 | #endif | |
15 | ||
63415778 DW |
16 | // For compilers that support precompilation, includes "wx.h". |
17 | #include "wx/wxprec.h" | |
18 | ||
19 | #ifndef WX_PRECOMP | |
20 | #include "wx/window.h" | |
21 | #include "wx/msw/private.h" | |
22 | #include "wx/font.h" | |
23 | #include "wx/bitmap.h" | |
24 | #include "wx/dcmemory.h" | |
25 | #include "wx/menu.h" | |
26 | #include "wx/utils.h" | |
27 | #endif | |
28 | ||
7e99520b DW |
29 | #if wxUSE_OWNER_DRAWN |
30 | ||
63415778 DW |
31 | #include "wx/ownerdrw.h" |
32 | #include "wx/menuitem.h" | |
33 | ||
34 | ||
35 | // ============================================================================ | |
36 | // implementation of wxOwnerDrawn class | |
37 | // ============================================================================ | |
38 | ||
402e2f7c | 39 | // |
63415778 DW |
40 | // ctor |
41 | // ---- | |
402e2f7c DW |
42 | // |
43 | wxOwnerDrawn::wxOwnerDrawn( | |
44 | const wxString& rsStr | |
45 | , bool bCheckable | |
46 | , bool bMenuItem | |
47 | ) | |
48 | : m_strName(rsStr) | |
63415778 | 49 | { |
402e2f7c DW |
50 | m_bCheckable = bCheckable; |
51 | m_bOwnerDrawn = FALSE; | |
52 | m_nHeight = 0; | |
53 | m_nMarginWidth = ms_nLastMarginWidth; | |
54 | if (wxNORMAL_FONT) | |
55 | m_font = *wxNORMAL_FONT; | |
56 | } // end of wxOwnerDrawn::wxOwnerDrawn | |
63415778 | 57 | |
402e2f7c | 58 | size_t wxOwnerDrawn::ms_nDefaultMarginWidth = 15; |
63415778 DW |
59 | |
60 | size_t wxOwnerDrawn::ms_nLastMarginWidth = ms_nDefaultMarginWidth; | |
61 | ||
402e2f7c DW |
62 | // |
63 | // Drawing | |
63415778 | 64 | // ------- |
402e2f7c | 65 | // |
63415778 | 66 | |
402e2f7c DW |
67 | bool wxOwnerDrawn::OnMeasureItem( |
68 | size_t* pWidth | |
69 | , size_t* pHeight | |
70 | ) | |
63415778 | 71 | { |
402e2f7c DW |
72 | wxMemoryDC vDC; |
73 | ||
74 | vDC.SetFont(GetFont()); | |
75 | ||
76 | wxString sStr = wxStripMenuCodes(m_strName); | |
77 | ||
78 | // | |
79 | // # without this menu items look too tightly packed (at least under Windows) | |
80 | // | |
81 | sStr += wxT('W'); // 'W' is typically the widest letter | |
82 | vDC.GetTextExtent( sStr | |
83 | ,(long *)pWidth | |
84 | ,(long *)pHeight | |
85 | ); | |
86 | ||
87 | // | |
88 | // JACS: items still look too tightly packed, so adding 2 pixels. | |
89 | // | |
90 | (*pHeight) = (*pHeight) + 2; | |
91 | m_nHeight = *pHeight; // remember height for use in OnDrawItem | |
92 | return TRUE; | |
93 | } // end of wxOwnerDrawn::OnMeasureItem | |
63415778 DW |
94 | |
95 | // searching for this macro you'll find all the code where I'm using the native | |
96 | // Win32 GDI functions and not wxWindows ones. Might help to whoever decides to | |
97 | // port this code to X. (VZ) | |
98 | ||
99 | // JACS: TODO. Why does a disabled but highlighted item still | |
100 | // get drawn embossed? How can we tell DrawState that we don't want the | |
101 | // embossing? | |
102 | ||
103 | // draw the item | |
402e2f7c DW |
104 | bool wxOwnerDrawn::OnDrawItem( |
105 | wxDC& rDC | |
106 | , const wxRect& rRect | |
107 | , wxODAction eAction | |
108 | , wxODStatus eStatus | |
109 | ) | |
63415778 | 110 | { |
402e2f7c DW |
111 | // |
112 | // For now we let PM deal with highlighting and framing and such in a | |
113 | // default manner. So we leave fsAttribute and fsOldAttribute ( or | |
114 | // fsState and fsOldState ) the same and pass it on. We may want to add | |
115 | // code later to draw theseattributes in a more custom manner. | |
116 | // | |
117 | ||
118 | // | |
119 | // WxWinGdi_CColour <-> RGB | |
120 | // | |
121 | #define ToRGB(col) OS2RGB(col.Red(), col.Green(), col.Blue()) | |
122 | #define UnRGB(col) GetRValue(col), GetGValue(col), GetBValue(col) | |
123 | ||
124 | CHARBUNDLE vCbndText; | |
125 | CHARBUNDLE vCbndBack; | |
126 | HPS hPS= rDC.GetHPS(); | |
127 | ULONG lColBack; | |
128 | ULONG lColText; | |
129 | ||
130 | if (eStatus & wxODSelected) | |
131 | { | |
132 | lColBack = (DWORD)::WinQuerySysColor( HWND_DESKTOP | |
133 | ,SYSCLR_MENUHILITEBGND // Light gray | |
134 | ,0L | |
135 | ); | |
136 | lColText = (DWORD)::WinQuerySysColor( HWND_DESKTOP | |
137 | ,SYSCLR_MENUTEXT // Black | |
138 | ,0L | |
139 | ); | |
140 | } | |
141 | else if (eStatus & wxODDisabled) | |
142 | { | |
143 | lColBack = (DWORD)::WinQuerySysColor( HWND_DESKTOP | |
144 | ,SYSCLR_MENU // Light gray | |
145 | ,0L | |
146 | ); | |
147 | lColText = (DWORD)::WinQuerySysColor( HWND_DESKTOP | |
148 | ,SYSCLR_MENUDISABLEDTEXT // dark gray | |
149 | ,0L | |
150 | ); | |
151 | } | |
152 | else | |
153 | { | |
154 | // | |
155 | // Fall back to default colors if none explicitly specified | |
156 | // | |
157 | lColBack = m_colBack.Ok() ? ToRGB(m_colBack) : ::WinQuerySysColor( HWND_DESKTOP | |
158 | ,SYSCLR_MENU // we are using gray for all our window backgrounds in wxWindows | |
159 | ,0L | |
160 | ); | |
161 | lColText = m_colText.Ok() ? ToRGB(m_colText) : ::WinQuerySysColor( HWND_DESKTOP | |
162 | ,SYSCLR_WINDOWTEXT // Black | |
163 | ,0L | |
164 | ); | |
165 | } | |
166 | vCbndText.lColor = (LONG)lColText; | |
167 | vCbndBack.lColor = (LONG)lColBack; | |
168 | ||
169 | ::GpiSetAttrs( hPS | |
170 | ,PRIM_CHAR | |
171 | ,CBB_BACK_COLOR | |
172 | ,0 | |
173 | ,&vCbndBack | |
174 | ); | |
175 | ::GpiSetAttrs( hPS | |
176 | ,PRIM_CHAR | |
177 | ,CBB_COLOR | |
178 | ,0 | |
179 | ,&vCbndText | |
180 | ); | |
181 | ||
182 | ||
183 | // | |
184 | // Determine where to draw and leave space for a check-mark. | |
185 | // | |
186 | int nX = rRect.x + GetMarginWidth(); | |
187 | ||
188 | // | |
189 | // Select the font and draw the text | |
190 | // --------------------------------- | |
191 | // | |
192 | ||
193 | // | |
194 | // Use default font if no font set | |
195 | // | |
196 | if (m_font.Ok()) | |
197 | { | |
198 | m_font.RealizeResource(); | |
199 | } | |
200 | else | |
201 | { | |
202 | ::GpiSetCharSet(hPS, LCID_DEFAULT); | |
203 | } | |
63415778 | 204 | |
402e2f7c DW |
205 | // |
206 | // Unfortunately, unlike Win32, PM has no owner drawn specific text | |
207 | // drawing methods like ::DrawState that can cleanly handle accel | |
208 | // pneumonics and deal, automatically, with various states, so we have | |
209 | // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn | |
210 | // strings either. | |
211 | ||
212 | rDC.DrawText( m_strName | |
213 | ,nX | |
214 | ,rRect.y | |
215 | ); | |
216 | ||
217 | // | |
218 | // Draw the bitmap | |
219 | // --------------- | |
220 | // | |
221 | if (IsCheckable() && !m_bmpChecked.Ok()) | |
222 | { | |
223 | if (eStatus & wxODChecked) | |
224 | { | |
225 | RECTL vRect; | |
226 | HBITMAP hBmpCheck = ::WinGetSysBitmap(HWND_DESKTOP, SBMP_MENUCHECK); | |
227 | ||
228 | vRect.xLeft = rRect.x; | |
229 | vRect.xRight = rRect.x + GetMarginWidth(); | |
230 | vRect.yBottom = rRect.y; | |
231 | vRect.yTop = rRect.y + m_nHeight; | |
232 | ||
233 | ::WinDrawBitmap( hPS // PS for this menuitem | |
234 | ,hBmpCheck // system checkmark | |
235 | ,NULL // draw the whole bitmap | |
236 | ,(PPOINTL)&vRect // destination -- bottom left corner of the menuitem area | |
237 | ,0L // ignored | |
238 | ,0L // draw a bitmap | |
239 | ,DBM_NORMAL // draw normal size | |
240 | ); | |
241 | } | |
63415778 | 242 | } |
402e2f7c DW |
243 | else |
244 | { | |
245 | // | |
246 | // For uncheckable item we use only the 'checked' bitmap | |
247 | // | |
248 | wxBitmap vBmp(GetBitmap(IsCheckable() ? ((eStatus & wxODChecked) != 0) : TRUE)); | |
249 | ||
250 | if (vBmp.Ok()) | |
251 | { | |
252 | wxMemoryDC vDCMem(&rDC); | |
253 | ||
254 | vDCMem.SelectObject(vBmp); | |
255 | ||
256 | // | |
257 | // Center bitmap | |
258 | // | |
259 | int nBmpWidth = vBmp.GetWidth(); | |
260 | int nBmpHeight = vBmp.GetHeight(); | |
261 | ||
262 | // | |
263 | // There should be enough space! | |
264 | // | |
265 | wxASSERT((nBmpWidth <= rRect.width) && (nBmpHeight <= rRect.height)); | |
266 | ||
267 | // | |
268 | //MT: blit with mask enabled. | |
269 | // | |
270 | rDC.Blit( rRect.x + (GetMarginWidth() - nBmpWidth) / 2 | |
271 | ,rRect.y + (m_nHeight - nBmpHeight) /2 | |
272 | ,nBmpWidth | |
273 | ,nBmpHeight | |
274 | ,&vDCMem | |
275 | ,0 | |
276 | ,0 | |
277 | ,wxCOPY | |
278 | ,TRUE | |
279 | ); | |
280 | ||
281 | if (eStatus & wxODSelected) | |
282 | { | |
283 | RECT vRectBmp = { rRect.x | |
284 | ,rRect.y | |
285 | ,rRect.x + GetMarginWidth() | |
286 | ,rRect.y + m_nHeight | |
287 | }; | |
288 | LINEBUNDLE vLine; | |
289 | ||
290 | vLine.lColor = lColBack; | |
291 | ::GpiSetAttrs( hPS | |
292 | ,PRIM_LINE | |
293 | ,LBB_COLOR | |
294 | ,0 | |
295 | ,&vLine | |
296 | ); | |
297 | ::GpiBox( hPS | |
298 | ,DRO_OUTLINE | |
299 | ,(PPOINTL)&vRectBmp | |
300 | ,0L | |
301 | ,0L | |
302 | ); | |
303 | } | |
304 | } | |
63415778 | 305 | } |
402e2f7c | 306 | |
63415778 DW |
307 | return TRUE; |
308 | } | |
309 | ||
7e99520b | 310 | #endif //wxUSE_OWNER_DRAWN |