]>
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"
22 #include "wx/bmpbuttn.h"
24 #include "wx/dcmemory.h"
27 #include "wx/msw/private.h"
29 #include "wx/msw/uxtheme.h"
31 // ----------------------------------------------------------------------------
33 // ----------------------------------------------------------------------------
35 #if wxUSE_EXTENDED_RTTI
37 WX_DEFINE_FLAGS( wxBitmapButtonStyle
)
39 wxBEGIN_FLAGS( wxBitmapButtonStyle
)
40 // new style border flags, we put them first to
41 // use them for streaming out
42 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
43 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
44 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
45 wxFLAGS_MEMBER(wxBORDER_RAISED
)
46 wxFLAGS_MEMBER(wxBORDER_STATIC
)
47 wxFLAGS_MEMBER(wxBORDER_NONE
)
49 // old style border flags
50 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
51 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
52 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
53 wxFLAGS_MEMBER(wxRAISED_BORDER
)
54 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
55 wxFLAGS_MEMBER(wxBORDER
)
57 // standard window styles
58 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
59 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
60 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
61 wxFLAGS_MEMBER(wxWANTS_CHARS
)
62 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE
)
63 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
64 wxFLAGS_MEMBER(wxVSCROLL
)
65 wxFLAGS_MEMBER(wxHSCROLL
)
67 wxFLAGS_MEMBER(wxBU_AUTODRAW
)
68 wxFLAGS_MEMBER(wxBU_LEFT
)
69 wxFLAGS_MEMBER(wxBU_RIGHT
)
70 wxFLAGS_MEMBER(wxBU_TOP
)
71 wxFLAGS_MEMBER(wxBU_BOTTOM
)
72 wxEND_FLAGS( wxBitmapButtonStyle
)
74 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton
, wxButton
,"wx/bmpbuttn.h")
76 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton
)
77 wxPROPERTY_FLAGS( WindowStyle
, wxBitmapButtonStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, EMPTY_MACROVALUE
, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
78 wxEND_PROPERTIES_TABLE()
80 wxBEGIN_HANDLERS_TABLE(wxBitmapButton
)
81 wxEND_HANDLERS_TABLE()
83 wxCONSTRUCTOR_5( wxBitmapButton
, wxWindow
* , Parent
, wxWindowID
, Id
, wxBitmap
, Bitmap
, wxPoint
, Position
, wxSize
, Size
)
86 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton
, wxButton
)
89 BEGIN_EVENT_TABLE(wxBitmapButton
, wxBitmapButtonBase
)
90 EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged
)
91 EVT_ENTER_WINDOW(wxBitmapButton::OnMouseEnterOrLeave
)
92 EVT_LEAVE_WINDOW(wxBitmapButton::OnMouseEnterOrLeave
)
98 long "style" , wxBU_AUTODRAW
105 bool wxBitmapButton::Create(wxWindow
*parent
, wxWindowID id
,
106 const wxBitmap
& bitmap
,
108 const wxSize
& size
, long style
,
109 const wxValidator
& wxVALIDATOR_PARAM(validator
),
110 const wxString
& name
)
112 m_bmpNormal
= bitmap
;
116 SetValidator(validator
);
117 #endif // wxUSE_VALIDATORS
119 parent
->AddChild(this);
121 m_backgroundColour
= parent
->GetBackgroundColour();
122 m_foregroundColour
= parent
->GetForegroundColour();
123 m_windowStyle
= style
;
125 if ( style
& wxBU_AUTODRAW
)
132 m_windowId
= NewControlId();
136 long msStyle
= WS_VISIBLE
| WS_TABSTOP
| WS_CHILD
| BS_OWNERDRAW
;
138 if ( m_windowStyle
& wxCLIP_SIBLINGS
)
139 msStyle
|= WS_CLIPSIBLINGS
;
142 if(m_windowStyle
& wxBU_LEFT
)
144 if(m_windowStyle
& wxBU_RIGHT
)
146 if(m_windowStyle
& wxBU_TOP
)
148 if(m_windowStyle
& wxBU_BOTTOM
)
149 msStyle
|= BS_BOTTOM
;
152 m_hWnd
= (WXHWND
) CreateWindowEx(
164 // Subclass again for purposes of dialog editing mode
173 bool wxBitmapButton::SetBackgroundColour(const wxColour
& colour
)
175 if ( !wxBitmapButtonBase::SetBackgroundColour(colour
) )
181 // invalidate the brush, it will be recreated the next time it's needed
182 m_brushDisabled
= wxNullBrush
;
187 void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent
& event
)
189 m_brushDisabled
= wxNullBrush
;
193 // this change affects our current state
200 void wxBitmapButton::OnMouseEnterOrLeave(wxMouseEvent
& event
)
202 if ( IsEnabled() && m_bmpHover
.Ok() )
208 void wxBitmapButton::OnSetBitmap()
210 // if the focus bitmap is specified but hover one isn't, use the focus
211 // bitmap for hovering as well if this is consistent with the current
212 // Windows version look and feel
214 // rationale: this is compatible with the old wxGTK behaviour and also
215 // makes it much easier to do "the right thing" for all platforms (some of
216 // them, such as Windows XP, have "hot" buttons while others don't)
217 if ( !m_bmpHover
.Ok() &&
219 wxUxThemeEngine::GetIfActive() )
221 m_bmpHover
= m_bmpFocus
;
224 // this will redraw us
225 wxBitmapButtonBase::OnSetBitmap();
228 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
229 #define FOCUS_MARGIN 3
231 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT
*item
)
234 long style
= GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
235 if (style
& BS_BITMAP
)
237 // Let default procedure draw the bitmap, which is defined
238 // in the Windows resource.
243 LPDRAWITEMSTRUCT lpDIS
= (LPDRAWITEMSTRUCT
) item
;
244 HDC hDC
= lpDIS
->hDC
;
245 UINT state
= lpDIS
->itemState
;
246 bool isSelected
= (state
& ODS_SELECTED
) != 0;
247 bool autoDraw
= (GetWindowStyleFlag() & wxBU_AUTODRAW
) != 0;
250 // choose the bitmap to use depending on the button state
253 if ( isSelected
&& m_bmpSelected
.Ok() )
254 bitmap
= &m_bmpSelected
;
255 else if ( m_bmpHover
.Ok() && IsMouseInWindow() )
256 bitmap
= &m_bmpHover
;
257 else if ((state
& ODS_FOCUS
) && m_bmpFocus
.Ok())
258 bitmap
= &m_bmpFocus
;
259 else if ((state
& ODS_DISABLED
) && m_bmpDisabled
.Ok())
260 bitmap
= &m_bmpDisabled
;
262 bitmap
= &m_bmpNormal
;
267 // centre the bitmap in the control area
268 int x
= lpDIS
->rcItem
.left
;
269 int y
= lpDIS
->rcItem
.top
;
270 int width
= lpDIS
->rcItem
.right
- x
;
271 int height
= lpDIS
->rcItem
.bottom
- y
;
272 int wBmp
= bitmap
->GetWidth();
273 int hBmp
= bitmap
->GetHeight();
277 if(m_windowStyle
& wxBU_LEFT
)
278 x1
= x
+ (FOCUS_MARGIN
+1);
279 else if(m_windowStyle
& wxBU_RIGHT
)
280 x1
= x
+ (width
- wBmp
) - (FOCUS_MARGIN
+1);
282 x1
= x
+ (width
- wBmp
) / 2;
284 if(m_windowStyle
& wxBU_TOP
)
285 y1
= y
+ (FOCUS_MARGIN
+1);
286 else if(m_windowStyle
& wxBU_BOTTOM
)
287 y1
= y
+ (height
- hBmp
) - (FOCUS_MARGIN
+1);
289 y1
= y
+ (height
- hBmp
) / 2;
291 if ( isSelected
&& autoDraw
)
297 // draw the face, if auto-drawing
300 DrawFace((WXHDC
) hDC
,
301 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
302 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
307 wxDCTemp
dst((WXHDC
)hDC
);
308 dst
.DrawBitmap(*bitmap
, x1
, y1
, true);
310 // draw focus / disabled state, if auto-drawing
311 if ( (state
& ODS_DISABLED
) && autoDraw
)
313 DrawButtonDisable((WXHDC
) hDC
,
314 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
315 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
318 else if ( (state
& ODS_FOCUS
) && autoDraw
)
320 DrawButtonFocus((WXHDC
) hDC
,
324 lpDIS
->rcItem
.bottom
,
331 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
333 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
,
334 int right
, int bottom
, bool sel
)
343 // create needed pens and brush
344 penHiLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DHILIGHT
));
345 penLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DLIGHT
));
346 penShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DSHADOW
));
347 penDkShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DDKSHADOW
));
348 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
349 // Taking the background colour fits in better with
350 // Windows XP themes.
351 brushFace
= CreateSolidBrush(m_backgroundColour
.m_pixel
);
353 // draw the rectangle
358 rect
.bottom
= bottom
;
359 FillRect((HDC
) dc
, &rect
, brushFace
);
362 oldp
= (HPEN
) SelectObject( (HDC
) dc
, sel
? penDkShadow
: penHiLight
);
364 wxDrawLine((HDC
) dc
, left
, top
, right
-1, top
);
365 wxDrawLine((HDC
) dc
, left
, top
+1, left
, bottom
-1);
367 SelectObject( (HDC
) dc
, sel
? penShadow
: penLight
);
368 wxDrawLine((HDC
) dc
, left
+1, top
+1, right
-2, top
+1);
369 wxDrawLine((HDC
) dc
, left
+1, top
+2, left
+1, bottom
-2);
371 SelectObject( (HDC
) dc
, sel
? penLight
: penShadow
);
372 wxDrawLine((HDC
) dc
, left
+1, bottom
-2, right
-1, bottom
-2);
373 wxDrawLine((HDC
) dc
, right
-2, bottom
-3, right
-2, top
);
375 SelectObject( (HDC
) dc
, sel
? penHiLight
: penDkShadow
);
376 wxDrawLine((HDC
) dc
, left
, bottom
-1, right
+2, bottom
-1);
377 wxDrawLine((HDC
) dc
, right
-1, bottom
-2, right
-1, top
-1);
379 // delete allocated resources
380 SelectObject((HDC
) dc
,oldp
);
381 DeleteObject(penHiLight
);
382 DeleteObject(penLight
);
383 DeleteObject(penShadow
);
384 DeleteObject(penDkShadow
);
385 DeleteObject(brushFace
);
388 void wxBitmapButton::DrawButtonFocus( WXHDC dc
, int left
, int top
, int right
,
389 int bottom
, bool WXUNUSED(sel
) )
395 rect
.bottom
= bottom
;
396 InflateRect( &rect
, - FOCUS_MARGIN
, - FOCUS_MARGIN
);
398 // GRG: the focus rectangle should not move when the button is pushed!
401 OffsetRect( &rect, 1, 1 );
404 DrawFocusRect( (HDC
) dc
, &rect
);
408 wxBitmapButton::DrawButtonDisable( WXHDC dc
,
409 int left
, int top
, int right
, int bottom
,
412 if ( !m_brushDisabled
.Ok() )
414 // draw a bitmap with two black and two background colour pixels
417 dc
.SelectObject(bmp
);
418 dc
.SetPen(*wxBLACK_PEN
);
421 dc
.SetPen(GetBackgroundColour());
425 m_brushDisabled
= wxBrush(bmp
);
428 SelectInHDC
selectBrush((HDC
)dc
, GetHbrushOf(m_brushDisabled
));
430 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
431 // name, give it our own
432 static const DWORD PATTERNPAINT
= 0xFA0089UL
;
438 right
-= 2 * m_marginX
;
439 bottom
-= 2 * m_marginY
;
442 ::PatBlt( (HDC
) dc
, left
, top
, right
, bottom
, PATTERNPAINT
);
445 void wxBitmapButton::SetDefault()
447 wxButton::SetDefault();
450 wxSize
wxBitmapButton::DoGetBestSize() const
452 if ( m_bmpNormal
.Ok() )
454 wxSize
best(m_bmpNormal
.GetWidth() + 2*m_marginX
,
455 m_bmpNormal
.GetHeight() + 2*m_marginY
);
460 // no idea what our best size should be, defer to the base class
461 return wxBitmapButtonBase::DoGetBestSize();
464 #endif // wxUSE_BMPBUTTON