]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/bmpbuttn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/bmpbuttn.cpp
3 // Purpose: wxBitmapButton
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "bmpbuttn.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
26 #include "wx/bmpbuttn.h"
28 #include "wx/dcmemory.h"
31 #include "wx/msw/private.h"
34 // ----------------------------------------------------------------------------
36 // ----------------------------------------------------------------------------
38 #if wxUSE_EXTENDED_RTTI
40 WX_DEFINE_FLAGS( wxBitmapButtonStyle
)
42 wxBEGIN_FLAGS( wxBitmapButtonStyle
)
43 // new style border flags, we put them first to
44 // use them for streaming out
45 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
46 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
47 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
48 wxFLAGS_MEMBER(wxBORDER_RAISED
)
49 wxFLAGS_MEMBER(wxBORDER_STATIC
)
50 wxFLAGS_MEMBER(wxBORDER_NONE
)
52 // old style border flags
53 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
54 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
55 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
56 wxFLAGS_MEMBER(wxRAISED_BORDER
)
57 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
58 wxFLAGS_MEMBER(wxBORDER
)
60 // standard window styles
61 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
62 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
63 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
64 wxFLAGS_MEMBER(wxWANTS_CHARS
)
65 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
66 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
67 wxFLAGS_MEMBER(wxVSCROLL
)
68 wxFLAGS_MEMBER(wxHSCROLL
)
70 wxFLAGS_MEMBER(wxBU_AUTODRAW
)
71 wxFLAGS_MEMBER(wxBU_LEFT
)
72 wxFLAGS_MEMBER(wxBU_RIGHT
)
73 wxFLAGS_MEMBER(wxBU_TOP
)
74 wxFLAGS_MEMBER(wxBU_BOTTOM
)
75 wxEND_FLAGS( wxBitmapButtonStyle
)
77 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton
, wxButton
,"wx/bmpbuttn.h")
79 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton
)
80 wxPROPERTY_FLAGS( WindowStyle
, wxBitmapButtonStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
81 wxEND_PROPERTIES_TABLE()
83 wxBEGIN_HANDLERS_TABLE(wxBitmapButton
)
84 wxEND_HANDLERS_TABLE()
86 wxCONSTRUCTOR_5( wxBitmapButton
, wxWindow
* , Parent
, wxWindowID
, Id
, wxBitmap
, Bitmap
, wxPoint
, Position
, wxSize
, Size
)
89 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton
, wxButton
)
92 BEGIN_EVENT_TABLE(wxBitmapButton
, wxBitmapButtonBase
)
93 EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged
)
99 long "style" , wxBU_AUTODRAW
106 #define BUTTON_HEIGHT_FACTOR (EDIT_CONTROL_FACTOR * 1.1)
108 bool wxBitmapButton::Create(wxWindow
*parent
, wxWindowID id
,
109 const wxBitmap
& bitmap
,
111 const wxSize
& size
, long style
,
112 const wxValidator
& wxVALIDATOR_PARAM(validator
),
113 const wxString
& name
)
115 m_bmpNormal
= bitmap
;
119 SetValidator(validator
);
120 #endif // wxUSE_VALIDATORS
122 parent
->AddChild(this);
124 m_backgroundColour
= parent
->GetBackgroundColour();
125 m_foregroundColour
= parent
->GetForegroundColour();
126 m_windowStyle
= style
;
128 if ( style
& wxBU_AUTODRAW
)
130 m_marginX
= wxDEFAULT_BUTTON_MARGIN
;
131 m_marginY
= wxDEFAULT_BUTTON_MARGIN
;
135 m_windowId
= NewControlId();
139 long msStyle
= WS_VISIBLE
| WS_TABSTOP
| WS_CHILD
| BS_OWNERDRAW
;
141 if ( m_windowStyle
& wxCLIP_SIBLINGS
)
142 msStyle
|= WS_CLIPSIBLINGS
;
145 if(m_windowStyle
& wxBU_LEFT
)
147 if(m_windowStyle
& wxBU_RIGHT
)
149 if(m_windowStyle
& wxBU_TOP
)
151 if(m_windowStyle
& wxBU_BOTTOM
)
152 msStyle
|= BS_BOTTOM
;
155 m_hWnd
= (WXHWND
) CreateWindowEx(
167 // Subclass again for purposes of dialog editing mode
176 bool wxBitmapButton::SetBackgroundColour(const wxColour
& colour
)
178 if ( !wxBitmapButtonBase::SetBackgroundColour(colour
) )
184 // invalidate the brush, it will be recreated the next time it's needed
185 m_brushDisabled
= wxNullBrush
;
190 void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent
& event
)
192 m_brushDisabled
= wxNullBrush
;
196 // this change affects our current state
203 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
204 #define FOCUS_MARGIN 3
206 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT
*item
)
209 long style
= GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
210 if (style
& BS_BITMAP
)
212 // Let default procedure draw the bitmap, which is defined
213 // in the Windows resource.
218 LPDRAWITEMSTRUCT lpDIS
= (LPDRAWITEMSTRUCT
) item
;
219 HDC hDC
= lpDIS
->hDC
;
220 UINT state
= lpDIS
->itemState
;
221 bool isSelected
= (state
& ODS_SELECTED
) != 0;
222 bool autoDraw
= (GetWindowStyleFlag() & wxBU_AUTODRAW
) != 0;
225 // choose the bitmap to use depending on the button state
228 if ( isSelected
&& m_bmpSelected
.Ok() )
229 bitmap
= &m_bmpSelected
;
230 else if ((state
& ODS_FOCUS
) && m_bmpFocus
.Ok())
231 bitmap
= &m_bmpFocus
;
232 else if ((state
& ODS_DISABLED
) && m_bmpDisabled
.Ok())
233 bitmap
= &m_bmpDisabled
;
235 bitmap
= &m_bmpNormal
;
240 // centre the bitmap in the control area
241 int x
= lpDIS
->rcItem
.left
;
242 int y
= lpDIS
->rcItem
.top
;
243 int width
= lpDIS
->rcItem
.right
- x
;
244 int height
= lpDIS
->rcItem
.bottom
- y
;
245 int wBmp
= bitmap
->GetWidth();
246 int hBmp
= bitmap
->GetHeight();
250 if(m_windowStyle
& wxBU_LEFT
)
251 x1
= x
+ (FOCUS_MARGIN
+1);
252 else if(m_windowStyle
& wxBU_RIGHT
)
253 x1
= x
+ (width
- wBmp
) - (FOCUS_MARGIN
+1);
255 x1
= x
+ (width
- wBmp
) / 2;
257 if(m_windowStyle
& wxBU_TOP
)
258 y1
= y
+ (FOCUS_MARGIN
+1);
259 else if(m_windowStyle
& wxBU_BOTTOM
)
260 y1
= y
+ (height
- hBmp
) - (FOCUS_MARGIN
+1);
262 y1
= y
+ (height
- hBmp
) / 2;
264 if ( isSelected
&& autoDraw
)
270 // draw the face, if auto-drawing
273 DrawFace((WXHDC
) hDC
,
274 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
275 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
281 dst
.SetHDC((WXHDC
) hDC
, false);
282 dst
.DrawBitmap(*bitmap
, x1
, y1
, true);
284 // draw focus / disabled state, if auto-drawing
285 if ( (state
& ODS_DISABLED
) && autoDraw
)
287 DrawButtonDisable((WXHDC
) hDC
,
288 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
289 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
292 else if ( (state
& ODS_FOCUS
) && autoDraw
)
294 DrawButtonFocus((WXHDC
) hDC
,
298 lpDIS
->rcItem
.bottom
,
305 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
307 #if defined(__WIN95__)
309 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
,
310 int right
, int bottom
, bool sel
)
319 // create needed pens and brush
320 penHiLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DHILIGHT
));
321 penLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DLIGHT
));
322 penShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DSHADOW
));
323 penDkShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DDKSHADOW
));
324 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
325 // Taking the background colour fits in better with
326 // Windows XP themes.
327 brushFace
= CreateSolidBrush(m_backgroundColour
.m_pixel
);
329 // draw the rectangle
334 rect
.bottom
= bottom
;
335 FillRect((HDC
) dc
, &rect
, brushFace
);
338 oldp
= (HPEN
) SelectObject( (HDC
) dc
, sel
? penDkShadow
: penHiLight
);
340 wxDrawLine((HDC
) dc
, left
, top
, right
-1, top
);
341 wxDrawLine((HDC
) dc
, left
, top
+1, left
, bottom
-1);
343 SelectObject( (HDC
) dc
, sel
? penShadow
: penLight
);
344 wxDrawLine((HDC
) dc
, left
+1, top
+1, right
-2, top
+1);
345 wxDrawLine((HDC
) dc
, left
+1, top
+2, left
+1, bottom
-2);
347 SelectObject( (HDC
) dc
, sel
? penLight
: penShadow
);
348 wxDrawLine((HDC
) dc
, left
+1, bottom
-2, right
-1, bottom
-2);
349 wxDrawLine((HDC
) dc
, right
-2, bottom
-3, right
-2, top
);
351 SelectObject( (HDC
) dc
, sel
? penHiLight
: penDkShadow
);
352 wxDrawLine((HDC
) dc
, left
, bottom
-1, right
+2, bottom
-1);
353 wxDrawLine((HDC
) dc
, right
-1, bottom
-2, right
-1, top
-1);
355 // delete allocated resources
356 SelectObject((HDC
) dc
,oldp
);
357 DeleteObject(penHiLight
);
358 DeleteObject(penLight
);
359 DeleteObject(penShadow
);
360 DeleteObject(penDkShadow
);
361 DeleteObject(brushFace
);
366 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
,
367 int right
, int bottom
, bool sel
)
375 // create needed pens and brush
376 penBorder
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_WINDOWFRAME
));
377 penShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_BTNSHADOW
));
378 penLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_BTNHIGHLIGHT
));
379 brushFace
= CreateSolidBrush(COLOR_BTNFACE
);
381 // draw the rectangle
386 rect
.bottom
= bottom
;
387 FillRect((HDC
) dc
, &rect
, brushFace
);
390 oldp
= (HPEN
) SelectObject( (HDC
) dc
, penBorder
);
391 MoveToEx((HDC
) dc
,left
+1,top
,NULL
);LineTo((HDC
) dc
,right
-1,top
);
392 MoveToEx((HDC
) dc
,left
,top
+1,NULL
);LineTo((HDC
) dc
,left
,bottom
-1);
393 MoveToEx((HDC
) dc
,left
+1,bottom
-1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1);
394 MoveToEx((HDC
) dc
,right
-1,top
+1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1);
396 SelectObject( (HDC
) dc
, penShadow
);
399 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
);
400 LineTo((HDC
) dc
, left
+1 ,top
+1);
401 LineTo((HDC
) dc
, right
-2 ,top
+1);
405 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
);
406 LineTo((HDC
) dc
, right
-2 ,bottom
-2);
407 LineTo((HDC
) dc
, right
-2 ,top
);
409 MoveToEx((HDC
) dc
,left
+2 ,bottom
-3 ,NULL
);
410 LineTo((HDC
) dc
, right
-3 ,bottom
-3);
411 LineTo((HDC
) dc
, right
-3 ,top
+1);
413 SelectObject( (HDC
) dc
, penLight
);
415 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
);
416 LineTo((HDC
) dc
, left
+1 ,top
+1);
417 LineTo((HDC
) dc
, right
-2 ,top
+1);
420 // delete allocated resources
421 SelectObject((HDC
) dc
,oldp
);
422 DeleteObject(penBorder
);
423 DeleteObject(penLight
);
424 DeleteObject(penShadow
);
425 DeleteObject(brushFace
);
428 #endif // defined(__WIN95__)
431 void wxBitmapButton::DrawButtonFocus( WXHDC dc
, int left
, int top
, int right
,
432 int bottom
, bool WXUNUSED(sel
) )
438 rect
.bottom
= bottom
;
439 InflateRect( &rect
, - FOCUS_MARGIN
, - FOCUS_MARGIN
);
441 // GRG: the focus rectangle should not move when the button is pushed!
444 OffsetRect( &rect, 1, 1 );
447 DrawFocusRect( (HDC
) dc
, &rect
);
451 wxBitmapButton::DrawButtonDisable( WXHDC dc
,
452 int left
, int top
, int right
, int bottom
,
455 if ( !m_brushDisabled
.Ok() )
457 // draw a bitmap with two black and two background colour pixels
460 dc
.SelectObject(bmp
);
461 dc
.SetPen(*wxBLACK_PEN
);
464 dc
.SetPen(GetBackgroundColour());
468 m_brushDisabled
= wxBrush(bmp
);
471 SelectInHDC
selectBrush((HDC
)dc
, GetHbrushOf(m_brushDisabled
));
473 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
474 // name, give it our own
475 static const DWORD PATTERNPAINT
= 0xFA0089UL
;
481 right
-= 2 * m_marginX
;
482 bottom
-= 2 * m_marginY
;
485 ::PatBlt( (HDC
) dc
, left
, top
, right
, bottom
, PATTERNPAINT
);
488 void wxBitmapButton::SetDefault()
490 wxButton::SetDefault();
493 wxSize
wxBitmapButton::DoGetBestSize() const
495 if ( m_bmpNormal
.Ok() )
497 return wxSize(m_bmpNormal
.GetWidth() + 2*m_marginX
,
498 m_bmpNormal
.GetHeight() + 2*m_marginY
);
501 // no idea what our best size should be, defer to the base class
502 return wxBitmapButtonBase::DoGetBestSize();
505 #endif // wxUSE_BMPBUTTON