xti extensions
[wxWidgets.git] / src / msw / bmpbuttn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/bmpbuttn.cpp
3 // Purpose: wxBitmapButton
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "bmpbuttn.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_BMPBUTTON
24
25 #ifndef WX_PRECOMP
26 #include "wx/bmpbuttn.h"
27 #include "wx/log.h"
28 #include "wx/dcmemory.h"
29 #endif
30
31 #include "wx/msw/private.h"
32
33 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
34
35 /*
36 TODO PROPERTIES :
37
38 long "style" , wxBU_AUTODRAW
39 bool "default" , 0
40 bitmap "selected" ,
41 bitmap "focus" ,
42 bitmap "disabled" ,
43 */
44
45 #define BUTTON_HEIGHT_FACTOR (EDIT_CONTROL_FACTOR * 1.1)
46
47 bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id, const wxBitmap& bitmap,
48 const wxPoint& pos,
49 const wxSize& size, long style,
50 const wxValidator& validator,
51 const wxString& name)
52 {
53 m_bmpNormal = bitmap;
54 SetName(name);
55
56 #if wxUSE_VALIDATORS
57 SetValidator(validator);
58 #endif // wxUSE_VALIDATORS
59
60 parent->AddChild(this);
61
62 m_backgroundColour = parent->GetBackgroundColour();
63 m_foregroundColour = parent->GetForegroundColour();
64 m_windowStyle = style;
65
66 if ( style & wxBU_AUTODRAW )
67 {
68 m_marginX = wxDEFAULT_BUTTON_MARGIN;
69 m_marginY = wxDEFAULT_BUTTON_MARGIN;
70 }
71
72 int x = pos.x;
73 int y = pos.y;
74 int width = size.x;
75 int height = size.y;
76
77 if (id == -1)
78 m_windowId = NewControlId();
79 else
80 m_windowId = id;
81
82 if ( width == -1 && bitmap.Ok())
83 width = bitmap.GetWidth() + 2*m_marginX;
84
85 if ( height == -1 && bitmap.Ok())
86 height = bitmap.GetHeight() + 2*m_marginY;
87
88 long msStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_OWNERDRAW ;
89
90 if ( m_windowStyle & wxCLIP_SIBLINGS )
91 msStyle |= WS_CLIPSIBLINGS;
92
93 #ifdef __WIN32__
94 if(m_windowStyle & wxBU_LEFT)
95 msStyle |= BS_LEFT;
96 if(m_windowStyle & wxBU_RIGHT)
97 msStyle |= BS_RIGHT;
98 if(m_windowStyle & wxBU_TOP)
99 msStyle |= BS_TOP;
100 if(m_windowStyle & wxBU_BOTTOM)
101 msStyle |= BS_BOTTOM;
102 #endif
103
104 m_hWnd = (WXHWND)CreateWindowEx
105 (
106 0,
107 wxT("BUTTON"),
108 wxEmptyString,
109 msStyle,
110 0, 0, 0, 0,
111 GetWinHwnd(parent),
112 (HMENU)m_windowId,
113 wxGetInstance(),
114 NULL
115 );
116
117 // Subclass again for purposes of dialog editing mode
118 SubclassWin(m_hWnd);
119
120 SetFont(parent->GetFont());
121
122 SetSize(x, y, width, height);
123
124 return TRUE;
125 }
126
127 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
128 #define FOCUS_MARGIN 3
129
130 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
131 {
132 #ifndef __WXWINCE__
133 long style = GetWindowLong((HWND) GetHWND(), GWL_STYLE);
134 if (style & BS_BITMAP)
135 {
136 // Let default procedure draw the bitmap, which is defined
137 // in the Windows resource.
138 return FALSE;
139 }
140 #endif
141
142 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) item;
143 HDC hDC = lpDIS->hDC;
144 UINT state = lpDIS->itemState;
145 bool isSelected = (state & ODS_SELECTED) != 0;
146 bool autoDraw = (GetWindowStyleFlag() & wxBU_AUTODRAW) != 0;
147
148
149 // choose the bitmap to use depending on the button state
150 wxBitmap* bitmap;
151
152 if ( isSelected && m_bmpSelected.Ok() )
153 bitmap = &m_bmpSelected;
154 else if ((state & ODS_FOCUS) && m_bmpFocus.Ok())
155 bitmap = &m_bmpFocus;
156 else if ((state & ODS_DISABLED) && m_bmpDisabled.Ok())
157 bitmap = &m_bmpDisabled;
158 else
159 bitmap = &m_bmpNormal;
160
161 if ( !bitmap->Ok() )
162 return FALSE;
163
164 // centre the bitmap in the control area
165 int x = lpDIS->rcItem.left;
166 int y = lpDIS->rcItem.top;
167 int width = lpDIS->rcItem.right - x;
168 int height = lpDIS->rcItem.bottom - y;
169 int wBmp = bitmap->GetWidth();
170 int hBmp = bitmap->GetHeight();
171
172 int x1,y1;
173
174 if(m_windowStyle & wxBU_LEFT)
175 x1 = x + (FOCUS_MARGIN+1);
176 else if(m_windowStyle & wxBU_RIGHT)
177 x1 = x + (width - wBmp) - (FOCUS_MARGIN+1);
178 else
179 x1 = x + (width - wBmp) / 2;
180
181 if(m_windowStyle & wxBU_TOP)
182 y1 = y + (FOCUS_MARGIN+1);
183 else if(m_windowStyle & wxBU_BOTTOM)
184 y1 = y + (height - hBmp) - (FOCUS_MARGIN+1);
185 else
186 y1 = y + (height - hBmp) / 2;
187
188 if ( isSelected && autoDraw )
189 {
190 x1++;
191 y1++;
192 }
193
194 // draw the face, if auto-drawing
195 if ( autoDraw )
196 {
197 DrawFace((WXHDC) hDC,
198 lpDIS->rcItem.left, lpDIS->rcItem.top,
199 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
200 isSelected);
201 }
202
203 // draw the bitmap
204 wxDC dst;
205 dst.SetHDC((WXHDC) hDC, FALSE);
206 dst.DrawBitmap(*bitmap, x1, y1, TRUE);
207
208 // draw focus / disabled state, if auto-drawing
209 if ( (state & ODS_DISABLED) && autoDraw )
210 {
211 DrawButtonDisable((WXHDC) hDC,
212 lpDIS->rcItem.left, lpDIS->rcItem.top,
213 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
214 TRUE);
215 }
216 else if ( (state & ODS_FOCUS) && autoDraw )
217 {
218 DrawButtonFocus((WXHDC) hDC,
219 lpDIS->rcItem.left,
220 lpDIS->rcItem.top,
221 lpDIS->rcItem.right,
222 lpDIS->rcItem.bottom,
223 isSelected);
224 }
225
226 return TRUE;
227 }
228
229 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
230
231 #if defined(__WIN95__)
232
233 void wxBitmapButton::DrawFace( WXHDC dc, int left, int top, int right, int bottom, bool sel )
234 {
235 HPEN oldp;
236 HPEN penHiLight;
237 HPEN penLight;
238 HPEN penShadow;
239 HPEN penDkShadow;
240 HBRUSH brushFace;
241
242 // create needed pens and brush
243 penHiLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
244 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
245 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
246 penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
247 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
248 // Taking the background colour fits in better with
249 // Windows XP themes.
250 brushFace = CreateSolidBrush(m_backgroundColour.m_pixel);
251
252 // draw the rectangle
253 RECT rect;
254 rect.left = left;
255 rect.right = right;
256 rect.top = top;
257 rect.bottom = bottom;
258 FillRect((HDC) dc, &rect, brushFace);
259
260 // draw the border
261 oldp = (HPEN) SelectObject( (HDC) dc, sel? penDkShadow : penHiLight);
262
263 wxDrawLine((HDC) dc, left, top, right-1, top);
264 wxDrawLine((HDC) dc, left, top+1, left, bottom-1);
265
266 SelectObject( (HDC) dc, sel? penShadow : penLight);
267 wxDrawLine((HDC) dc, left+1, top+1, right-2, top+1);
268 wxDrawLine((HDC) dc, left+1, top+2, left+1, bottom-2);
269
270 SelectObject( (HDC) dc, sel? penLight : penShadow);
271 wxDrawLine((HDC) dc, left+1, bottom-2, right-1, bottom-2);
272 wxDrawLine((HDC) dc, right-2, bottom-3, right-2, top);
273
274 SelectObject( (HDC) dc, sel? penHiLight : penDkShadow);
275 wxDrawLine((HDC) dc, left, bottom-1, right+2, bottom-1);
276 wxDrawLine((HDC) dc, right-1, bottom-2, right-1, top-1);
277
278 // delete allocated resources
279 SelectObject((HDC) dc,oldp);
280 DeleteObject(penHiLight);
281 DeleteObject(penLight);
282 DeleteObject(penShadow);
283 DeleteObject(penDkShadow);
284 DeleteObject(brushFace);
285 }
286
287 #else
288
289 void wxBitmapButton::DrawFace( WXHDC dc, int left, int top, int right, int bottom, bool sel )
290 {
291 HPEN oldp;
292 HPEN penBorder;
293 HPEN penLight;
294 HPEN penShadow;
295 HBRUSH brushFace;
296
297 // create needed pens and brush
298 penBorder = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWFRAME));
299 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
300 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNHIGHLIGHT));
301 brushFace = CreateSolidBrush(COLOR_BTNFACE);
302
303 // draw the rectangle
304 RECT rect;
305 rect.left = left;
306 rect.right = right;
307 rect.top = top;
308 rect.bottom = bottom;
309 FillRect((HDC) dc, &rect, brushFace);
310
311 // draw the border
312 oldp = (HPEN) SelectObject( (HDC) dc, penBorder);
313 MoveToEx((HDC) dc,left+1,top,NULL);LineTo((HDC) dc,right-1,top);
314 MoveToEx((HDC) dc,left,top+1,NULL);LineTo((HDC) dc,left,bottom-1);
315 MoveToEx((HDC) dc,left+1,bottom-1,NULL);LineTo((HDC) dc,right-1,bottom-1);
316 MoveToEx((HDC) dc,right-1,top+1,NULL);LineTo((HDC) dc,right-1,bottom-1);
317
318 SelectObject( (HDC) dc, penShadow);
319 if (sel)
320 {
321 MoveToEx((HDC) dc,left+1 ,bottom-2 ,NULL);
322 LineTo((HDC) dc, left+1 ,top+1);
323 LineTo((HDC) dc, right-2 ,top+1);
324 }
325 else
326 {
327 MoveToEx((HDC) dc,left+1 ,bottom-2 ,NULL);
328 LineTo((HDC) dc, right-2 ,bottom-2);
329 LineTo((HDC) dc, right-2 ,top);
330
331 MoveToEx((HDC) dc,left+2 ,bottom-3 ,NULL);
332 LineTo((HDC) dc, right-3 ,bottom-3);
333 LineTo((HDC) dc, right-3 ,top+1);
334
335 SelectObject( (HDC) dc, penLight);
336
337 MoveToEx((HDC) dc,left+1 ,bottom-2 ,NULL);
338 LineTo((HDC) dc, left+1 ,top+1);
339 LineTo((HDC) dc, right-2 ,top+1);
340 }
341
342 // delete allocated resources
343 SelectObject((HDC) dc,oldp);
344 DeleteObject(penBorder);
345 DeleteObject(penLight);
346 DeleteObject(penShadow);
347 DeleteObject(brushFace);
348 }
349
350 #endif // defined(__WIN95__)
351
352
353 void wxBitmapButton::DrawButtonFocus( WXHDC dc, int left, int top, int right, int bottom, bool sel )
354 {
355 RECT rect;
356 rect.left = left;
357 rect.top = top;
358 rect.right = right;
359 rect.bottom = bottom;
360 InflateRect( &rect, - FOCUS_MARGIN, - FOCUS_MARGIN );
361
362 // GRG: the focus rectangle should not move when the button is pushed!
363 /*
364 if ( sel )
365 OffsetRect( &rect, 1, 1 );
366 */
367 (void)sel;
368 DrawFocusRect( (HDC) dc, &rect );
369 }
370
371 extern HBRUSH wxDisableButtonBrush;
372 void wxBitmapButton::DrawButtonDisable( WXHDC dc, int left, int top, int right, int bottom, bool with_marg )
373 {
374 HBRUSH old = (HBRUSH) SelectObject( (HDC) dc, wxDisableButtonBrush );
375
376 // VZ: what's this?? there is no such ROP AFAIK
377 #ifdef __SALFORDC__
378 DWORD dwRop = 0xFA0089L;
379 #else
380 DWORD dwRop = 0xFA0089UL;
381 #endif
382
383 if ( with_marg )
384 {
385 left += m_marginX;
386 top += m_marginY;
387 right -= 2 * m_marginX;
388 bottom -= 2 * m_marginY;
389 }
390
391 ::PatBlt( (HDC) dc, left, top, right, bottom, dwRop);
392
393 ::SelectObject( (HDC) dc, old );
394 }
395
396 void wxBitmapButton::SetDefault()
397 {
398 wxButton::SetDefault();
399 }
400
401 #endif // wxUSE_BMPBUTTON