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"
33 // ----------------------------------------------------------------------------
35 // ----------------------------------------------------------------------------
37 #if wxUSE_EXTENDED_RTTI
39 WX_DEFINE_FLAGS( wxBitmapButtonStyle
)
41 wxBEGIN_FLAGS( wxBitmapButtonStyle
)
42 // new style border flags, we put them first to
43 // use them for streaming out
44 wxFLAGS_MEMBER(wxBORDER_SIMPLE
)
45 wxFLAGS_MEMBER(wxBORDER_SUNKEN
)
46 wxFLAGS_MEMBER(wxBORDER_DOUBLE
)
47 wxFLAGS_MEMBER(wxBORDER_RAISED
)
48 wxFLAGS_MEMBER(wxBORDER_STATIC
)
49 wxFLAGS_MEMBER(wxBORDER_NONE
)
51 // old style border flags
52 wxFLAGS_MEMBER(wxSIMPLE_BORDER
)
53 wxFLAGS_MEMBER(wxSUNKEN_BORDER
)
54 wxFLAGS_MEMBER(wxDOUBLE_BORDER
)
55 wxFLAGS_MEMBER(wxRAISED_BORDER
)
56 wxFLAGS_MEMBER(wxSTATIC_BORDER
)
57 wxFLAGS_MEMBER(wxNO_BORDER
)
59 // standard window styles
60 wxFLAGS_MEMBER(wxTAB_TRAVERSAL
)
61 wxFLAGS_MEMBER(wxCLIP_CHILDREN
)
62 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW
)
63 wxFLAGS_MEMBER(wxWANTS_CHARS
)
64 wxFLAGS_MEMBER(wxNO_FULL_REPAINT_ON_RESIZE
)
65 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB
)
66 wxFLAGS_MEMBER(wxVSCROLL
)
67 wxFLAGS_MEMBER(wxHSCROLL
)
69 wxFLAGS_MEMBER(wxBU_AUTODRAW
)
70 wxFLAGS_MEMBER(wxBU_LEFT
)
71 wxFLAGS_MEMBER(wxBU_RIGHT
)
72 wxFLAGS_MEMBER(wxBU_TOP
)
73 wxFLAGS_MEMBER(wxBU_BOTTOM
)
74 wxEND_FLAGS( wxBitmapButtonStyle
)
76 IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton
, wxButton
,"wx/bmpbuttn.h")
78 wxBEGIN_PROPERTIES_TABLE(wxBitmapButton
)
79 wxPROPERTY_FLAGS( WindowStyle
, wxBitmapButtonStyle
, long , SetWindowStyleFlag
, GetWindowStyleFlag
, , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
80 wxEND_PROPERTIES_TABLE()
82 wxBEGIN_HANDLERS_TABLE(wxBitmapButton
)
83 wxEND_HANDLERS_TABLE()
85 wxCONSTRUCTOR_5( wxBitmapButton
, wxWindow
* , Parent
, wxWindowID
, Id
, wxBitmap
, Bitmap
, wxPoint
, Position
, wxSize
, Size
)
88 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton
, wxButton
)
94 long "style" , wxBU_AUTODRAW
101 #define BUTTON_HEIGHT_FACTOR (EDIT_CONTROL_FACTOR * 1.1)
103 bool wxBitmapButton::Create(wxWindow
*parent
, wxWindowID id
, const wxBitmap
& bitmap
,
105 const wxSize
& size
, long style
,
106 const wxValidator
& validator
,
107 const wxString
& name
)
109 m_bmpNormal
= bitmap
;
113 SetValidator(validator
);
114 #endif // wxUSE_VALIDATORS
116 parent
->AddChild(this);
118 m_backgroundColour
= parent
->GetBackgroundColour();
119 m_foregroundColour
= parent
->GetForegroundColour();
120 m_windowStyle
= style
;
122 if ( style
& wxBU_AUTODRAW
)
124 m_marginX
= wxDEFAULT_BUTTON_MARGIN
;
125 m_marginY
= wxDEFAULT_BUTTON_MARGIN
;
134 m_windowId
= NewControlId();
138 if ( width
== -1 && bitmap
.Ok())
139 width
= bitmap
.GetWidth() + 2*m_marginX
;
141 if ( height
== -1 && bitmap
.Ok())
142 height
= bitmap
.GetHeight() + 2*m_marginY
;
144 long msStyle
= WS_VISIBLE
| WS_TABSTOP
| WS_CHILD
| BS_OWNERDRAW
;
146 if ( m_windowStyle
& wxCLIP_SIBLINGS
)
147 msStyle
|= WS_CLIPSIBLINGS
;
150 if(m_windowStyle
& wxBU_LEFT
)
152 if(m_windowStyle
& wxBU_RIGHT
)
154 if(m_windowStyle
& wxBU_TOP
)
156 if(m_windowStyle
& wxBU_BOTTOM
)
157 msStyle
|= BS_BOTTOM
;
160 m_hWnd
= (WXHWND
)CreateWindowEx
173 // Subclass again for purposes of dialog editing mode
176 SetFont(parent
->GetFont());
178 SetSize(x
, y
, width
, height
);
183 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
184 #define FOCUS_MARGIN 3
186 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT
*item
)
189 long style
= GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
190 if (style
& BS_BITMAP
)
192 // Let default procedure draw the bitmap, which is defined
193 // in the Windows resource.
198 LPDRAWITEMSTRUCT lpDIS
= (LPDRAWITEMSTRUCT
) item
;
199 HDC hDC
= lpDIS
->hDC
;
200 UINT state
= lpDIS
->itemState
;
201 bool isSelected
= (state
& ODS_SELECTED
) != 0;
202 bool autoDraw
= (GetWindowStyleFlag() & wxBU_AUTODRAW
) != 0;
205 // choose the bitmap to use depending on the button state
208 if ( isSelected
&& m_bmpSelected
.Ok() )
209 bitmap
= &m_bmpSelected
;
210 else if ((state
& ODS_FOCUS
) && m_bmpFocus
.Ok())
211 bitmap
= &m_bmpFocus
;
212 else if ((state
& ODS_DISABLED
) && m_bmpDisabled
.Ok())
213 bitmap
= &m_bmpDisabled
;
215 bitmap
= &m_bmpNormal
;
220 // centre the bitmap in the control area
221 int x
= lpDIS
->rcItem
.left
;
222 int y
= lpDIS
->rcItem
.top
;
223 int width
= lpDIS
->rcItem
.right
- x
;
224 int height
= lpDIS
->rcItem
.bottom
- y
;
225 int wBmp
= bitmap
->GetWidth();
226 int hBmp
= bitmap
->GetHeight();
230 if(m_windowStyle
& wxBU_LEFT
)
231 x1
= x
+ (FOCUS_MARGIN
+1);
232 else if(m_windowStyle
& wxBU_RIGHT
)
233 x1
= x
+ (width
- wBmp
) - (FOCUS_MARGIN
+1);
235 x1
= x
+ (width
- wBmp
) / 2;
237 if(m_windowStyle
& wxBU_TOP
)
238 y1
= y
+ (FOCUS_MARGIN
+1);
239 else if(m_windowStyle
& wxBU_BOTTOM
)
240 y1
= y
+ (height
- hBmp
) - (FOCUS_MARGIN
+1);
242 y1
= y
+ (height
- hBmp
) / 2;
244 if ( isSelected
&& autoDraw
)
250 // draw the face, if auto-drawing
253 DrawFace((WXHDC
) hDC
,
254 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
255 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
261 dst
.SetHDC((WXHDC
) hDC
, FALSE
);
262 dst
.DrawBitmap(*bitmap
, x1
, y1
, TRUE
);
264 // draw focus / disabled state, if auto-drawing
265 if ( (state
& ODS_DISABLED
) && autoDraw
)
267 DrawButtonDisable((WXHDC
) hDC
,
268 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
269 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
272 else if ( (state
& ODS_FOCUS
) && autoDraw
)
274 DrawButtonFocus((WXHDC
) hDC
,
278 lpDIS
->rcItem
.bottom
,
285 // GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
287 #if defined(__WIN95__)
289 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool sel
)
298 // create needed pens and brush
299 penHiLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DHILIGHT
));
300 penLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DLIGHT
));
301 penShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DSHADOW
));
302 penDkShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_3DDKSHADOW
));
303 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
304 // Taking the background colour fits in better with
305 // Windows XP themes.
306 brushFace
= CreateSolidBrush(m_backgroundColour
.m_pixel
);
308 // draw the rectangle
313 rect
.bottom
= bottom
;
314 FillRect((HDC
) dc
, &rect
, brushFace
);
317 oldp
= (HPEN
) SelectObject( (HDC
) dc
, sel
? penDkShadow
: penHiLight
);
319 wxDrawLine((HDC
) dc
, left
, top
, right
-1, top
);
320 wxDrawLine((HDC
) dc
, left
, top
+1, left
, bottom
-1);
322 SelectObject( (HDC
) dc
, sel
? penShadow
: penLight
);
323 wxDrawLine((HDC
) dc
, left
+1, top
+1, right
-2, top
+1);
324 wxDrawLine((HDC
) dc
, left
+1, top
+2, left
+1, bottom
-2);
326 SelectObject( (HDC
) dc
, sel
? penLight
: penShadow
);
327 wxDrawLine((HDC
) dc
, left
+1, bottom
-2, right
-1, bottom
-2);
328 wxDrawLine((HDC
) dc
, right
-2, bottom
-3, right
-2, top
);
330 SelectObject( (HDC
) dc
, sel
? penHiLight
: penDkShadow
);
331 wxDrawLine((HDC
) dc
, left
, bottom
-1, right
+2, bottom
-1);
332 wxDrawLine((HDC
) dc
, right
-1, bottom
-2, right
-1, top
-1);
334 // delete allocated resources
335 SelectObject((HDC
) dc
,oldp
);
336 DeleteObject(penHiLight
);
337 DeleteObject(penLight
);
338 DeleteObject(penShadow
);
339 DeleteObject(penDkShadow
);
340 DeleteObject(brushFace
);
345 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool sel
)
353 // create needed pens and brush
354 penBorder
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_WINDOWFRAME
));
355 penShadow
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_BTNSHADOW
));
356 penLight
= CreatePen(PS_SOLID
, 0, GetSysColor(COLOR_BTNHIGHLIGHT
));
357 brushFace
= CreateSolidBrush(COLOR_BTNFACE
);
359 // draw the rectangle
364 rect
.bottom
= bottom
;
365 FillRect((HDC
) dc
, &rect
, brushFace
);
368 oldp
= (HPEN
) SelectObject( (HDC
) dc
, penBorder
);
369 MoveToEx((HDC
) dc
,left
+1,top
,NULL
);LineTo((HDC
) dc
,right
-1,top
);
370 MoveToEx((HDC
) dc
,left
,top
+1,NULL
);LineTo((HDC
) dc
,left
,bottom
-1);
371 MoveToEx((HDC
) dc
,left
+1,bottom
-1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1);
372 MoveToEx((HDC
) dc
,right
-1,top
+1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1);
374 SelectObject( (HDC
) dc
, penShadow
);
377 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
);
378 LineTo((HDC
) dc
, left
+1 ,top
+1);
379 LineTo((HDC
) dc
, right
-2 ,top
+1);
383 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
);
384 LineTo((HDC
) dc
, right
-2 ,bottom
-2);
385 LineTo((HDC
) dc
, right
-2 ,top
);
387 MoveToEx((HDC
) dc
,left
+2 ,bottom
-3 ,NULL
);
388 LineTo((HDC
) dc
, right
-3 ,bottom
-3);
389 LineTo((HDC
) dc
, right
-3 ,top
+1);
391 SelectObject( (HDC
) dc
, penLight
);
393 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
);
394 LineTo((HDC
) dc
, left
+1 ,top
+1);
395 LineTo((HDC
) dc
, right
-2 ,top
+1);
398 // delete allocated resources
399 SelectObject((HDC
) dc
,oldp
);
400 DeleteObject(penBorder
);
401 DeleteObject(penLight
);
402 DeleteObject(penShadow
);
403 DeleteObject(brushFace
);
406 #endif // defined(__WIN95__)
409 void wxBitmapButton::DrawButtonFocus( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool sel
)
415 rect
.bottom
= bottom
;
416 InflateRect( &rect
, - FOCUS_MARGIN
, - FOCUS_MARGIN
);
418 // GRG: the focus rectangle should not move when the button is pushed!
421 OffsetRect( &rect, 1, 1 );
424 DrawFocusRect( (HDC
) dc
, &rect
);
427 extern HBRUSH wxDisableButtonBrush
;
428 void wxBitmapButton::DrawButtonDisable( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool with_marg
)
430 HBRUSH old
= (HBRUSH
) SelectObject( (HDC
) dc
, wxDisableButtonBrush
);
432 // VZ: what's this?? there is no such ROP AFAIK
434 DWORD dwRop
= 0xFA0089L
;
436 DWORD dwRop
= 0xFA0089UL
;
443 right
-= 2 * m_marginX
;
444 bottom
-= 2 * m_marginY
;
447 ::PatBlt( (HDC
) dc
, left
, top
, right
, bottom
, dwRop
);
449 ::SelectObject( (HDC
) dc
, old
);
452 void wxBitmapButton::SetDefault()
454 wxButton::SetDefault();
457 #endif // wxUSE_BMPBUTTON