]> git.saurik.com Git - wxWidgets.git/blob - src/msw/bmpbuttn.cpp
support for 10.4 provided context menu
[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 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_BMPBUTTON
20
21 #ifndef WX_PRECOMP
22 #include "wx/bmpbuttn.h"
23 #include "wx/log.h"
24 #include "wx/dcmemory.h"
25 #endif
26
27 #include "wx/msw/private.h"
28 #include "wx/image.h"
29
30 // ----------------------------------------------------------------------------
31 // macros
32 // ----------------------------------------------------------------------------
33
34 #if wxUSE_EXTENDED_RTTI
35
36 WX_DEFINE_FLAGS( wxBitmapButtonStyle )
37
38 wxBEGIN_FLAGS( wxBitmapButtonStyle )
39 // new style border flags, we put them first to
40 // use them for streaming out
41 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
42 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
43 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
44 wxFLAGS_MEMBER(wxBORDER_RAISED)
45 wxFLAGS_MEMBER(wxBORDER_STATIC)
46 wxFLAGS_MEMBER(wxBORDER_NONE)
47
48 // old style border flags
49 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
50 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
51 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
52 wxFLAGS_MEMBER(wxRAISED_BORDER)
53 wxFLAGS_MEMBER(wxSTATIC_BORDER)
54 wxFLAGS_MEMBER(wxBORDER)
55
56 // standard window styles
57 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
58 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
59 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
60 wxFLAGS_MEMBER(wxWANTS_CHARS)
61 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
62 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
63 wxFLAGS_MEMBER(wxVSCROLL)
64 wxFLAGS_MEMBER(wxHSCROLL)
65
66 wxFLAGS_MEMBER(wxBU_AUTODRAW)
67 wxFLAGS_MEMBER(wxBU_LEFT)
68 wxFLAGS_MEMBER(wxBU_RIGHT)
69 wxFLAGS_MEMBER(wxBU_TOP)
70 wxFLAGS_MEMBER(wxBU_BOTTOM)
71 wxEND_FLAGS( wxBitmapButtonStyle )
72
73 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton, wxButton,"wx/bmpbuttn.h")
74
75 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton)
76 wxPROPERTY_FLAGS( WindowStyle , wxBitmapButtonStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
77 wxEND_PROPERTIES_TABLE()
78
79 wxBEGIN_HANDLERS_TABLE(wxBitmapButton)
80 wxEND_HANDLERS_TABLE()
81
82 wxCONSTRUCTOR_5( wxBitmapButton , wxWindow* , Parent , wxWindowID , Id , wxBitmap , Bitmap , wxPoint , Position , wxSize , Size )
83
84 #else
85 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
86 #endif
87
88 BEGIN_EVENT_TABLE(wxBitmapButton, wxBitmapButtonBase)
89 EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged)
90 EVT_ENTER_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
91 EVT_LEAVE_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
92 END_EVENT_TABLE()
93
94 /*
95 TODO PROPERTIES :
96
97 long "style" , wxBU_AUTODRAW
98 bool "default" , 0
99 bitmap "selected" ,
100 bitmap "focus" ,
101 bitmap "disabled" ,
102 */
103
104 bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
105 const wxBitmap& bitmap,
106 const wxPoint& pos,
107 const wxSize& size, long style,
108 const wxValidator& wxVALIDATOR_PARAM(validator),
109 const wxString& name)
110 {
111 m_bmpNormal = bitmap;
112 SetName(name);
113
114 #if wxUSE_VALIDATORS
115 SetValidator(validator);
116 #endif // wxUSE_VALIDATORS
117
118 parent->AddChild(this);
119
120 m_backgroundColour = parent->GetBackgroundColour();
121 m_foregroundColour = parent->GetForegroundColour();
122 m_windowStyle = style;
123
124 if ( style & wxBU_AUTODRAW )
125 {
126 m_marginX =
127 m_marginY = 4;
128 }
129
130 if (id == wxID_ANY)
131 m_windowId = NewControlId();
132 else
133 m_windowId = id;
134
135 long msStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_OWNERDRAW ;
136
137 if ( m_windowStyle & wxCLIP_SIBLINGS )
138 msStyle |= WS_CLIPSIBLINGS;
139
140 #ifdef __WIN32__
141 if(m_windowStyle & wxBU_LEFT)
142 msStyle |= BS_LEFT;
143 if(m_windowStyle & wxBU_RIGHT)
144 msStyle |= BS_RIGHT;
145 if(m_windowStyle & wxBU_TOP)
146 msStyle |= BS_TOP;
147 if(m_windowStyle & wxBU_BOTTOM)
148 msStyle |= BS_BOTTOM;
149 #endif
150
151 m_hWnd = (WXHWND) CreateWindowEx(
152 0,
153 wxT("BUTTON"),
154 wxEmptyString,
155 msStyle,
156 0, 0, 0, 0,
157 GetWinHwnd(parent),
158 (HMENU)m_windowId,
159 wxGetInstance(),
160 NULL
161 );
162
163 // Subclass again for purposes of dialog editing mode
164 SubclassWin(m_hWnd);
165
166 SetPosition(pos);
167 SetBestSize(size);
168
169 return true;
170 }
171
172 bool wxBitmapButton::SetBackgroundColour(const wxColour& colour)
173 {
174 if ( !wxBitmapButtonBase::SetBackgroundColour(colour) )
175 {
176 // didn't change
177 return false;
178 }
179
180 // invalidate the brush, it will be recreated the next time it's needed
181 m_brushDisabled = wxNullBrush;
182
183 return true;
184 }
185
186 void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent& event)
187 {
188 m_brushDisabled = wxNullBrush;
189
190 if ( !IsEnabled() )
191 {
192 // this change affects our current state
193 Refresh();
194 }
195
196 event.Skip();
197 }
198
199 void wxBitmapButton::OnMouseEnterOrLeave(wxMouseEvent& event)
200 {
201 if ( IsEnabled() && m_bmpHover.Ok() )
202 Refresh();
203
204 event.Skip();
205 }
206
207 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
208 #define FOCUS_MARGIN 3
209
210 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
211 {
212 #ifndef __WXWINCE__
213 long style = GetWindowLong((HWND) GetHWND(), GWL_STYLE);
214 if (style & BS_BITMAP)
215 {
216 // Let default procedure draw the bitmap, which is defined
217 // in the Windows resource.
218 return false;
219 }
220 #endif
221
222 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) item;
223 HDC hDC = lpDIS->hDC;
224 UINT state = lpDIS->itemState;
225 bool isSelected = (state & ODS_SELECTED) != 0;
226 bool autoDraw = (GetWindowStyleFlag() & wxBU_AUTODRAW) != 0;
227
228
229 // choose the bitmap to use depending on the button state
230 wxBitmap *bitmap;
231
232 if ( isSelected && m_bmpSelected.Ok() )
233 bitmap = &m_bmpSelected;
234 else if ( m_bmpHover.Ok() && IsMouseInWindow() )
235 bitmap = &m_bmpHover;
236 else if ((state & ODS_FOCUS) && m_bmpFocus.Ok())
237 bitmap = &m_bmpFocus;
238 else if ((state & ODS_DISABLED) && m_bmpDisabled.Ok())
239 bitmap = &m_bmpDisabled;
240 else
241 bitmap = &m_bmpNormal;
242
243 if ( !bitmap->Ok() )
244 return false;
245
246 // centre the bitmap in the control area
247 int x = lpDIS->rcItem.left;
248 int y = lpDIS->rcItem.top;
249 int width = lpDIS->rcItem.right - x;
250 int height = lpDIS->rcItem.bottom - y;
251 int wBmp = bitmap->GetWidth();
252 int hBmp = bitmap->GetHeight();
253
254 int x1,y1;
255
256 if(m_windowStyle & wxBU_LEFT)
257 x1 = x + (FOCUS_MARGIN+1);
258 else if(m_windowStyle & wxBU_RIGHT)
259 x1 = x + (width - wBmp) - (FOCUS_MARGIN+1);
260 else
261 x1 = x + (width - wBmp) / 2;
262
263 if(m_windowStyle & wxBU_TOP)
264 y1 = y + (FOCUS_MARGIN+1);
265 else if(m_windowStyle & wxBU_BOTTOM)
266 y1 = y + (height - hBmp) - (FOCUS_MARGIN+1);
267 else
268 y1 = y + (height - hBmp) / 2;
269
270 if ( isSelected && autoDraw )
271 {
272 x1++;
273 y1++;
274 }
275
276 // draw the face, if auto-drawing
277 if ( autoDraw )
278 {
279 DrawFace((WXHDC) hDC,
280 lpDIS->rcItem.left, lpDIS->rcItem.top,
281 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
282 isSelected);
283 }
284
285 // draw the bitmap
286 wxDC dst;
287 dst.SetHDC((WXHDC) hDC, false);
288 dst.DrawBitmap(*bitmap, x1, y1, true);
289
290 // draw focus / disabled state, if auto-drawing
291 if ( (state & ODS_DISABLED) && autoDraw )
292 {
293 DrawButtonDisable((WXHDC) hDC,
294 lpDIS->rcItem.left, lpDIS->rcItem.top,
295 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
296 true);
297 }
298 else if ( (state & ODS_FOCUS) && autoDraw )
299 {
300 DrawButtonFocus((WXHDC) hDC,
301 lpDIS->rcItem.left,
302 lpDIS->rcItem.top,
303 lpDIS->rcItem.right,
304 lpDIS->rcItem.bottom,
305 isSelected);
306 }
307
308 return true;
309 }
310
311 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
312
313 #if defined(__WIN95__)
314
315 void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
316 int right, int bottom, bool sel )
317 {
318 HPEN oldp;
319 HPEN penHiLight;
320 HPEN penLight;
321 HPEN penShadow;
322 HPEN penDkShadow;
323 HBRUSH brushFace;
324
325 // create needed pens and brush
326 penHiLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
327 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
328 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
329 penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
330 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
331 // Taking the background colour fits in better with
332 // Windows XP themes.
333 brushFace = CreateSolidBrush(m_backgroundColour.m_pixel);
334
335 // draw the rectangle
336 RECT rect;
337 rect.left = left;
338 rect.right = right;
339 rect.top = top;
340 rect.bottom = bottom;
341 FillRect((HDC) dc, &rect, brushFace);
342
343 // draw the border
344 oldp = (HPEN) SelectObject( (HDC) dc, sel? penDkShadow : penHiLight);
345
346 wxDrawLine((HDC) dc, left, top, right-1, top);
347 wxDrawLine((HDC) dc, left, top+1, left, bottom-1);
348
349 SelectObject( (HDC) dc, sel? penShadow : penLight);
350 wxDrawLine((HDC) dc, left+1, top+1, right-2, top+1);
351 wxDrawLine((HDC) dc, left+1, top+2, left+1, bottom-2);
352
353 SelectObject( (HDC) dc, sel? penLight : penShadow);
354 wxDrawLine((HDC) dc, left+1, bottom-2, right-1, bottom-2);
355 wxDrawLine((HDC) dc, right-2, bottom-3, right-2, top);
356
357 SelectObject( (HDC) dc, sel? penHiLight : penDkShadow);
358 wxDrawLine((HDC) dc, left, bottom-1, right+2, bottom-1);
359 wxDrawLine((HDC) dc, right-1, bottom-2, right-1, top-1);
360
361 // delete allocated resources
362 SelectObject((HDC) dc,oldp);
363 DeleteObject(penHiLight);
364 DeleteObject(penLight);
365 DeleteObject(penShadow);
366 DeleteObject(penDkShadow);
367 DeleteObject(brushFace);
368 }
369
370 #else
371
372 void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
373 int right, int bottom, bool sel )
374 {
375 HPEN oldp;
376 HPEN penBorder;
377 HPEN penLight;
378 HPEN penShadow;
379 HBRUSH brushFace;
380
381 // create needed pens and brush
382 penBorder = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOWFRAME));
383 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW));
384 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_BTNHIGHLIGHT));
385 brushFace = CreateSolidBrush(COLOR_BTNFACE);
386
387 // draw the rectangle
388 RECT rect;
389 rect.left = left;
390 rect.right = right;
391 rect.top = top;
392 rect.bottom = bottom;
393 FillRect((HDC) dc, &rect, brushFace);
394
395 // draw the border
396 oldp = (HPEN) SelectObject( (HDC) dc, penBorder);
397 MoveToEx((HDC) dc,left+1,top,NULL);LineTo((HDC) dc,right-1,top);
398 MoveToEx((HDC) dc,left,top+1,NULL);LineTo((HDC) dc,left,bottom-1);
399 MoveToEx((HDC) dc,left+1,bottom-1,NULL);LineTo((HDC) dc,right-1,bottom-1);
400 MoveToEx((HDC) dc,right-1,top+1,NULL);LineTo((HDC) dc,right-1,bottom-1);
401
402 SelectObject( (HDC) dc, penShadow);
403 if (sel)
404 {
405 MoveToEx((HDC) dc,left+1 ,bottom-2 ,NULL);
406 LineTo((HDC) dc, left+1 ,top+1);
407 LineTo((HDC) dc, right-2 ,top+1);
408 }
409 else
410 {
411 MoveToEx((HDC) dc,left+1 ,bottom-2 ,NULL);
412 LineTo((HDC) dc, right-2 ,bottom-2);
413 LineTo((HDC) dc, right-2 ,top);
414
415 MoveToEx((HDC) dc,left+2 ,bottom-3 ,NULL);
416 LineTo((HDC) dc, right-3 ,bottom-3);
417 LineTo((HDC) dc, right-3 ,top+1);
418
419 SelectObject( (HDC) dc, penLight);
420
421 MoveToEx((HDC) dc,left+1 ,bottom-2 ,NULL);
422 LineTo((HDC) dc, left+1 ,top+1);
423 LineTo((HDC) dc, right-2 ,top+1);
424 }
425
426 // delete allocated resources
427 SelectObject((HDC) dc,oldp);
428 DeleteObject(penBorder);
429 DeleteObject(penLight);
430 DeleteObject(penShadow);
431 DeleteObject(brushFace);
432 }
433
434 #endif // defined(__WIN95__)
435
436
437 void wxBitmapButton::DrawButtonFocus( WXHDC dc, int left, int top, int right,
438 int bottom, bool WXUNUSED(sel) )
439 {
440 RECT rect;
441 rect.left = left;
442 rect.top = top;
443 rect.right = right;
444 rect.bottom = bottom;
445 InflateRect( &rect, - FOCUS_MARGIN, - FOCUS_MARGIN );
446
447 // GRG: the focus rectangle should not move when the button is pushed!
448 /*
449 if ( sel )
450 OffsetRect( &rect, 1, 1 );
451 */
452
453 DrawFocusRect( (HDC) dc, &rect );
454 }
455
456 void
457 wxBitmapButton::DrawButtonDisable( WXHDC dc,
458 int left, int top, int right, int bottom,
459 bool with_marg )
460 {
461 if ( !m_brushDisabled.Ok() )
462 {
463 // draw a bitmap with two black and two background colour pixels
464 wxBitmap bmp(2, 2);
465 wxMemoryDC dc;
466 dc.SelectObject(bmp);
467 dc.SetPen(*wxBLACK_PEN);
468 dc.DrawPoint(0, 0);
469 dc.DrawPoint(1, 1);
470 dc.SetPen(GetBackgroundColour());
471 dc.DrawPoint(0, 1);
472 dc.DrawPoint(1, 0);
473
474 m_brushDisabled = wxBrush(bmp);
475 }
476
477 SelectInHDC selectBrush((HDC)dc, GetHbrushOf(m_brushDisabled));
478
479 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
480 // name, give it our own
481 static const DWORD PATTERNPAINT = 0xFA0089UL;
482
483 if ( with_marg )
484 {
485 left += m_marginX;
486 top += m_marginY;
487 right -= 2 * m_marginX;
488 bottom -= 2 * m_marginY;
489 }
490
491 ::PatBlt( (HDC) dc, left, top, right, bottom, PATTERNPAINT);
492 }
493
494 void wxBitmapButton::SetDefault()
495 {
496 wxButton::SetDefault();
497 }
498
499 wxSize wxBitmapButton::DoGetBestSize() const
500 {
501 if ( m_bmpNormal.Ok() )
502 {
503 wxSize best(m_bmpNormal.GetWidth() + 2*m_marginX,
504 m_bmpNormal.GetHeight() + 2*m_marginY);
505 CacheBestSize(best);
506 return best;
507 }
508
509 // no idea what our best size should be, defer to the base class
510 return wxBitmapButtonBase::DoGetBestSize();
511 }
512
513 #endif // wxUSE_BMPBUTTON
514