1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxBitmapButton
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "bmpbuttn.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
24 #include "wx/bmpbuttn.h"
28 #include "wx/msw/private.h"
30 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton
, wxButton
)
32 #define BUTTON_HEIGHT_FACTOR (EDIT_CONTROL_FACTOR * 1.1)
34 bool wxBitmapButton::Create(wxWindow
*parent
, wxWindowID id
, const wxBitmap
& bitmap
,
36 const wxSize
& size
, long style
,
37 const wxValidator
& validator
,
40 m_buttonBitmap
= bitmap
;
44 SetValidator(validator
);
45 #endif // wxUSE_VALIDATORS
47 parent
->AddChild(this);
49 m_backgroundColour
= parent
->GetBackgroundColour() ;
50 m_foregroundColour
= parent
->GetForegroundColour() ;
51 m_windowStyle
= style
;
55 if ( style
& wxBU_AUTODRAW
)
57 m_marginX
= wxDEFAULT_BUTTON_MARGIN
;
58 m_marginY
= wxDEFAULT_BUTTON_MARGIN
;
67 m_windowId
= NewControlId();
71 if ( width
== -1 && bitmap
.Ok())
72 width
= bitmap
.GetWidth() + 2*m_marginX
;
74 if ( height
== -1 && bitmap
.Ok())
75 height
= bitmap
.GetHeight() + 2*m_marginY
;
77 m_hWnd
= (WXHWND
)CreateWindowEx
82 WS_VISIBLE
| WS_TABSTOP
| WS_CHILD
| BS_OWNERDRAW
,
90 // Subclass again for purposes of dialog editing mode
93 SetFont(parent
->GetFont()) ;
95 SetSize(x
, y
, width
, height
);
100 void wxBitmapButton::SetBitmapLabel(const wxBitmap
& bitmap
)
102 m_buttonBitmap
= bitmap
;
105 bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT
*item
)
107 #if defined(__WIN95__)
108 long style
= GetWindowLong((HWND
) GetHWND(), GWL_STYLE
);
109 if (style
& BS_BITMAP
)
111 // Let default procedure draw the bitmap, which is defined
112 // in the Windows resource.
117 LPDRAWITEMSTRUCT lpDIS
= (LPDRAWITEMSTRUCT
) item
;
119 // choose the bitmap to use depending on the buttons state
122 UINT state
= lpDIS
->itemState
;
123 bool isSelected
= (state
& ODS_SELECTED
) != 0;
124 if ( isSelected
&& m_buttonBitmapSelected
.Ok() )
125 bitmap
= &m_buttonBitmapSelected
;
126 else if ((state
& ODS_FOCUS
) && m_buttonBitmapFocus
.Ok())
127 bitmap
= &m_buttonBitmapFocus
;
128 else if ((state
& ODS_DISABLED
) && m_buttonBitmapDisabled
.Ok())
129 bitmap
= &m_buttonBitmapDisabled
;
131 bitmap
= &m_buttonBitmap
;
136 // draw it on the memory DC
137 HDC hDC
= lpDIS
->hDC
;
138 HDC memDC
= ::CreateCompatibleDC(hDC
);
140 HBITMAP old
= (HBITMAP
) ::SelectObject(memDC
, (HBITMAP
) bitmap
->GetHBITMAP());
144 wxLogLastError(_T("SelectObject"));
149 int x
= lpDIS
->rcItem
.left
;
150 int y
= lpDIS
->rcItem
.top
;
151 int width
= lpDIS
->rcItem
.right
- x
;
152 int height
= lpDIS
->rcItem
.bottom
- y
;
154 int wBmp
= bitmap
->GetWidth(),
155 hBmp
= bitmap
->GetHeight();
157 // Draw the face, if auto-drawing
158 bool autoDraw
= (GetWindowStyleFlag() & wxBU_AUTODRAW
) != 0;
161 DrawFace((WXHDC
) hDC
,
162 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
163 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
167 // Centre the bitmap in the control area
168 int x1
= x
+ (width
- wBmp
) / 2;
169 int y1
= y
+ (height
- hBmp
) / 2;
171 if ( isSelected
&& autoDraw
)
179 // no MaskBlt() under Win16
181 wxMask
*mask
= bitmap
->GetMask();
184 // the fg ROP is applied for the pixels of the mask bitmap which are 1
185 // (for a wxMask this means that this is a non transparent pixel), the
186 // bg ROP is applied for all the others
188 HBRUSH hbrBackground
=
189 ::CreateSolidBrush(wxColourToRGB(GetBackgroundColour()));
190 HBRUSH hbrOld
= (HBRUSH
)::SelectObject(hDC
, hbrBackground
);
193 hDC
, x1
, y1
, wBmp
, hBmp
, // dst
195 (HBITMAP
)mask
->GetMaskBitmap(), 0, 0, // mask
196 MAKEROP4(SRCCOPY
, // fg ROP
200 ::SelectObject(hDC
, hbrOld
);
201 ::DeleteObject(hbrBackground
);
205 // this will make the check below fail and BitBlt() will be used if
206 // MaskBlt() is not supported (for example, under Win95)
213 ok
= ::BitBlt(hDC
, x1
, y1
, wBmp
, hBmp
, // dst
220 wxLogLastError(_T("Mask/BitBlt()"));
223 if ( (state
& ODS_DISABLED
) && autoDraw
)
225 DrawButtonDisable((WXHDC
) hDC
,
226 lpDIS
->rcItem
.left
, lpDIS
->rcItem
.top
,
227 lpDIS
->rcItem
.right
, lpDIS
->rcItem
.bottom
,
230 else if ( (state
& ODS_FOCUS
) && autoDraw
)
232 DrawButtonFocus((WXHDC
) hDC
,
236 lpDIS
->rcItem
.bottom
,
240 ::SelectObject(memDC
, old
);
247 void wxBitmapButton::DrawFace( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool sel
)
258 ms_color
= GetSysColor(COLOR_WINDOWFRAME
) ;
259 penBorder
= CreatePen(PS_SOLID
,0,ms_color
) ;
261 ms_color
= GetSysColor(COLOR_BTNSHADOW
) ;
262 penShadow
= CreatePen(PS_SOLID
,0,ms_color
) ;
264 ms_color
= GetSysColor(COLOR_BTNHIGHLIGHT
) ;
265 penLight
= CreatePen(PS_SOLID
,0,ms_color
) ;
267 ms_color
= GetSysColor(COLOR_BTNFACE
) ;
268 brushFace
= CreateSolidBrush(ms_color
) ;
270 oldp
= (HPEN
) SelectObject( (HDC
) dc
, GetStockObject( NULL_PEN
) ) ;
271 oldb
= (HBRUSH
) SelectObject( (HDC
) dc
, brushFace
) ;
272 Rectangle( (HDC
) dc
, left
, top
, right
, bottom
) ;
273 SelectObject( (HDC
) dc
, penBorder
) ;
274 MoveToEx((HDC
) dc
,left
+1,top
,NULL
);LineTo((HDC
) dc
,right
-1,top
);
275 MoveToEx((HDC
) dc
,left
,top
+1,NULL
);LineTo((HDC
) dc
,left
,bottom
-1);
276 MoveToEx((HDC
) dc
,left
+1,bottom
-1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1);
277 MoveToEx((HDC
) dc
,right
-1,top
+1,NULL
);LineTo((HDC
) dc
,right
-1,bottom
-1);
279 SelectObject( (HDC
) dc
, penShadow
) ;
282 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
) ;
283 LineTo((HDC
) dc
, left
+1 ,top
+1) ;
284 LineTo((HDC
) dc
, right
-2 ,top
+1) ;
288 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
) ;
289 LineTo((HDC
) dc
, right
-2 ,bottom
-2) ;
290 LineTo((HDC
) dc
, right
-2 ,top
) ;
291 MoveToEx((HDC
) dc
,left
+2 ,bottom
-3 ,NULL
) ;
292 LineTo((HDC
) dc
, right
-3 ,bottom
-3) ;
293 LineTo((HDC
) dc
, right
-3 ,top
+1) ;
295 SelectObject( (HDC
) dc
, penLight
) ;
297 MoveToEx((HDC
) dc
,left
+1 ,bottom
-2 ,NULL
) ;
298 LineTo((HDC
) dc
, left
+1 ,top
+1) ;
299 LineTo((HDC
) dc
, right
-2 ,top
+1) ;
301 SelectObject((HDC
) dc
,oldp
) ;
302 SelectObject((HDC
) dc
,oldb
) ;
304 DeleteObject(penBorder
);
305 DeleteObject(penLight
);
306 DeleteObject(penShadow
);
307 DeleteObject(brushFace
);
310 // VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
311 #define FOCUS_MARGIN 3
313 void wxBitmapButton::DrawButtonFocus( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool sel
)
319 rect
.bottom
= bottom
;
320 InflateRect( &rect
, - FOCUS_MARGIN
, - FOCUS_MARGIN
) ;
322 OffsetRect( &rect
, 1, 1 ) ;
323 DrawFocusRect( (HDC
) dc
, &rect
) ;
326 extern HBRUSH wxDisableButtonBrush
;
327 void wxBitmapButton::DrawButtonDisable( WXHDC dc
, int left
, int top
, int right
, int bottom
, bool with_marg
)
329 HBRUSH old
= (HBRUSH
) SelectObject( (HDC
) dc
, wxDisableButtonBrush
) ;
331 // VZ: what's this?? there is no such ROP AFAIK
333 DWORD dwRop
= 0xFA0089L
;
335 DWORD dwRop
= 0xFA0089UL
;
342 right
-= 2 * m_marginX
;
343 bottom
-= 2 * m_marginY
;
346 ::PatBlt( (HDC
) dc
, left
, top
, right
, bottom
, dwRop
);
348 ::SelectObject( (HDC
) dc
, old
) ;
351 void wxBitmapButton::SetDefault()
353 wxButton::SetDefault();