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