]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bmpbuttn.cpp
Correct wxDataViewListModel::RowPrepended
[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{
2352862a 193 if ( IsEnabled() && m_bitmaps[State_Current].IsOk() )
1fdc16ad
VZ
194 Refresh();
195
196 event.Skip();
197}
198
2352862a 199void wxBitmapButton::DoSetBitmap(const wxBitmap& bitmap, State which)
5f1f21d2 200{
2352862a 201 if ( bitmap.IsOk() )
5f1f21d2 202 {
2352862a
VZ
203 switch ( which )
204 {
205#if wxUSE_IMAGE
206 case State_Normal:
207 if ( !HasFlag(wxBU_AUTODRAW) && !m_disabledSetByUser )
208 {
209 wxImage img(bitmap.ConvertToImage().ConvertToGreyscale());
210 m_bitmaps[State_Disabled] = wxBitmap(img);
211 }
212 break;
5f1f21d2
VZ
213#endif // wxUSE_IMAGE
214
2352862a
VZ
215 case State_Focused:
216 // if the focus bitmap is specified but current one isn't, use
217 // the focus bitmap for hovering as well if this is consistent
218 // with the current Windows version look and feel
219 //
220 // rationale: this is compatible with the old wxGTK behaviour
221 // and also makes it much easier to do "the right thing" for
222 // all platforms (some of them, such as Windows XP, have "hot"
223 // buttons while others don't)
224 if ( !m_hoverSetByUser )
225 m_bitmaps[State_Current] = bitmap;
226 break;
227
228 case State_Current:
229 // don't overwrite it with the focused bitmap
230 m_hoverSetByUser = true;
231 break;
232
233 case State_Disabled:
234 // don't overwrite it with the version automatically created
235 // from the normal one
236 m_disabledSetByUser = true;
237 break;
238 }
239 }
5f1f21d2 240
2352862a 241 wxBitmapButtonBase::DoSetBitmap(bitmap, which);
7996ff80
VZ
242}
243
4e9da8b7
RD
244#if wxUSE_UXTHEME
245static
246void MSWDrawXPBackground(wxButton *button, WXDRAWITEMSTRUCT *wxdis)
247{
248 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
249 HDC hdc = lpDIS->hDC;
250 UINT state = lpDIS->itemState;
251 RECT rectBtn;
252 CopyRect(&rectBtn, &lpDIS->rcItem);
253
254 wxUxThemeHandle theme(button, L"BUTTON");
255 int iState;
256
257 if ( state & ODS_SELECTED )
258 {
259 iState = PBS_PRESSED;
260 }
261 else if ( button->HasCapture() || button->IsMouseInWindow() )
262 {
263 iState = PBS_HOT;
264 }
265 else if ( state & ODS_FOCUS )
266 {
267 iState = PBS_DEFAULTED;
268 }
269 else if ( state & ODS_DISABLED )
270 {
271 iState = PBS_DISABLED;
272 }
273 else
274 {
275 iState = PBS_NORMAL;
276 }
277
278 // draw parent background if needed
279 if ( wxUxThemeEngine::Get()->IsThemeBackgroundPartiallyTransparent(theme,
280 BP_PUSHBUTTON,
281 iState) )
282 {
283 wxUxThemeEngine::Get()->DrawThemeParentBackground(GetHwndOf(button), hdc, &rectBtn);
284 }
285
286 // draw background
287 wxUxThemeEngine::Get()->DrawThemeBackground(theme, hdc, BP_PUSHBUTTON, iState,
288 &rectBtn, NULL);
289
290 // calculate content area margins
291 MARGINS margins;
292 wxUxThemeEngine::Get()->GetThemeMargins(theme, hdc, BP_PUSHBUTTON, iState,
293 TMT_CONTENTMARGINS, &rectBtn, &margins);
294 RECT rectClient;
295 ::CopyRect(&rectClient, &rectBtn);
296 ::InflateRect(&rectClient, -margins.cxLeftWidth, -margins.cyTopHeight);
297
298 // if focused and !nofocus rect
299 if ( (state & ODS_FOCUS) && !(state & ODS_NOFOCUSRECT) )
300 {
301 DrawFocusRect(hdc, &rectClient);
302 }
303
304 if ( button->UseBgCol() )
305 {
306 COLORREF colBg = wxColourToRGB(button->GetBackgroundColour());
307 HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
308
309 // don't overwrite the focus rect
310 ::InflateRect(&rectClient, -1, -1);
311 FillRect(hdc, &rectClient, hbrushBackground);
312 ::DeleteObject(hbrushBackground);
313 }
314}
315#endif // wxUSE_UXTHEME
316
f6bcfd97
BP
317// VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
318#define FOCUS_MARGIN 3
319
2bda0e17
KB
320bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
321{
4676948b 322#ifndef __WXWINCE__
ba681060 323 long style = GetWindowLong((HWND) GetHWND(), GWL_STYLE);
fd3f686c
VZ
324 if (style & BS_BITMAP)
325 {
fd3f686c
VZ
326 // Let default procedure draw the bitmap, which is defined
327 // in the Windows resource.
a265d21a 328 return false;
fd3f686c 329 }
2bda0e17
KB
330#endif
331
332 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) item;
47e92c41
GRG
333 HDC hDC = lpDIS->hDC;
334 UINT state = lpDIS->itemState;
335 bool isSelected = (state & ODS_SELECTED) != 0;
2352862a 336 bool autoDraw = HasFlag(wxBU_AUTODRAW);
2bda0e17 337
47e92c41
GRG
338
339 // choose the bitmap to use depending on the button state
2352862a 340 wxBitmap bitmap;
2bda0e17 341
2352862a
VZ
342 if ( isSelected )
343 bitmap = GetBitmapSelected();
344 else if ( IsMouseInWindow() )
345 bitmap = GetBitmapCurrent();
346 else if ( state & ODS_DISABLED )
347 bitmap = GetBitmapDisabled();
348
349 if ( !bitmap.IsOk() )
350 {
351 if ( state & ODS_FOCUS )
352 bitmap = GetBitmapFocus();
353
354 if ( !bitmap.IsOk() )
355 bitmap = GetBitmapLabel();
356
357 if ( !bitmap.IsOk() )
358 return false;
359 }
2bda0e17 360
47e92c41
GRG
361 // centre the bitmap in the control area
362 int x = lpDIS->rcItem.left;
363 int y = lpDIS->rcItem.top;
364 int width = lpDIS->rcItem.right - x;
365 int height = lpDIS->rcItem.bottom - y;
2352862a
VZ
366 int wBmp = bitmap.GetWidth();
367 int hBmp = bitmap.GetHeight();
f6bcfd97 368
4e9da8b7
RD
369#if wxUSE_UXTHEME
370 if ( autoDraw && wxUxThemeEngine::GetIfActive() )
371 {
372 MSWDrawXPBackground(this, item);
373 wxUxThemeHandle theme(this, L"BUTTON");
374
375 // calculate content area margins
376 // assuming here that each state is the same size
377 MARGINS margins;
378 wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
379 BP_PUSHBUTTON, PBS_NORMAL,
380 TMT_CONTENTMARGINS, NULL,
381 &margins);
382 int marginX = margins.cxLeftWidth + 1;
383 int marginY = margins.cyTopHeight + 1;
384 int x1,y1;
385
386 if ( m_windowStyle & wxBU_LEFT )
387 {
388 x1 = x + marginX;
389 }
390 else if ( m_windowStyle & wxBU_RIGHT )
391 {
392 x1 = x + (width - wBmp) - marginX;
393 }
394 else
395 {
396 x1 = x + (width - wBmp) / 2;
397 }
398
399 if ( m_windowStyle & wxBU_TOP )
400 {
401 y1 = y + marginY;
402 }
403 else if ( m_windowStyle & wxBU_BOTTOM )
404 {
405 y1 = y + (height - hBmp) - marginY;
406 }
407 else
408 {
409 y1 = y + (height - hBmp) / 2;
410 }
411
412 // draw the bitmap
71c1dbbd 413 wxDCTemp dst((WXHDC)hDC);
2352862a 414 dst.DrawBitmap(bitmap, x1, y1, true);
4e9da8b7
RD
415
416 return true;
417 }
418#endif // wxUSE_UXTHEME
419
a265d21a
DS
420 int x1,y1;
421
f6bcfd97
BP
422 if(m_windowStyle & wxBU_LEFT)
423 x1 = x + (FOCUS_MARGIN+1);
424 else if(m_windowStyle & wxBU_RIGHT)
425 x1 = x + (width - wBmp) - (FOCUS_MARGIN+1);
426 else
427 x1 = x + (width - wBmp) / 2;
428
429 if(m_windowStyle & wxBU_TOP)
430 y1 = y + (FOCUS_MARGIN+1);
431 else if(m_windowStyle & wxBU_BOTTOM)
432 y1 = y + (height - hBmp) - (FOCUS_MARGIN+1);
433 else
434 y1 = y + (height - hBmp) / 2;
2bda0e17 435
47e92c41 436 if ( isSelected && autoDraw )
d9c8e68e 437 {
47e92c41
GRG
438 x1++;
439 y1++;
d9c8e68e 440 }
2bda0e17 441
47e92c41 442 // draw the face, if auto-drawing
d9c8e68e
VZ
443 if ( autoDraw )
444 {
445 DrawFace((WXHDC) hDC,
446 lpDIS->rcItem.left, lpDIS->rcItem.top,
447 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
448 isSelected);
449 }
2bda0e17 450
47e92c41 451 // draw the bitmap
7d09b97f 452 wxDCTemp dst((WXHDC)hDC);
2352862a 453 dst.DrawBitmap(bitmap, x1, y1, true);
33ac7e6f 454
47e92c41 455 // draw focus / disabled state, if auto-drawing
d9c8e68e
VZ
456 if ( (state & ODS_DISABLED) && autoDraw )
457 {
458 DrawButtonDisable((WXHDC) hDC,
459 lpDIS->rcItem.left, lpDIS->rcItem.top,
460 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
a265d21a 461 true);
d9c8e68e
VZ
462 }
463 else if ( (state & ODS_FOCUS) && autoDraw )
464 {
465 DrawButtonFocus((WXHDC) hDC,
466 lpDIS->rcItem.left,
467 lpDIS->rcItem.top,
468 lpDIS->rcItem.right,
469 lpDIS->rcItem.bottom,
470 isSelected);
471 }
2bda0e17 472
a265d21a 473 return true;
2bda0e17
KB
474}
475
5ab1fa8e
GRG
476// GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
477
a265d21a
DS
478void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
479 int right, int bottom, bool sel )
2bda0e17 480{
d9c8e68e 481 HPEN oldp;
5ab1fa8e 482 HPEN penHiLight;
d9c8e68e
VZ
483 HPEN penLight;
484 HPEN penShadow;
5ab1fa8e 485 HPEN penDkShadow;
d9c8e68e 486 HBRUSH brushFace;
2bda0e17 487
5ab1fa8e
GRG
488 // create needed pens and brush
489 penHiLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
490 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
491 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
492 penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
4e9da8b7 493 brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
5ab1fa8e
GRG
494
495 // draw the rectangle
496 RECT rect;
497 rect.left = left;
498 rect.right = right;
499 rect.top = top;
500 rect.bottom = bottom;
501 FillRect((HDC) dc, &rect, brushFace);
502
503 // draw the border
504 oldp = (HPEN) SelectObject( (HDC) dc, sel? penDkShadow : penHiLight);
4676948b
JS
505
506 wxDrawLine((HDC) dc, left, top, right-1, top);
507 wxDrawLine((HDC) dc, left, top+1, left, bottom-1);
5ab1fa8e
GRG
508
509 SelectObject( (HDC) dc, sel? penShadow : penLight);
4676948b
JS
510 wxDrawLine((HDC) dc, left+1, top+1, right-2, top+1);
511 wxDrawLine((HDC) dc, left+1, top+2, left+1, bottom-2);
5ab1fa8e
GRG
512
513 SelectObject( (HDC) dc, sel? penLight : penShadow);
4676948b
JS
514 wxDrawLine((HDC) dc, left+1, bottom-2, right-1, bottom-2);
515 wxDrawLine((HDC) dc, right-2, bottom-3, right-2, top);
5ab1fa8e
GRG
516
517 SelectObject( (HDC) dc, sel? penHiLight : penDkShadow);
4676948b
JS
518 wxDrawLine((HDC) dc, left, bottom-1, right+2, bottom-1);
519 wxDrawLine((HDC) dc, right-1, bottom-2, right-1, top-1);
5ab1fa8e
GRG
520
521 // delete allocated resources
522 SelectObject((HDC) dc,oldp);
523 DeleteObject(penHiLight);
524 DeleteObject(penLight);
525 DeleteObject(penShadow);
526 DeleteObject(penDkShadow);
527 DeleteObject(brushFace);
528}
529
a265d21a
DS
530void wxBitmapButton::DrawButtonFocus( WXHDC dc, int left, int top, int right,
531 int bottom, bool WXUNUSED(sel) )
2bda0e17 532{
fd3f686c
VZ
533 RECT rect;
534 rect.left = left;
535 rect.top = top;
536 rect.right = right;
537 rect.bottom = bottom;
5ab1fa8e
GRG
538 InflateRect( &rect, - FOCUS_MARGIN, - FOCUS_MARGIN );
539
540 // GRG: the focus rectangle should not move when the button is pushed!
541/*
fd3f686c 542 if ( sel )
5ab1fa8e
GRG
543 OffsetRect( &rect, 1, 1 );
544*/
a265d21a 545
5ab1fa8e 546 DrawFocusRect( (HDC) dc, &rect );
2bda0e17
KB
547}
548
d50dbf7c
VZ
549void
550wxBitmapButton::DrawButtonDisable( WXHDC dc,
551 int left, int top, int right, int bottom,
552 bool with_marg )
2bda0e17 553{
2352862a 554 if ( !m_brushDisabled.IsOk() )
d50dbf7c
VZ
555 {
556 // draw a bitmap with two black and two background colour pixels
557 wxBitmap bmp(2, 2);
558 wxMemoryDC dc;
559 dc.SelectObject(bmp);
560 dc.SetPen(*wxBLACK_PEN);
561 dc.DrawPoint(0, 0);
562 dc.DrawPoint(1, 1);
563 dc.SetPen(GetBackgroundColour());
564 dc.DrawPoint(0, 1);
565 dc.DrawPoint(1, 0);
566
567 m_brushDisabled = wxBrush(bmp);
568 }
569
570 SelectInHDC selectBrush((HDC)dc, GetHbrushOf(m_brushDisabled));
2bda0e17 571
2b268535
VZ
572 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
573 // name, give it our own
a265d21a 574 static const DWORD PATTERNPAINT = 0xFA0089UL;
d9c8e68e
VZ
575
576 if ( with_marg )
577 {
578 left += m_marginX;
579 top += m_marginY;
580 right -= 2 * m_marginX;
581 bottom -= 2 * m_marginY;
582 }
583
a265d21a 584 ::PatBlt( (HDC) dc, left, top, right, bottom, PATTERNPAINT);
2bda0e17
KB
585}
586
c046274e
RD
587wxSize wxBitmapButton::DoGetBestSize() const
588{
2352862a 589 if ( GetBitmapLabel().IsOk() )
c046274e 590 {
2352862a
VZ
591 int width = GetBitmapLabel().GetWidth(),
592 height = GetBitmapLabel().GetHeight();
d381e983
VZ
593 int marginH = 0,
594 marginV = 0;
595
4e9da8b7 596#if wxUSE_UXTHEME
0d1c8f39 597 if ( wxUxThemeEngine::GetIfActive() )
4e9da8b7
RD
598 {
599 wxUxThemeHandle theme((wxBitmapButton *)this, L"BUTTON");
600
4e9da8b7
RD
601 MARGINS margins;
602 wxUxThemeEngine::Get()->GetThemeMargins(theme, NULL,
603 BP_PUSHBUTTON, PBS_NORMAL,
604 TMT_CONTENTMARGINS, NULL,
605 &margins);
0d1c8f39 606
9d1b7527
JG
607 // XP doesn't draw themed buttons correctly when the client area is
608 // smaller than 8x8 - enforce this minimum size for small bitmaps
d381e983
VZ
609 if ( width < 8 )
610 width = 8;
611 if ( height < 8 )
612 height = 8;
613
614 // don't add margins for the borderless buttons, they don't need
615 // them and it just makes them appear larger than needed
616 if ( !HasFlag(wxBORDER_NONE) )
617 {
aceeebce
VZ
618 // we need 2 extra pixels for the focus rectangle, without them
619 // it's overwritten by the bitmap itself
620 marginH = margins.cxLeftWidth + margins.cxRightWidth + 2;
621 marginV = margins.cyTopHeight + margins.cyBottomHeight + 2;
d381e983 622 }
4e9da8b7 623 }
d381e983 624 else
4e9da8b7 625#endif // wxUSE_UXTHEME
d381e983
VZ
626 {
627 if ( !HasFlag(wxBORDER_NONE) )
628 {
629 marginH = 2*m_marginX;
630 marginV = 2*m_marginY;
631 }
632 }
4e9da8b7 633
d381e983 634 wxSize best(width + marginH, height + marginV);
31582e4e
RD
635 CacheBestSize(best);
636 return best;
c046274e 637 }
e8153940 638
9266e0ec
VZ
639 // no idea what our best size should be, defer to the base class
640 return wxBitmapButtonBase::DoGetBestSize();
c046274e
RD
641}
642
1e6feb95 643#endif // wxUSE_BMPBUTTON