]>
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 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
21 #include "wx/bmpbuttn.h"
25 #include "wx/dcmemory.h"
28 #include "wx/msw/private.h"
30 #include "wx/msw/uxtheme.h"
32 // ----------------------------------------------------------------------------
34 // ----------------------------------------------------------------------------
36 #if wxUSE_EXTENDED_RTTI
38 WX_DEFINE_FLAGS( wxBitmapButtonStyle
)
40 wxBEGIN_FLAGS( wxBitmapButtonStyle
)
41 // new style border flags, we put them first to
42 // use them for streaming out
43 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
44 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
45 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
46 wxFLAGS_MEMBER(wxBORDER_RAISED
)
47 wxFLAGS_MEMBER(wxBORDER_STATIC
)
48 wxFLAGS_MEMBER(wxBORDER_NONE
)
50 // old style border flags
51 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
52 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
53 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
54 wxFLAGS_MEMBER(wxRAISED_BORDER
)
55 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
56 wxFLAGS_MEMBER(wxBORDER
)
58 // standard window styles
59 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
60 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
61 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
62 wxFLAGS_MEMBER(wxWANTS_CHARS
)
63 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
64 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
65 wxFLAGS_MEMBER(wxVSCROLL
)
66 wxFLAGS_MEMBER(wxHSCROLL
)
68 wxFLAGS_MEMBER(wxBU_AUTODRAW
)
69 wxFLAGS_MEMBER(wxBU_LEFT
)
70 wxFLAGS_MEMBER(wxBU_RIGHT
)
71 wxFLAGS_MEMBER(wxBU_TOP
)
72 wxFLAGS_MEMBER(wxBU_BOTTOM
)
73 wxEND_FLAGS( wxBitmapButtonStyle
)
75 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton
, wxButton
,"wx/bmpbuttn.h")
77 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton
)
78 wxPROPERTY_FLAGS( WindowStyle
, wxBitmapButtonStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
79 wxEND_PROPERTIES_TABLE()
81 wxBEGIN_HANDLERS_TABLE(wxBitmapButton
)
82 wxEND_HANDLERS_TABLE()
84 wxCONSTRUCTOR_5( wxBitmapButton
, wxWindow
* , Parent
, wxWindowID
, Id
, wxBitmap
, Bitmap
, wxPoint
, Position
, wxSize
, Size
)
87 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton
, wxButton
)
90 BEGIN_EVENT_TABLE(wxBitmapButton
, wxBitmapButtonBase
)
91 EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged
)
92 EVT_ENTER_WINDOW(wxBitmapButton::OnMouseEnterOrLeave
)
93 EVT_LEAVE_WINDOW(wxBitmapButton::OnMouseEnterOrLeave
)
99 long "style" , wxBU_AUTODRAW
106 bool wxBitmapButton::Create(wxWindow
*parent
, wxWindowID id
,
107 const wxBitmap
& bitmap
,
109 const wxSize
& size
, long style
,
110 const wxValidator
& wxVALIDATOR_PARAM(validator
),
111 const wxString
& name
)
113 m_bmpNormal
= bitmap
;
117 SetValidator(validator
);
118 #endif // wxUSE_VALIDATORS
120 parent
->AddChild(this);
122 m_backgroundColour
= parent
->GetBackgroundColour();
123 m_foregroundColour
= parent
->GetForegroundColour();
124 m_windowStyle
= style
;
126 if ( style
& wxBU_AUTODRAW
)
133 m_windowId
= NewControlId();
137 long msStyle
= WS_VISIBLE
| WS_TABSTOP
| WS_CHILD
| BS_OWNERDRAW
;
139 if ( m_windowStyle
& wxCLIP_SIBLINGS
)
140 msStyle
|= WS_CLIPSIBLINGS
;
143 if(m_windowStyle
& wxBU_LEFT
)
145 if(m_windowStyle
& wxBU_RIGHT
)
147 if(m_windowStyle
& wxBU_TOP
)
149 if(m_windowStyle
& wxBU_BOTTOM
)
150 msStyle
|= BS_BOTTOM
;
153 m_hWnd
= (WXHWND
) CreateWindowEx(
165 // Subclass again for purposes of dialog editing mode
174 bool wxBitmapButton::SetBackgroundColour(const wxColour
& colour
)
176 if ( !wxBitmapButtonBase::SetBackgroundColour(colour
) )
182 // invalidate the brush, it will be recreated the next time it's needed
183 m_brushDisabled
= wxNullBrush
;
188 void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent
& event
)
190 m_brushDisabled
= wxNullBrush
;
194 // this change affects our current state
201 void wxBitmapButton::OnMouseEnterOrLeave(wxMouseEvent
& event
)
203 if ( IsEnabled() && m_bmpHover
.Ok() )
209 void wxBitmapButton::OnSetBitmap()
211 // if the focus bitmap is specified but hover one isn't, use the focus
212 // bitmap for hovering as well if this is consistent with the current
213 // Windows version look and feel
215 // rationale: this is compatible with the old wxGTK behaviour and also
216 // makes it much easier to do "the right thing" for all platforms (some of
217 // them, such as Windows XP, have "hot" buttons while others don't)
218 if ( !m_bmpHover
.Ok() &&
220 wxUxThemeEngine::GetIfActive() )
222 m_bmpHover
= m_bmpFocus
;
225 // this will redraw us
226 wxBitmapButtonBase::OnSetBitmap();
229 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
230 #define FOCUS_MARGIN 3
232 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT
*item
)
235 long style
= GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
236 if (style
& BS_BITMAP
)
238 // Let default procedure draw the bitmap, which is defined
239 // in the Windows resource.
244 LPDRAWITEMSTRUCT lpDIS
= (LPDRAWITEMSTRUCT
) item
;
245 HDC hDC
= lpDIS
->hDC
;
246 UINT state
= lpDIS
->itemState
;
247 bool isSelected
= (state
& ODS_SELECTED
) != 0;
248 bool autoDraw
= (GetWindowStyleFlag() & wxBU_AUTODRAW
) != 0;
251 // choose the bitmap to use depending on the button state
254 if ( isSelected
&& m_bmpSelected
.Ok() )
255 bitmap
= &m_bmpSelected
;
256 else if ( m_bmpHover
.Ok() && IsMouseInWindow() )
257 bitmap
= &m_bmpHover
;
258 else if ((state
& ODS_FOCUS
) && m_bmpFocus
.Ok())
259 bitmap
= &m_bmpFocus
;
260 else if ((state
& ODS_DISABLED
) && m_bmpDisabled
.Ok())
261 bitmap
= &m_bmpDisabled
;
263 bitmap
= &m_bmpNormal
;
268 // centre the bitmap in the control area
269 int x
= lpDIS
->rcItem
.left
;
270 int y
= lpDIS
->rcItem
.top
;
271 int width
= lpDIS
->rcItem
.right
- x
;
272 int height
= lpDIS
->rcItem
.bottom
- y
;
273 int wBmp
= bitmap
->GetWidth();
274 int hBmp
= bitmap
->GetHeight();
278 if(m_windowStyle
& wxBU_LEFT
)
279 x1
= x
+ (FOCUS_MARGIN
+1);
280 else if(m_windowStyle
& wxBU_RIGHT
)
281 x1
= x
+ (width
- wBmp
) - (FOCUS_MARGIN
+1);
283 x1
= x
+ (width
- wBmp
) / 2;
285 if(m_windowStyle
& wxBU_TOP
)
286 y1
= y
+ (FOCUS_MARGIN
+1);
287 else if(m_windowStyle
& wxBU_BOTTOM
)
288 y1
= y
+ (height
- hBmp
) - (FOCUS_MARGIN
+1);
290 y1
= y
+ (height
- hBmp
) / 2;
292 if ( isSelected
&& autoDraw
)
298 // draw the face, if auto-drawing
301 DrawFace((WXHDC
) hDC
,
302 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
303 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
308 wxDCTemp
dst((WXHDC
)hDC
);
309 dst
.DrawBitmap(*bitmap
, x1
, y1
, true);
311 // draw focus / disabled state, if auto-drawing
312 if ( (state
& ODS_DISABLED
) && autoDraw
)
314 DrawButtonDisable((WXHDC
) hDC
,
315 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
316 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
319 else if ( (state
& ODS_FOCUS
) && autoDraw
)
321 DrawButtonFocus((WXHDC
) hDC
,
325 lpDIS
->rcItem
.bottom
,
332 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
334 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
,
335 int right
, int bottom
, bool sel
)
344 // create needed pens and brush
345 penHiLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DHILIGHT
));
346 penLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DLIGHT
));
347 penShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DSHADOW
));
348 penDkShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DDKSHADOW
));
349 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
350 // Taking the background colour fits in better with
351 // Windows XP themes.
352 brushFace
= CreateSolidBrush(m_backgroundColour
.m_pixel
);
354 // draw the rectangle
359 rect
.bottom
= bottom
;
360 FillRect((HDC
) dc
, &rect
, brushFace
);
363 oldp
= (HPEN
) SelectObject( (HDC
) dc
, sel
? penDkShadow
: penHiLight
);
365 wxDrawLine((HDC
) dc
, left
, top
, right
-1, top
);
366 wxDrawLine((HDC
) dc
, left
, top
+1, left
, bottom
-1);
368 SelectObject( (HDC
) dc
, sel
? penShadow
: penLight
);
369 wxDrawLine((HDC
) dc
, left
+1, top
+1, right
-2, top
+1);
370 wxDrawLine((HDC
) dc
, left
+1, top
+2, left
+1, bottom
-2);
372 SelectObject( (HDC
) dc
, sel
? penLight
: penShadow
);
373 wxDrawLine((HDC
) dc
, left
+1, bottom
-2, right
-1, bottom
-2);
374 wxDrawLine((HDC
) dc
, right
-2, bottom
-3, right
-2, top
);
376 SelectObject( (HDC
) dc
, sel
? penHiLight
: penDkShadow
);
377 wxDrawLine((HDC
) dc
, left
, bottom
-1, right
+2, bottom
-1);
378 wxDrawLine((HDC
) dc
, right
-1, bottom
-2, right
-1, top
-1);
380 // delete allocated resources
381 SelectObject((HDC
) dc
,oldp
);
382 DeleteObject(penHiLight
);
383 DeleteObject(penLight
);
384 DeleteObject(penShadow
);
385 DeleteObject(penDkShadow
);
386 DeleteObject(brushFace
);
389 void wxBitmapButton::DrawButtonFocus( WXHDC dc
, int left
, int top
, int right
,
390 int bottom
, bool WXUNUSED(sel
) )
396 rect
.bottom
= bottom
;
397 InflateRect( &rect
, - FOCUS_MARGIN
, - FOCUS_MARGIN
);
399 // GRG: the focus rectangle should not move when the button is pushed!
402 OffsetRect( &rect, 1, 1 );
405 DrawFocusRect( (HDC
) dc
, &rect
);
409 wxBitmapButton::DrawButtonDisable( WXHDC dc
,
410 int left
, int top
, int right
, int bottom
,
413 if ( !m_brushDisabled
.Ok() )
415 // draw a bitmap with two black and two background colour pixels
418 dc
.SelectObject(bmp
);
419 dc
.SetPen(*wxBLACK_PEN
);
422 dc
.SetPen(GetBackgroundColour());
426 m_brushDisabled
= wxBrush(bmp
);
429 SelectInHDC
selectBrush((HDC
)dc
, GetHbrushOf(m_brushDisabled
));
431 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
432 // name, give it our own
433 static const DWORD PATTERNPAINT
= 0xFA0089UL
;
439 right
-= 2 * m_marginX
;
440 bottom
-= 2 * m_marginY
;
443 ::PatBlt( (HDC
) dc
, left
, top
, right
, bottom
, PATTERNPAINT
);
446 void wxBitmapButton::SetDefault()
448 wxButton::SetDefault();
451 wxSize
wxBitmapButton::DoGetBestSize() const
453 if ( m_bmpNormal
.Ok() )
455 wxSize
best(m_bmpNormal
.GetWidth() + 2*m_marginX
,
456 m_bmpNormal
.GetHeight() + 2*m_marginY
);
461 // no idea what our best size should be, defer to the base class
462 return wxBitmapButtonBase::DoGetBestSize();
465 #endif // wxUSE_BMPBUTTON