]> git.saurik.com Git - wxWidgets.git/blame - src/msw/button.cpp
make sure we don't keep a focus pointer to a window that gets deleted
[wxWidgets.git] / src / msw / button.cpp
CommitLineData
2bda0e17 1/////////////////////////////////////////////////////////////////////////////
cd0b1709 2// Name: msw/button.cpp
2bda0e17
KB
3// Purpose: wxButton
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
edccf428 9// Licence: wxWindows license
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
edccf428
VZ
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
cd0b1709 19
2bda0e17 20#ifdef __GNUG__
edccf428 21 #pragma implementation "button.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
edccf428 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
1e6feb95
VZ
31#if wxUSE_BUTTON
32
2bda0e17 33#ifndef WX_PRECOMP
edccf428
VZ
34 #include "wx/button.h"
35 #include "wx/brush.h"
4e938f5b 36 #include "wx/panel.h"
8a4df159 37 #include "wx/bmpbuttn.h"
fb39c7ec
RR
38 #include "wx/settings.h"
39 #include "wx/dcscreen.h"
2bda0e17
KB
40#endif
41
42#include "wx/msw/private.h"
43
edccf428
VZ
44// ----------------------------------------------------------------------------
45// macros
46// ----------------------------------------------------------------------------
47
cd0b1709 48IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
2bda0e17 49
edccf428
VZ
50// this macro tries to adjust the default button height to a reasonable value
51// using the char height as the base
1c4a764c 52#define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10)
2bda0e17 53
edccf428
VZ
54// ============================================================================
55// implementation
56// ============================================================================
57
58// ----------------------------------------------------------------------------
59// creation/destruction
60// ----------------------------------------------------------------------------
61
62bool wxButton::Create(wxWindow *parent,
63 wxWindowID id,
64 const wxString& label,
65 const wxPoint& pos,
66 const wxSize& size,
67 long style,
68 const wxValidator& validator,
69 const wxString& name)
2bda0e17 70{
5b2f31eb 71 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
edccf428
VZ
72 return FALSE;
73
8292017c
VZ
74 WXDWORD exstyle;
75 WXDWORD msStyle = MSWGetStyle(style, &exstyle);
76
77#ifdef __WIN32__
78 // if the label contains several lines we must explicitly tell the button
79 // about it or it wouldn't draw it correctly ("\n"s would just appear as
80 // black boxes)
81 //
82 // NB: we do it here and not in MSWGetStyle() because we need the label
83 // value and m_label is not set yet when MSWGetStyle() is called;
84 // besides changing BS_MULTILINE during run-time is pointless anyhow
85 if ( label.find(_T('\n')) != wxString::npos )
86 {
87 msStyle |= BS_MULTILINE;
88 }
89#endif // __WIN32__
90
91 return MSWCreateControl(_T("BUTTON"), msStyle, pos, size, label, exstyle);
5b2f31eb
VZ
92}
93
94wxButton::~wxButton()
95{
96}
edccf428 97
5b2f31eb
VZ
98// ----------------------------------------------------------------------------
99// flags
100// ----------------------------------------------------------------------------
cd0b1709 101
5b2f31eb
VZ
102WXDWORD wxButton::MSWGetStyle(long style, WXDWORD *exstyle) const
103{
104 // buttons never have an external border, they draw their own one
105 WXDWORD msStyle = wxControl::MSWGetStyle
106 (
107 (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle
108 );
f6bcfd97 109
5b2f31eb
VZ
110 // we must use WS_CLIPSIBLINGS with the buttons or they would draw over
111 // each other in any resizeable dialog which has more than one button in
112 // the bottom
113 msStyle |= WS_CLIPSIBLINGS;
b0766406 114
f6bcfd97 115#ifdef __WIN32__
5b2f31eb
VZ
116 // don't use "else if" here: weird as it is, but you may combine wxBU_LEFT
117 // and wxBU_RIGHT to get BS_CENTER!
118 if ( style & wxBU_LEFT )
f6bcfd97 119 msStyle |= BS_LEFT;
5b2f31eb 120 if ( style & wxBU_RIGHT )
f6bcfd97 121 msStyle |= BS_RIGHT;
5b2f31eb 122 if ( style & wxBU_TOP )
f6bcfd97 123 msStyle |= BS_TOP;
5b2f31eb 124 if ( style & wxBU_BOTTOM )
f6bcfd97 125 msStyle |= BS_BOTTOM;
5b2f31eb 126#endif // __WIN32__
edccf428 127
5b2f31eb 128 return msStyle;
2bda0e17
KB
129}
130
edccf428
VZ
131// ----------------------------------------------------------------------------
132// size management including autosizing
133// ----------------------------------------------------------------------------
134
f68586e5 135wxSize wxButton::DoGetBestSize() const
2bda0e17 136{
4438caf4 137 int wBtn;
1e023926 138 GetTextExtent(wxGetWindowText(GetHWND()), &wBtn, NULL);
edccf428 139
4438caf4
VZ
140 int wChar, hChar;
141 wxGetCharSize(GetHWND(), &wChar, &hChar, &GetFont());
142
1e023926 143 // add a margin -- the button is wider than just its label
4438caf4
VZ
144 wBtn += 3*wChar;
145
146 // the button height is proportional to the height of the font used
147 int hBtn = BUTTON_HEIGHT_FROM_CHAR_HEIGHT(hChar);
edccf428 148
1e023926
VZ
149 // all buttons have at least the standard size unless the user explicitly
150 // wants them to be of smaller size and used wxBU_EXACTFIT style when
151 // creating the button
152 if ( !HasFlag(wxBU_EXACTFIT) )
188b9f2e
RD
153 {
154 wxSize sz = GetDefaultSize();
1e023926
VZ
155 if (wBtn > sz.x)
156 sz.x = wBtn;
157 if (hBtn > sz.y)
158 sz.y = hBtn;
159
188b9f2e
RD
160 return sz;
161 }
a63f2bec 162
1e023926 163 return wxSize(wBtn, hBtn);
2bda0e17
KB
164}
165
e1f36ff8 166/* static */
1e6feb95 167wxSize wxButtonBase::GetDefaultSize()
e1f36ff8 168{
8c3c31d4 169 static wxSize s_sizeBtn;
e1f36ff8 170
8c3c31d4
VZ
171 if ( s_sizeBtn.x == 0 )
172 {
173 wxScreenDC dc;
a756f210 174 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
8c3c31d4
VZ
175
176 // the size of a standard button in the dialog units is 50x14,
177 // translate this to pixels
178 // NB1: the multipliers come from the Windows convention
179 // NB2: the extra +1/+2 were needed to get the size be the same as the
180 // size of the buttons in the standard dialog - I don't know how
181 // this happens, but on my system this size is 75x23 in pixels and
182 // 23*8 isn't even divisible by 14... Would be nice to understand
183 // why these constants are needed though!
184 s_sizeBtn.x = (50 * (dc.GetCharWidth() + 1))/4;
185 s_sizeBtn.y = ((14 * dc.GetCharHeight()) + 2)/8;
186 }
e1f36ff8 187
8c3c31d4 188 return s_sizeBtn;
e1f36ff8
VZ
189}
190
4438caf4 191// ----------------------------------------------------------------------------
036da5e3 192// default button handling
4438caf4
VZ
193// ----------------------------------------------------------------------------
194
d78f09e2
VZ
195/*
196 "Everything you ever wanted to know about the default buttons" or "Why do we
197 have to do all this?"
198
199 In MSW the default button should be activated when the user presses Enter
200 and the current control doesn't process Enter itself somehow. This is
201 handled by ::DefWindowProc() (or maybe ::DefDialogProc()) using DM_SETDEFID
202 Another aspect of "defaultness" is that the default button has different
203 appearance: this is due to BS_DEFPUSHBUTTON style which is completely
7fb1b2b4
VZ
204 separate from DM_SETDEFID stuff (!). Also note that BS_DEFPUSHBUTTON should
205 be unset if our parent window is not active so it should be unset whenever
206 we lose activation and set back when we regain it.
d78f09e2
VZ
207
208 Final complication is that when a button is active, it should be the default
209 one, i.e. pressing Enter on a button always activates it and not another
210 one.
211
212 We handle this by maintaining a permanent and a temporary default items in
213 wxControlContainer (both may be NULL). When a button becomes the current
214 control (i.e. gets focus) it sets itself as the temporary default which
215 ensures that it has the right appearance and that Enter will be redirected
216 to it. When the button loses focus, it unsets the temporary default and so
217 the default item will be the permanent default -- that is the default button
218 if any had been set or none otherwise, which is just what we want.
219
7fb1b2b4
VZ
220 NB: all this is quite complicated by now and the worst is that normally
221 it shouldn't be necessary at all as for the normal Windows programs
222 DefWindowProc() and IsDialogMessage() take care of all this
223 automatically -- however in wxWindows programs this doesn't work for
224 nested hierarchies (i.e. a notebook inside a notebook) for unknown
225 reason and so we have to reproduce all this code ourselves. It would be
226 very nice if we could avoid doing it.
d78f09e2
VZ
227 */
228
036da5e3 229// set this button as the (permanently) default one in its panel
edccf428 230void wxButton::SetDefault()
2bda0e17 231{
edccf428 232 wxWindow *parent = GetParent();
2bda0e17 233
036da5e3
VZ
234 wxCHECK_RET( parent, _T("button without parent?") );
235
7fb1b2b4 236 // set this one as the default button both for wxWindows ...
036da5e3 237 wxWindow *winOldDefault = parent->SetDefaultItem(this);
036da5e3 238
7fb1b2b4
VZ
239 // ... and Windows
240 SetDefaultStyle(wxDynamicCast(winOldDefault, wxButton), FALSE);
241 SetDefaultStyle(this, TRUE);
036da5e3
VZ
242}
243
7fb1b2b4 244// set this button as being currently default
036da5e3
VZ
245void wxButton::SetTmpDefault()
246{
247 wxWindow *parent = GetParent();
248
249 wxCHECK_RET( parent, _T("button without parent?") );
250
251 wxWindow *winOldDefault = parent->GetDefaultItem();
252 parent->SetTmpDefaultItem(this);
7fb1b2b4
VZ
253
254 SetDefaultStyle(wxDynamicCast(winOldDefault, wxButton), FALSE);
255 SetDefaultStyle(this, TRUE);
036da5e3
VZ
256}
257
7fb1b2b4 258// unset this button as currently default, it may still stay permanent default
036da5e3
VZ
259void wxButton::UnsetTmpDefault()
260{
261 wxWindow *parent = GetParent();
262
263 wxCHECK_RET( parent, _T("button without parent?") );
264
265 parent->SetTmpDefaultItem(NULL);
266
267 wxWindow *winOldDefault = parent->GetDefaultItem();
7fb1b2b4
VZ
268
269 SetDefaultStyle(this, FALSE);
270 SetDefaultStyle(wxDynamicCast(winOldDefault, wxButton), TRUE);
036da5e3 271}
8ed57d93 272
036da5e3
VZ
273/* static */
274void
7fb1b2b4 275wxButton::SetDefaultStyle(wxButton *btn, bool on)
036da5e3 276{
7fb1b2b4
VZ
277 // we may be called with NULL pointer -- simpler to do the check here than
278 // in the caller which does wxDynamicCast()
279 if ( !btn )
280 return;
281
282 // first, let DefDlgProc() know about the new default button
283 if ( on )
5d1d2d46 284 {
7fb1b2b4
VZ
285 // we shouldn't set BS_DEFPUSHBUTTON for any button if we don't have
286 // focus at all any more
287 if ( !wxTheApp->IsActive() )
288 return;
cd0b1709 289
7fb1b2b4
VZ
290 // look for a panel-like window
291 wxWindow *win = btn->GetParent();
292 while ( win && !win->HasFlag(wxTAB_TRAVERSAL) )
293 win = win->GetParent();
294
295 if ( win )
be4017f8 296 {
7fb1b2b4
VZ
297 ::SendMessage(GetHwndOf(win), DM_SETDEFID, btn->GetId(), 0L);
298
299 // sending DM_SETDEFID also changes the button style to
300 // BS_DEFPUSHBUTTON so there is nothing more to do
be4017f8 301 }
5d1d2d46
VZ
302 }
303
7fb1b2b4
VZ
304 // then also change the style as needed
305 long style = ::GetWindowLong(GetHwndOf(btn), GWL_STYLE);
306 if ( !(style & BS_DEFPUSHBUTTON) == on )
be4017f8 307 {
7fb1b2b4
VZ
308 // don't do it with the owner drawn buttons because it will
309 // reset BS_OWNERDRAW style bit too (as BS_OWNERDRAW &
310 // BS_DEFPUSHBUTTON != 0)!
036da5e3
VZ
311 if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW )
312 {
7fb1b2b4
VZ
313 ::SendMessage(GetHwndOf(btn), BM_SETSTYLE,
314 on ? style | BS_DEFPUSHBUTTON
315 : style & ~BS_DEFPUSHBUTTON,
316 1L /* redraw */);
036da5e3 317 }
7fb1b2b4 318 else // owner drawn
036da5e3 319 {
7fb1b2b4
VZ
320 // redraw the button - it will notice itself that it's
321 // [not] the default one [any longer]
322 btn->Refresh();
036da5e3 323 }
be4017f8 324 }
7fb1b2b4 325 //else: already has correct style
2bda0e17
KB
326}
327
edccf428
VZ
328// ----------------------------------------------------------------------------
329// helpers
330// ----------------------------------------------------------------------------
331
332bool wxButton::SendClickEvent()
2bda0e17 333{
edccf428
VZ
334 wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
335 event.SetEventObject(this);
336
337 return ProcessCommand(event);
2bda0e17
KB
338}
339
edccf428 340void wxButton::Command(wxCommandEvent & event)
2bda0e17 341{
edccf428 342 ProcessCommand(event);
2bda0e17
KB
343}
344
edccf428
VZ
345// ----------------------------------------------------------------------------
346// event/message handlers
347// ----------------------------------------------------------------------------
2bda0e17 348
33ac7e6f 349bool wxButton::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
edccf428
VZ
350{
351 bool processed = FALSE;
57c0af52 352 switch ( param )
edccf428 353 {
a95e38c0
VZ
354 case 1: // message came from an accelerator
355 case BN_CLICKED: // normal buttons send this
356 case BN_DOUBLECLICKED: // owner-drawn ones also send this
57c0af52
VZ
357 processed = SendClickEvent();
358 break;
edccf428 359 }
2bda0e17 360
edccf428 361 return processed;
2bda0e17
KB
362}
363
678cd6de
VZ
364long wxButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
365{
036da5e3
VZ
366 // when we receive focus, we want to temporary become the default button in
367 // our parent panel so that pressing "Enter" would activate us -- and when
368 // losing it we should restore the previous default button as well
be4017f8 369 if ( nMsg == WM_SETFOCUS )
678cd6de 370 {
036da5e3 371 SetTmpDefault();
be4017f8 372
036da5e3
VZ
373 // let the default processing take place too
374 }
375 else if ( nMsg == WM_KILLFOCUS )
376 {
377 UnsetTmpDefault();
678cd6de 378 }
a95e38c0
VZ
379 else if ( nMsg == WM_LBUTTONDBLCLK )
380 {
f6bcfd97
BP
381 // emulate a click event to force an owner-drawn button to change its
382 // appearance - without this, it won't do it
383 (void)wxControl::MSWWindowProc(WM_LBUTTONDOWN, wParam, lParam);
384
036da5e3 385 // and continue with processing the message normally as well
a95e38c0 386 }
678cd6de
VZ
387
388 // let the base class do all real processing
389 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
390}
cd0b1709
VZ
391
392// ----------------------------------------------------------------------------
393// owner-drawn buttons support
394// ----------------------------------------------------------------------------
395
396#ifdef __WIN32__
397
398// drawing helpers
399
400static void DrawButtonText(HDC hdc,
401 RECT *pRect,
402 const wxString& text,
403 COLORREF col)
404{
405 COLORREF colOld = SetTextColor(hdc, col);
406 int modeOld = SetBkMode(hdc, TRANSPARENT);
407
408 DrawText(hdc, text, text.length(), pRect,
409 DT_CENTER | DT_VCENTER | DT_SINGLELINE);
410
411 SetBkMode(hdc, modeOld);
412 SetTextColor(hdc, colOld);
413}
414
415static void DrawRect(HDC hdc, const RECT& r)
416{
417 MoveToEx(hdc, r.left, r.top, NULL);
418 LineTo(hdc, r.right, r.top);
419 LineTo(hdc, r.right, r.bottom);
420 LineTo(hdc, r.left, r.bottom);
421 LineTo(hdc, r.left, r.top);
422}
423
424void wxButton::MakeOwnerDrawn()
425{
426 long style = GetWindowLong(GetHwnd(), GWL_STYLE);
9750fc42 427 if ( (style & BS_OWNERDRAW) != BS_OWNERDRAW )
cd0b1709
VZ
428 {
429 // make it so
430 style |= BS_OWNERDRAW;
431 SetWindowLong(GetHwnd(), GWL_STYLE, style);
432 }
433}
434
435bool wxButton::SetBackgroundColour(const wxColour &colour)
436{
437 if ( !wxControl::SetBackgroundColour(colour) )
438 {
439 // nothing to do
440 return FALSE;
441 }
442
443 MakeOwnerDrawn();
444
445 Refresh();
446
447 return TRUE;
448}
449
450bool wxButton::SetForegroundColour(const wxColour &colour)
451{
452 if ( !wxControl::SetForegroundColour(colour) )
453 {
454 // nothing to do
455 return FALSE;
456 }
457
458 MakeOwnerDrawn();
459
460 Refresh();
461
462 return TRUE;
463}
464
465/*
466 The button frame looks like this normally:
467
468 WWWWWWWWWWWWWWWWWWB
16162a64
GRG
469 WHHHHHHHHHHHHHHHHGB W = white (HILIGHT)
470 WH GB H = light grey (LIGHT)
471 WH GB G = dark grey (SHADOW)
472 WH GB B = black (DKSHADOW)
473 WH GB
cd0b1709
VZ
474 WGGGGGGGGGGGGGGGGGB
475 BBBBBBBBBBBBBBBBBBB
476
477 When the button is selected, the button becomes like this (the total button
478 size doesn't change):
479
480 BBBBBBBBBBBBBBBBBBB
481 BWWWWWWWWWWWWWWWWBB
16162a64
GRG
482 BWHHHHHHHHHHHHHHGBB
483 BWH GBB
484 BWH GBB
cd0b1709
VZ
485 BWGGGGGGGGGGGGGGGBB
486 BBBBBBBBBBBBBBBBBBB
487 BBBBBBBBBBBBBBBBBBB
488
489 When the button is pushed (while selected) it is like:
490
491 BBBBBBBBBBBBBBBBBBB
492 BGGGGGGGGGGGGGGGGGB
493 BG GB
494 BG GB
495 BG GB
16162a64 496 BG GB
cd0b1709
VZ
497 BGGGGGGGGGGGGGGGGGB
498 BBBBBBBBBBBBBBBBBBB
499*/
500
501static void DrawButtonFrame(HDC hdc, const RECT& rectBtn,
502 bool selected, bool pushed)
503{
504 RECT r;
505 CopyRect(&r, &rectBtn);
506
16162a64
GRG
507 HPEN hpenBlack = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW)),
508 hpenGrey = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW)),
509 hpenLightGr = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT)),
510 hpenWhite = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT));
cd0b1709
VZ
511
512 HPEN hpenOld = (HPEN)SelectObject(hdc, hpenBlack);
513
514 r.right--;
515 r.bottom--;
516
517 if ( pushed )
518 {
519 DrawRect(hdc, r);
520
521 (void)SelectObject(hdc, hpenGrey);
522 InflateRect(&r, -1, -1);
523
524 DrawRect(hdc, r);
525 }
526 else // !pushed
527 {
528 if ( selected )
529 {
530 DrawRect(hdc, r);
531
532 InflateRect(&r, -1, -1);
533 }
534
535 MoveToEx(hdc, r.left, r.bottom, NULL);
536 LineTo(hdc, r.right, r.bottom);
537 LineTo(hdc, r.right, r.top - 1);
538
539 (void)SelectObject(hdc, hpenWhite);
540 MoveToEx(hdc, r.left, r.bottom - 1, NULL);
541 LineTo(hdc, r.left, r.top);
542 LineTo(hdc, r.right, r.top);
543
16162a64
GRG
544 (void)SelectObject(hdc, hpenLightGr);
545 MoveToEx(hdc, r.left + 1, r.bottom - 2, NULL);
546 LineTo(hdc, r.left + 1, r.top + 1);
547 LineTo(hdc, r.right - 1, r.top + 1);
548
cd0b1709
VZ
549 (void)SelectObject(hdc, hpenGrey);
550 MoveToEx(hdc, r.left + 1, r.bottom - 1, NULL);
551 LineTo(hdc, r.right - 1, r.bottom - 1);
552 LineTo(hdc, r.right - 1, r.top);
553 }
554
555 (void)SelectObject(hdc, hpenOld);
556 DeleteObject(hpenWhite);
16162a64 557 DeleteObject(hpenLightGr);
cd0b1709
VZ
558 DeleteObject(hpenGrey);
559 DeleteObject(hpenBlack);
560}
561
562bool wxButton::MSWOnDraw(WXDRAWITEMSTRUCT *wxdis)
563{
564 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)wxdis;
565
566 RECT rectBtn;
567 CopyRect(&rectBtn, &lpDIS->rcItem);
568
569 COLORREF colBg = wxColourToRGB(GetBackgroundColour()),
570 colFg = wxColourToRGB(GetForegroundColour());
571
572 HDC hdc = lpDIS->hDC;
573 UINT state = lpDIS->itemState;
574
575 // first, draw the background
576 HBRUSH hbrushBackground = ::CreateSolidBrush(colBg);
577
578 FillRect(hdc, &rectBtn, hbrushBackground);
579
580 // draw the border for the current state
581 bool selected = (state & ODS_SELECTED) != 0;
582 if ( !selected )
583 {
584 wxPanel *panel = wxDynamicCast(GetParent(), wxPanel);
585 if ( panel )
586 {
587 selected = panel->GetDefaultItem() == this;
588 }
589 }
590 bool pushed = (SendMessage(GetHwnd(), BM_GETSTATE, 0, 0) & BST_PUSHED) != 0;
591
592 DrawButtonFrame(hdc, rectBtn, selected, pushed);
593
594 // draw the focus rect if needed
595 if ( state & ODS_FOCUS )
596 {
597 RECT rectFocus;
598 CopyRect(&rectFocus, &rectBtn);
599
600 // I don't know where does this constant come from, but this is how
601 // Windows draws them
602 InflateRect(&rectFocus, -4, -4);
603
604 DrawFocusRect(hdc, &rectFocus);
605 }
606
9750fc42
VZ
607 if ( pushed )
608 {
609 // the label is shifted by 1 pixel to create "pushed" effect
610 OffsetRect(&rectBtn, 1, 1);
611 }
612
cd0b1709
VZ
613 DrawButtonText(hdc, &rectBtn, GetLabel(),
614 state & ODS_DISABLED ? GetSysColor(COLOR_GRAYTEXT)
615 : colFg);
616
617 ::DeleteObject(hbrushBackground);
618
cd0b1709
VZ
619 return TRUE;
620}
621
622#endif // __WIN32__
1e6feb95
VZ
623
624#endif // wxUSE_BUTTON
625