]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bmpbuttn.cpp
always properly check if SeekI() calls succeded; this makes CanRead() functions of...
[wxWidgets.git] / src / msw / bmpbuttn.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
1e6feb95 2// Name: src/msw/bmpbuttn.cpp
2bda0e17
KB
3// Purpose: wxBitmapButton
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
6c9a19aa 8// Copyright: (c) Julian Smart
65571936 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
2bda0e17
KB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
1e6feb95 16 #pragma hdrstop
2bda0e17
KB
17#endif
18
1e6feb95
VZ
19#if wxUSE_BMPBUTTON
20
910b0053
WS
21#include "wx/bmpbuttn.h"
22
2bda0e17 23#ifndef WX_PRECOMP
84f19880 24 #include "wx/log.h"
47e92c41 25 #include "wx/dcmemory.h"
155ecd4c 26 #include "wx/image.h"
2bda0e17
KB
27#endif
28
29#include "wx/msw/private.h"
025f7d77 30#include "wx/msw/dc.h" // for wxDCTemp
4e9da8b7 31
37005692 32#include "wx/msw/uxtheme.h"
4e9da8b7 33
37005692 34#if wxUSE_UXTHEME
4e9da8b7
RD
35 // no need to include tmschema.h
36 #ifndef BP_PUSHBUTTON
37 #define BP_PUSHBUTTON 1
38
39 #define PBS_NORMAL 1
40 #define PBS_HOT 2
41 #define PBS_PRESSED 3
42 #define PBS_DISABLED 4
43 #define PBS_DEFAULTED 5
44
45 #define TMT_CONTENTMARGINS 3602
46 #endif
47#endif // wxUSE_UXTHEME
48
49#ifndef ODS_NOFOCUSRECT
50 #define ODS_NOFOCUSRECT 0x0200
51#endif
2bda0e17 52
bc9fb572
JS
53// ----------------------------------------------------------------------------
54// macros
55// ----------------------------------------------------------------------------
56
57#if wxUSE_EXTENDED_RTTI
58
59WX_DEFINE_FLAGS( wxBitmapButtonStyle )
60
3ff066a4 61wxBEGIN_FLAGS( wxBitmapButtonStyle )
bc9fb572
JS
62 // new style border flags, we put them first to
63 // use them for streaming out
3ff066a4
SC
64 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
65 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
66 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
67 wxFLAGS_MEMBER(wxBORDER_RAISED)
68 wxFLAGS_MEMBER(wxBORDER_STATIC)
69 wxFLAGS_MEMBER(wxBORDER_NONE)
fcf90ee1 70
bc9fb572 71 // old style border flags
3ff066a4
SC
72 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
73 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
74 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
75 wxFLAGS_MEMBER(wxRAISED_BORDER)
76 wxFLAGS_MEMBER(wxSTATIC_BORDER)
cb0afb26 77 wxFLAGS_MEMBER(wxBORDER)
bc9fb572
JS
78
79 // standard window styles
3ff066a4
SC
80 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
81 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
82 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
83 wxFLAGS_MEMBER(wxWANTS_CHARS)
cb0afb26 84 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
3ff066a4
SC
85 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
86 wxFLAGS_MEMBER(wxVSCROLL)
87 wxFLAGS_MEMBER(wxHSCROLL)
88
89 wxFLAGS_MEMBER(wxBU_AUTODRAW)
90 wxFLAGS_MEMBER(wxBU_LEFT)
91 wxFLAGS_MEMBER(wxBU_RIGHT)
92 wxFLAGS_MEMBER(wxBU_TOP)
93 wxFLAGS_MEMBER(wxBU_BOTTOM)
94wxEND_FLAGS( wxBitmapButtonStyle )
bc9fb572
JS
95
96IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton, wxButton,"wx/bmpbuttn.h")
97
3ff066a4 98wxBEGIN_PROPERTIES_TABLE(wxBitmapButton)
af498247 99 wxPROPERTY_FLAGS( WindowStyle , wxBitmapButtonStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
3ff066a4 100wxEND_PROPERTIES_TABLE()
bc9fb572 101
3ff066a4
SC
102wxBEGIN_HANDLERS_TABLE(wxBitmapButton)
103wxEND_HANDLERS_TABLE()
bc9fb572 104
3ff066a4 105wxCONSTRUCTOR_5( wxBitmapButton , wxWindow* , Parent , wxWindowID , Id , wxBitmap , Bitmap , wxPoint , Position , wxSize , Size )
bc9fb572
JS
106
107#else
2bda0e17 108IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
bc9fb572 109#endif
2bda0e17 110
a6fd0fde
VZ
111BEGIN_EVENT_TABLE(wxBitmapButton, wxBitmapButtonBase)
112 EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged)
1fdc16ad
VZ
113 EVT_ENTER_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
114 EVT_LEAVE_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
a6fd0fde
VZ
115END_EVENT_TABLE()
116
066f1b7a
SC
117/*
118TODO PROPERTIES :
119
120long "style" , wxBU_AUTODRAW
121bool "default" , 0
122bitmap "selected" ,
123bitmap "focus" ,
124bitmap "disabled" ,
125*/
126
56c74796
VZ
127bool wxBitmapButton::Create(wxWindow *parent,
128 wxWindowID id,
129 const wxBitmap& bitmap,
130 const wxPoint& pos,
131 const wxSize& size, long style,
132 const wxValidator& wxVALIDATOR_PARAM(validator),
133 const wxString& name)
2bda0e17 134{
56c74796
VZ
135 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
136 return false;
2bda0e17 137
56c74796 138 SetBitmapLabel(bitmap);
2bda0e17 139
a265d21a 140 if ( style & wxBU_AUTODRAW )
56c74796 141 SetMargins(4, 4);
2bda0e17 142
56c74796
VZ
143 return MSWCreateControl(_T("BUTTON"), wxEmptyString, pos, size);
144}
2bda0e17 145
56c74796
VZ
146WXDWORD wxBitmapButton::MSWGetStyle(long style, WXDWORD *exstyle) const
147{
148 WXDWORD msStyle = wxButton::MSWGetStyle(style, exstyle);
f6bcfd97 149
56c74796 150 msStyle |= BS_OWNERDRAW;
b0766406 151
56c74796 152 if ( style & wxBU_LEFT )
f6bcfd97 153 msStyle |= BS_LEFT;
56c74796 154 if ( style & wxBU_RIGHT )
f6bcfd97 155 msStyle |= BS_RIGHT;
56c74796 156 if ( style & wxBU_TOP )
f6bcfd97 157 msStyle |= BS_TOP;
56c74796 158 if ( style & wxBU_BOTTOM )
f6bcfd97 159 msStyle |= BS_BOTTOM;
2bda0e17 160
56c74796 161 return msStyle;
2bda0e17
KB
162}
163
d50dbf7c
VZ
164bool wxBitmapButton::SetBackgroundColour(const wxColour& colour)
165{
166 if ( !wxBitmapButtonBase::SetBackgroundColour(colour) )
167 {
168 // didn't change
169 return false;
170 }
171
172 // invalidate the brush, it will be recreated the next time it's needed
173 m_brushDisabled = wxNullBrush;
174
175 return true;
176}
177
a6fd0fde
VZ
178void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent& event)
179{
180 m_brushDisabled = wxNullBrush;
181
182 if ( !IsEnabled() )
183 {
184 // this change affects our current state
185 Refresh();
186 }
187
188 event.Skip();
189}
190
1fdc16ad
VZ
191void wxBitmapButton::OnMouseEnterOrLeave(wxMouseEvent& event)
192{
193 if ( IsEnabled() && m_bmpHover.Ok() )
194 Refresh();
195
196 event.Skip();
197}
198
5f1f21d2
VZ
199void wxBitmapButton::SetBitmapLabel(const wxBitmap& bitmap)
200{
201#if wxUSE_IMAGE
e040a4ff 202 if ( !HasFlag(wxBU_AUTODRAW) && !m_disabledSetByUser && bitmap.IsOk() )
5f1f21d2
VZ
203 {
204 m_bmpDisabled = wxBitmap(bitmap.ConvertToImage().ConvertToGreyscale());
205 }
206#endif // wxUSE_IMAGE
207
208 wxBitmapButtonBase::SetBitmapLabel(bitmap);
209}
210
211void wxBitmapButton::SetBitmapFocus(const wxBitmap& focus)
7996ff80
VZ
212{
213 // if the focus bitmap is specified but hover one isn't, use the focus
214 // bitmap for hovering as well if this is consistent with the current
215 // Windows version look and feel
216 //
217 // rationale: this is compatible with the old wxGTK behaviour and also
218 // makes it much easier to do "the right thing" for all platforms (some of
219 // them, such as Windows XP, have "hot" buttons while others don't)
5f1f21d2 220 if ( focus.Ok() && !m_hoverSetByUser )
7996ff80 221 m_bmpHover = m_bmpFocus;
7996ff80 222
5f1f21d2
VZ
223 wxBitmapButtonBase::SetBitmapFocus(focus);
224}
225
226void wxBitmapButton::SetBitmapDisabled(const wxBitmap& disabled)
227{
228 if ( disabled.IsOk() )
229 m_disabledSetByUser = true;
230
231 wxBitmapButtonBase::SetBitmapDisabled(disabled);
232}
233
234void wxBitmapButton::SetBitmapHover(const wxBitmap& hover)
235{
236 if ( hover.IsOk() )
237 m_hoverSetByUser = true;
238
239 wxBitmapButtonBase::SetBitmapHover(hover);
7996ff80
VZ
240}
241
4e9da8b7
RD
242#if wxUSE_UXTHEME
243static
244void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis)
245{
246 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
247 HDC hdc = lpDIS->hDC;
248 UINT state = lpDIS->itemState;
249 RECT rectBtn;
250 CopyRect(&rectBtn, &lpDIS->rcItem);
251
252 wxUxThemeHandle theme(button, L"BUTTON");
253 int iState;
254
255 if ( state & ODS_SELECTED )
256 {
257 iState = PBS_PRESSED;
258 }
259 else if ( button->HasCapture() || button->IsMouseInWindow() )
260 {
261 iState = PBS_HOT;
262 }
263 else if ( state & ODS_FOCUS )
264 {
265 iState = PBS_DEFAULTED;
266 }
267 else if ( state & ODS_DISABLED )
268 {
269 iState = PBS_DISABLED;
270 }
271 else
272 {
273 iState = PBS_NORMAL;
274 }
275
276 // draw parent background if needed
277 if ( wxUxThemeEngine::Get()->IsThemeBackgroundPartiallyTransparent(theme,
278 BP_PUSHBUTTON,
279 iState) )
280 {
281 wxUxThemeEngine::Get()->DrawThemeParentBackground(GetHwndOf(button), hdc, &rectBtn);
282 }
283
284 // draw background
285 wxUxThemeEngine::Get()->DrawThemeBackground(theme, hdc, BP_PUSHBUTTON, iState,
286 &rectBtn, NULL);
287
288 // calculate content area margins
289 MARGINS margins;
290 wxUxThemeEngine::Get()->GetThemeMargins(theme, hdc, BP_PUSHBUTTON, iState,
291 TMT_CONTENTMARGINS, &rectBtn, &margins);
292 RECT rectClient;
293 ::CopyRect(&rectClient, &rectBtn);
294 ::InflateRect(&rectClient, -margins.cxLeftWidth, -margins.cyTopHeight);
295
296 // if focused and !nofocus rect
297 if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
298 {
299 DrawFocusRect(hdc, &rectClient);
300 }
301
302 if ( button->UseBgCol() )
303 {
304 COLORREF colBg = wxColourToRGB(button->GetBackgroundColour());
305 HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
306
307 // don't overwrite the focus rect
308 ::InflateRect(&rectClient, -1, -1);
309 FillRect(hdc, &rectClient, hbrushBackground);
310 ::DeleteObject(hbrushBackground);
311 }
312}
313#endif // wxUSE_UXTHEME
314
f6bcfd97
BP
315// VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
316#define FOCUS_MARGIN 3
317
2bda0e17
KB
318bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
319{
4676948b 320#ifndef __WXWINCE__
ba681060 321 long style = GetWindowLong((HWND) GetHWND(), GWL_STYLE);
fd3f686c
VZ
322 if (style & BS_BITMAP)
323 {
fd3f686c
VZ
324 // Let default procedure draw the bitmap, which is defined
325 // in the Windows resource.
a265d21a 326 return false;
fd3f686c 327 }
2bda0e17
KB
328#endif
329
330 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) item;
47e92c41
GRG
331 HDC hDC = lpDIS->hDC;
332 UINT state = lpDIS->itemState;
333 bool isSelected = (state & ODS_SELECTED) != 0;
334 bool autoDraw = (GetWindowStyleFlag() & wxBU_AUTODRAW) != 0;
2bda0e17 335
47e92c41
GRG
336
337 // choose the bitmap to use depending on the button state
1fdc16ad 338 wxBitmap *bitmap;
2bda0e17 339
1e6feb95
VZ
340 if ( isSelected && m_bmpSelected.Ok() )
341 bitmap = &m_bmpSelected;
1fdc16ad
VZ
342 else if ( m_bmpHover.Ok() && IsMouseInWindow() )
343 bitmap = &m_bmpHover;
1e6feb95
VZ
344 else if ((state & ODS_FOCUS) && m_bmpFocus.Ok())
345 bitmap = &m_bmpFocus;
346 else if ((state & ODS_DISABLED) && m_bmpDisabled.Ok())
347 bitmap = &m_bmpDisabled;
d9c8e68e 348 else
1e6feb95 349 bitmap = &m_bmpNormal;
2bda0e17 350
42e69d6b 351 if ( !bitmap->Ok() )
a265d21a 352 return false;
2bda0e17 353
47e92c41
GRG
354 // centre the bitmap in the control area
355 int x = lpDIS->rcItem.left;
356 int y = lpDIS->rcItem.top;
357 int width = lpDIS->rcItem.right - x;
358 int height = lpDIS->rcItem.bottom - y;
359 int wBmp = bitmap->GetWidth();
360 int hBmp = bitmap->GetHeight();
f6bcfd97 361
4e9da8b7
RD
362#if wxUSE_UXTHEME
363 if ( autoDraw && wxUxThemeEngine::GetIfActive() )
364 {
365 MSWDrawXPBackground(this, item);
366 wxUxThemeHandle theme(this, L"BUTTON");
367
368 // calculate content area margins
369 // assuming here that each state is the same size
370 MARGINS margins;
371 wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
372 BP_PUSHBUTTON, PBS_NORMAL,
373 TMT_CONTENTMARGINS, NULL,
374 &margins);
375 int marginX = margins.cxLeftWidth + 1;
376 int marginY = margins.cyTopHeight + 1;
377 int x1,y1;
378
379 if ( m_windowStyle & wxBU_LEFT )
380 {
381 x1 = x + marginX;
382 }
383 else if ( m_windowStyle & wxBU_RIGHT )
384 {
385 x1 = x + (width - wBmp) - marginX;
386 }
387 else
388 {
389 x1 = x + (width - wBmp) / 2;
390 }
391
392 if ( m_windowStyle & wxBU_TOP )
393 {
394 y1 = y + marginY;
395 }
396 else if ( m_windowStyle & wxBU_BOTTOM )
397 {
398 y1 = y + (height - hBmp) - marginY;
399 }
400 else
401 {
402 y1 = y + (height - hBmp) / 2;
403 }
404
405 // draw the bitmap
71c1dbbd 406 wxDCTemp dst((WXHDC)hDC);
4e9da8b7
RD
407 dst.DrawBitmap(*bitmap, x1, y1, true);
408
409 return true;
410 }
411#endif // wxUSE_UXTHEME
412
a265d21a
DS
413 int x1,y1;
414
f6bcfd97
BP
415 if(m_windowStyle & wxBU_LEFT)
416 x1 = x + (FOCUS_MARGIN+1);
417 else if(m_windowStyle & wxBU_RIGHT)
418 x1 = x + (width - wBmp) - (FOCUS_MARGIN+1);
419 else
420 x1 = x + (width - wBmp) / 2;
421
422 if(m_windowStyle & wxBU_TOP)
423 y1 = y + (FOCUS_MARGIN+1);
424 else if(m_windowStyle & wxBU_BOTTOM)
425 y1 = y + (height - hBmp) - (FOCUS_MARGIN+1);
426 else
427 y1 = y + (height - hBmp) / 2;
2bda0e17 428
47e92c41 429 if ( isSelected && autoDraw )
d9c8e68e 430 {
47e92c41
GRG
431 x1++;
432 y1++;
d9c8e68e 433 }
2bda0e17 434
47e92c41 435 // draw the face, if auto-drawing
d9c8e68e
VZ
436 if ( autoDraw )
437 {
438 DrawFace((WXHDC) hDC,
439 lpDIS->rcItem.left, lpDIS->rcItem.top,
440 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
441 isSelected);
442 }
2bda0e17 443
47e92c41 444 // draw the bitmap
7d09b97f 445 wxDCTemp dst((WXHDC)hDC);
a265d21a 446 dst.DrawBitmap(*bitmap, x1, y1, true);
33ac7e6f 447
47e92c41 448 // draw focus / disabled state, if auto-drawing
d9c8e68e
VZ
449 if ( (state & ODS_DISABLED) && autoDraw )
450 {
451 DrawButtonDisable((WXHDC) hDC,
452 lpDIS->rcItem.left, lpDIS->rcItem.top,
453 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
a265d21a 454 true);
d9c8e68e
VZ
455 }
456 else if ( (state & ODS_FOCUS) && autoDraw )
457 {
458 DrawButtonFocus((WXHDC) hDC,
459 lpDIS->rcItem.left,
460 lpDIS->rcItem.top,
461 lpDIS->rcItem.right,
462 lpDIS->rcItem.bottom,
463 isSelected);
464 }
2bda0e17 465
a265d21a 466 return true;
2bda0e17
KB
467}
468
5ab1fa8e
GRG
469// GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
470
a265d21a
DS
471void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
472 int right, int bottom, bool sel )
2bda0e17 473{
d9c8e68e 474 HPEN oldp;
5ab1fa8e 475 HPEN penHiLight;
d9c8e68e
VZ
476 HPEN penLight;
477 HPEN penShadow;
5ab1fa8e 478 HPEN penDkShadow;
d9c8e68e 479 HBRUSH brushFace;
2bda0e17 480
5ab1fa8e
GRG
481 // create needed pens and brush
482 penHiLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
483 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
484 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
485 penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
4e9da8b7 486 brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
5ab1fa8e
GRG
487
488 // draw the rectangle
489 RECT rect;
490 rect.left = left;
491 rect.right = right;
492 rect.top = top;
493 rect.bottom = bottom;
494 FillRect((HDC) dc, &rect, brushFace);
495
496 // draw the border
497 oldp = (HPEN) SelectObject( (HDC) dc, sel? penDkShadow : penHiLight);
4676948b
JS
498
499 wxDrawLine((HDC) dc, left, top, right-1, top);
500 wxDrawLine((HDC) dc, left, top+1, left, bottom-1);
5ab1fa8e
GRG
501
502 SelectObject( (HDC) dc, sel? penShadow : penLight);
4676948b
JS
503 wxDrawLine((HDC) dc, left+1, top+1, right-2, top+1);
504 wxDrawLine((HDC) dc, left+1, top+2, left+1, bottom-2);
5ab1fa8e
GRG
505
506 SelectObject( (HDC) dc, sel? penLight : penShadow);
4676948b
JS
507 wxDrawLine((HDC) dc, left+1, bottom-2, right-1, bottom-2);
508 wxDrawLine((HDC) dc, right-2, bottom-3, right-2, top);
5ab1fa8e
GRG
509
510 SelectObject( (HDC) dc, sel? penHiLight : penDkShadow);
4676948b
JS
511 wxDrawLine((HDC) dc, left, bottom-1, right+2, bottom-1);
512 wxDrawLine((HDC) dc, right-1, bottom-2, right-1, top-1);
5ab1fa8e
GRG
513
514 // delete allocated resources
515 SelectObject((HDC) dc,oldp);
516 DeleteObject(penHiLight);
517 DeleteObject(penLight);
518 DeleteObject(penShadow);
519 DeleteObject(penDkShadow);
520 DeleteObject(brushFace);
521}
522
a265d21a
DS
523void wxBitmapButton::DrawButtonFocus( WXHDC dc, int left, int top, int right,
524 int bottom, bool WXUNUSED(sel) )
2bda0e17 525{
fd3f686c
VZ
526 RECT rect;
527 rect.left = left;
528 rect.top = top;
529 rect.right = right;
530 rect.bottom = bottom;
5ab1fa8e
GRG
531 InflateRect( &rect, - FOCUS_MARGIN, - FOCUS_MARGIN );
532
533 // GRG: the focus rectangle should not move when the button is pushed!
534/*
fd3f686c 535 if ( sel )
5ab1fa8e
GRG
536 OffsetRect( &rect, 1, 1 );
537*/
a265d21a 538
5ab1fa8e 539 DrawFocusRect( (HDC) dc, &rect );
2bda0e17
KB
540}
541
d50dbf7c
VZ
542void
543wxBitmapButton::DrawButtonDisable( WXHDC dc,
544 int left, int top, int right, int bottom,
545 bool with_marg )
2bda0e17 546{
d50dbf7c
VZ
547 if ( !m_brushDisabled.Ok() )
548 {
549 // draw a bitmap with two black and two background colour pixels
550 wxBitmap bmp(2, 2);
551 wxMemoryDC dc;
552 dc.SelectObject(bmp);
553 dc.SetPen(*wxBLACK_PEN);
554 dc.DrawPoint(0, 0);
555 dc.DrawPoint(1, 1);
556 dc.SetPen(GetBackgroundColour());
557 dc.DrawPoint(0, 1);
558 dc.DrawPoint(1, 0);
559
560 m_brushDisabled = wxBrush(bmp);
561 }
562
563 SelectInHDC selectBrush((HDC)dc, GetHbrushOf(m_brushDisabled));
2bda0e17 564
2b268535
VZ
565 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
566 // name, give it our own
a265d21a 567 static const DWORD PATTERNPAINT = 0xFA0089UL;
d9c8e68e
VZ
568
569 if ( with_marg )
570 {
571 left += m_marginX;
572 top += m_marginY;
573 right -= 2 * m_marginX;
574 bottom -= 2 * m_marginY;
575 }
576
a265d21a 577 ::PatBlt( (HDC) dc, left, top, right, bottom, PATTERNPAINT);
2bda0e17
KB
578}
579
c046274e
RD
580wxSize wxBitmapButton::DoGetBestSize() const
581{
9266e0ec 582 if ( m_bmpNormal.Ok() )
c046274e 583 {
d381e983
VZ
584 int width = m_bmpNormal.GetWidth(),
585 height = m_bmpNormal.GetHeight();
586 int marginH = 0,
587 marginV = 0;
588
4e9da8b7 589#if wxUSE_UXTHEME
0d1c8f39 590 if ( wxUxThemeEngine::GetIfActive() )
4e9da8b7
RD
591 {
592 wxUxThemeHandle theme((wxBitmapButton *)this, L"BUTTON");
593
4e9da8b7
RD
594 MARGINS margins;
595 wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
596 BP_PUSHBUTTON, PBS_NORMAL,
597 TMT_CONTENTMARGINS, NULL,
598 &margins);
0d1c8f39 599
9d1b7527
JG
600 // XP doesn't draw themed buttons correctly when the client area is
601 // smaller than 8x8 - enforce this minimum size for small bitmaps
d381e983
VZ
602 if ( width < 8 )
603 width = 8;
604 if ( height < 8 )
605 height = 8;
606
607 // don't add margins for the borderless buttons, they don't need
608 // them and it just makes them appear larger than needed
609 if ( !HasFlag(wxBORDER_NONE) )
610 {
aceeebce
VZ
611 // we need 2 extra pixels for the focus rectangle, without them
612 // it's overwritten by the bitmap itself
613 marginH = margins.cxLeftWidth + margins.cxRightWidth + 2;
614 marginV = margins.cyTopHeight + margins.cyBottomHeight + 2;
d381e983 615 }
4e9da8b7 616 }
d381e983 617 else
4e9da8b7 618#endif // wxUSE_UXTHEME
d381e983
VZ
619 {
620 if ( !HasFlag(wxBORDER_NONE) )
621 {
622 marginH = 2*m_marginX;
623 marginV = 2*m_marginY;
624 }
625 }
4e9da8b7 626
d381e983 627 wxSize best(width + marginH, height + marginV);
31582e4e
RD
628 CacheBestSize(best);
629 return best;
c046274e 630 }
e8153940 631
9266e0ec
VZ
632 // no idea what our best size should be, defer to the base class
633 return wxBitmapButtonBase::DoGetBestSize();
c046274e
RD
634}
635
1e6feb95 636#endif // wxUSE_BMPBUTTON