]> git.saurik.com Git - wxWidgets.git/blame - src/msw/bmpbuttn.cpp
Include commctrl.h properly.
[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"
2bda0e17
KB
26#endif
27
28#include "wx/msw/private.h"
d50dbf7c 29#include "wx/image.h"
7996ff80 30#include "wx/msw/uxtheme.h"
2bda0e17 31
bc9fb572
JS
32// ----------------------------------------------------------------------------
33// macros
34// ----------------------------------------------------------------------------
35
36#if wxUSE_EXTENDED_RTTI
37
38WX_DEFINE_FLAGS( wxBitmapButtonStyle )
39
3ff066a4 40wxBEGIN_FLAGS( wxBitmapButtonStyle )
bc9fb572
JS
41 // new style border flags, we put them first to
42 // use them for streaming out
3ff066a4
SC
43 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
44 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
45 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
46 wxFLAGS_MEMBER(wxBORDER_RAISED)
47 wxFLAGS_MEMBER(wxBORDER_STATIC)
48 wxFLAGS_MEMBER(wxBORDER_NONE)
fcf90ee1 49
bc9fb572 50 // old style border flags
3ff066a4
SC
51 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
52 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
53 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
54 wxFLAGS_MEMBER(wxRAISED_BORDER)
55 wxFLAGS_MEMBER(wxSTATIC_BORDER)
cb0afb26 56 wxFLAGS_MEMBER(wxBORDER)
bc9fb572
JS
57
58 // standard window styles
3ff066a4
SC
59 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
60 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
61 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
62 wxFLAGS_MEMBER(wxWANTS_CHARS)
cb0afb26 63 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
3ff066a4
SC
64 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
65 wxFLAGS_MEMBER(wxVSCROLL)
66 wxFLAGS_MEMBER(wxHSCROLL)
67
68 wxFLAGS_MEMBER(wxBU_AUTODRAW)
69 wxFLAGS_MEMBER(wxBU_LEFT)
70 wxFLAGS_MEMBER(wxBU_RIGHT)
71 wxFLAGS_MEMBER(wxBU_TOP)
72 wxFLAGS_MEMBER(wxBU_BOTTOM)
73wxEND_FLAGS( wxBitmapButtonStyle )
bc9fb572
JS
74
75IMPLEMENT_DYNAMIC_CLASS_XTI(wxBitmapButton, wxButton,"wx/bmpbuttn.h")
76
3ff066a4 77wxBEGIN_PROPERTIES_TABLE(wxBitmapButton)
af498247 78 wxPROPERTY_FLAGS( WindowStyle , wxBitmapButtonStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
3ff066a4 79wxEND_PROPERTIES_TABLE()
bc9fb572 80
3ff066a4
SC
81wxBEGIN_HANDLERS_TABLE(wxBitmapButton)
82wxEND_HANDLERS_TABLE()
bc9fb572 83
3ff066a4 84wxCONSTRUCTOR_5( wxBitmapButton , wxWindow* , Parent , wxWindowID , Id , wxBitmap , Bitmap , wxPoint , Position , wxSize , Size )
bc9fb572
JS
85
86#else
2bda0e17 87IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
bc9fb572 88#endif
2bda0e17 89
a6fd0fde
VZ
90BEGIN_EVENT_TABLE(wxBitmapButton, wxBitmapButtonBase)
91 EVT_SYS_COLOUR_CHANGED(wxBitmapButton::OnSysColourChanged)
1fdc16ad
VZ
92 EVT_ENTER_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
93 EVT_LEAVE_WINDOW(wxBitmapButton::OnMouseEnterOrLeave)
a6fd0fde
VZ
94END_EVENT_TABLE()
95
066f1b7a
SC
96/*
97TODO PROPERTIES :
98
99long "style" , wxBU_AUTODRAW
100bool "default" , 0
101bitmap "selected" ,
102bitmap "focus" ,
103bitmap "disabled" ,
104*/
105
a265d21a
DS
106bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
107 const wxBitmap& bitmap,
108 const wxPoint& pos,
109 const wxSize& size, long style,
110 const wxValidator& wxVALIDATOR_PARAM(validator),
111 const wxString& name)
2bda0e17 112{
a265d21a
DS
113 m_bmpNormal = bitmap;
114 SetName(name);
11b6a93b
VZ
115
116#if wxUSE_VALIDATORS
a265d21a 117 SetValidator(validator);
11b6a93b 118#endif // wxUSE_VALIDATORS
2bda0e17 119
a265d21a 120 parent->AddChild(this);
2bda0e17 121
a265d21a
DS
122 m_backgroundColour = parent->GetBackgroundColour();
123 m_foregroundColour = parent->GetForegroundColour();
124 m_windowStyle = style;
2bda0e17 125
a265d21a
DS
126 if ( style & wxBU_AUTODRAW )
127 {
1fdc16ad
VZ
128 m_marginX =
129 m_marginY = 4;
a265d21a 130 }
2bda0e17 131
fcf90ee1 132 if (id == wxID_ANY)
a265d21a
DS
133 m_windowId = NewControlId();
134 else
135 m_windowId = id;
2bda0e17 136
a265d21a 137 long msStyle = WS_VISIBLE | WS_TABSTOP | WS_CHILD | BS_OWNERDRAW ;
f6bcfd97 138
b0766406
JS
139 if ( m_windowStyle & wxCLIP_SIBLINGS )
140 msStyle |= WS_CLIPSIBLINGS;
141
f6bcfd97
BP
142#ifdef __WIN32__
143 if(m_windowStyle & wxBU_LEFT)
144 msStyle |= BS_LEFT;
145 if(m_windowStyle & wxBU_RIGHT)
146 msStyle |= BS_RIGHT;
147 if(m_windowStyle & wxBU_TOP)
148 msStyle |= BS_TOP;
149 if(m_windowStyle & wxBU_BOTTOM)
150 msStyle |= BS_BOTTOM;
151#endif
152
a265d21a 153 m_hWnd = (WXHWND) CreateWindowEx(
42e69d6b 154 0,
223d09f6 155 wxT("BUTTON"),
fda7962d 156 wxEmptyString,
f6bcfd97 157 msStyle,
33ac7e6f 158 0, 0, 0, 0,
42e69d6b
VZ
159 GetWinHwnd(parent),
160 (HMENU)m_windowId,
161 wxGetInstance(),
162 NULL
163 );
2bda0e17 164
a265d21a
DS
165 // Subclass again for purposes of dialog editing mode
166 SubclassWin(m_hWnd);
2bda0e17 167
9f884528
RD
168 SetPosition(pos);
169 SetBestSize(size);
2bda0e17 170
a265d21a 171 return true;
2bda0e17
KB
172}
173
d50dbf7c
VZ
174bool wxBitmapButton::SetBackgroundColour(const wxColour& colour)
175{
176 if ( !wxBitmapButtonBase::SetBackgroundColour(colour) )
177 {
178 // didn't change
179 return false;
180 }
181
182 // invalidate the brush, it will be recreated the next time it's needed
183 m_brushDisabled = wxNullBrush;
184
185 return true;
186}
187
a6fd0fde
VZ
188void wxBitmapButton::OnSysColourChanged(wxSysColourChangedEvent& event)
189{
190 m_brushDisabled = wxNullBrush;
191
192 if ( !IsEnabled() )
193 {
194 // this change affects our current state
195 Refresh();
196 }
197
198 event.Skip();
199}
200
1fdc16ad
VZ
201void wxBitmapButton::OnMouseEnterOrLeave(wxMouseEvent& event)
202{
203 if ( IsEnabled() && m_bmpHover.Ok() )
204 Refresh();
205
206 event.Skip();
207}
208
7996ff80
VZ
209void wxBitmapButton::OnSetBitmap()
210{
211 // if the focus bitmap is specified but hover one isn't, use the focus
212 // bitmap for hovering as well if this is consistent with the current
213 // Windows version look and feel
214 //
215 // rationale: this is compatible with the old wxGTK behaviour and also
216 // makes it much easier to do "the right thing" for all platforms (some of
217 // them, such as Windows XP, have "hot" buttons while others don't)
218 if ( !m_bmpHover.Ok() &&
219 m_bmpFocus.Ok() &&
220 wxUxThemeEngine::GetIfActive() )
221 {
222 m_bmpHover = m_bmpFocus;
223 }
224
225 // this will redraw us
226 wxBitmapButtonBase::OnSetBitmap();
227}
228
f6bcfd97
BP
229// VZ: should be at the very least less than wxDEFAULT_BUTTON_MARGIN
230#define FOCUS_MARGIN 3
231
2bda0e17
KB
232bool wxBitmapButton::MSWOnDraw(WXDRAWITEMSTRUCT *item)
233{
4676948b 234#ifndef __WXWINCE__
ba681060 235 long style = GetWindowLong((HWND) GetHWND(), GWL_STYLE);
fd3f686c
VZ
236 if (style & BS_BITMAP)
237 {
fd3f686c
VZ
238 // Let default procedure draw the bitmap, which is defined
239 // in the Windows resource.
a265d21a 240 return false;
fd3f686c 241 }
2bda0e17
KB
242#endif
243
244 LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT) item;
47e92c41
GRG
245 HDC hDC = lpDIS->hDC;
246 UINT state = lpDIS->itemState;
247 bool isSelected = (state & ODS_SELECTED) != 0;
248 bool autoDraw = (GetWindowStyleFlag() & wxBU_AUTODRAW) != 0;
2bda0e17 249
47e92c41
GRG
250
251 // choose the bitmap to use depending on the button state
1fdc16ad 252 wxBitmap *bitmap;
2bda0e17 253
1e6feb95
VZ
254 if ( isSelected && m_bmpSelected.Ok() )
255 bitmap = &m_bmpSelected;
1fdc16ad
VZ
256 else if ( m_bmpHover.Ok() && IsMouseInWindow() )
257 bitmap = &m_bmpHover;
1e6feb95
VZ
258 else if ((state & ODS_FOCUS) && m_bmpFocus.Ok())
259 bitmap = &m_bmpFocus;
260 else if ((state & ODS_DISABLED) && m_bmpDisabled.Ok())
261 bitmap = &m_bmpDisabled;
d9c8e68e 262 else
1e6feb95 263 bitmap = &m_bmpNormal;
2bda0e17 264
42e69d6b 265 if ( !bitmap->Ok() )
a265d21a 266 return false;
2bda0e17 267
47e92c41
GRG
268 // centre the bitmap in the control area
269 int x = lpDIS->rcItem.left;
270 int y = lpDIS->rcItem.top;
271 int width = lpDIS->rcItem.right - x;
272 int height = lpDIS->rcItem.bottom - y;
273 int wBmp = bitmap->GetWidth();
274 int hBmp = bitmap->GetHeight();
f6bcfd97 275
a265d21a
DS
276 int x1,y1;
277
f6bcfd97
BP
278 if(m_windowStyle & wxBU_LEFT)
279 x1 = x + (FOCUS_MARGIN+1);
280 else if(m_windowStyle & wxBU_RIGHT)
281 x1 = x + (width - wBmp) - (FOCUS_MARGIN+1);
282 else
283 x1 = x + (width - wBmp) / 2;
284
285 if(m_windowStyle & wxBU_TOP)
286 y1 = y + (FOCUS_MARGIN+1);
287 else if(m_windowStyle & wxBU_BOTTOM)
288 y1 = y + (height - hBmp) - (FOCUS_MARGIN+1);
289 else
290 y1 = y + (height - hBmp) / 2;
2bda0e17 291
47e92c41 292 if ( isSelected && autoDraw )
d9c8e68e 293 {
47e92c41
GRG
294 x1++;
295 y1++;
d9c8e68e 296 }
2bda0e17 297
47e92c41 298 // draw the face, if auto-drawing
d9c8e68e
VZ
299 if ( autoDraw )
300 {
301 DrawFace((WXHDC) hDC,
302 lpDIS->rcItem.left, lpDIS->rcItem.top,
303 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
304 isSelected);
305 }
2bda0e17 306
47e92c41 307 // draw the bitmap
7d09b97f 308 wxDCTemp dst((WXHDC)hDC);
a265d21a 309 dst.DrawBitmap(*bitmap, x1, y1, true);
33ac7e6f 310
47e92c41 311 // draw focus / disabled state, if auto-drawing
d9c8e68e
VZ
312 if ( (state & ODS_DISABLED) && autoDraw )
313 {
314 DrawButtonDisable((WXHDC) hDC,
315 lpDIS->rcItem.left, lpDIS->rcItem.top,
316 lpDIS->rcItem.right, lpDIS->rcItem.bottom,
a265d21a 317 true);
d9c8e68e
VZ
318 }
319 else if ( (state & ODS_FOCUS) && autoDraw )
320 {
321 DrawButtonFocus((WXHDC) hDC,
322 lpDIS->rcItem.left,
323 lpDIS->rcItem.top,
324 lpDIS->rcItem.right,
325 lpDIS->rcItem.bottom,
326 isSelected);
327 }
2bda0e17 328
a265d21a 329 return true;
2bda0e17
KB
330}
331
5ab1fa8e
GRG
332// GRG Feb/2000, support for bmp buttons with Win95/98 standard LNF
333
a265d21a
DS
334void wxBitmapButton::DrawFace( WXHDC dc, int left, int top,
335 int right, int bottom, bool sel )
2bda0e17 336{
d9c8e68e 337 HPEN oldp;
5ab1fa8e 338 HPEN penHiLight;
d9c8e68e
VZ
339 HPEN penLight;
340 HPEN penShadow;
5ab1fa8e 341 HPEN penDkShadow;
d9c8e68e 342 HBRUSH brushFace;
2bda0e17 343
5ab1fa8e
GRG
344 // create needed pens and brush
345 penHiLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DHILIGHT));
346 penLight = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT));
347 penShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DSHADOW));
348 penDkShadow = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW));
85b43fbf
JS
349 // brushFace = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
350 // Taking the background colour fits in better with
351 // Windows XP themes.
352 brushFace = CreateSolidBrush(m_backgroundColour.m_pixel);
5ab1fa8e
GRG
353
354 // draw the rectangle
355 RECT rect;
356 rect.left = left;
357 rect.right = right;
358 rect.top = top;
359 rect.bottom = bottom;
360 FillRect((HDC) dc, &rect, brushFace);
361
362 // draw the border
363 oldp = (HPEN) SelectObject( (HDC) dc, sel? penDkShadow : penHiLight);
4676948b
JS
364
365 wxDrawLine((HDC) dc, left, top, right-1, top);
366 wxDrawLine((HDC) dc, left, top+1, left, bottom-1);
5ab1fa8e
GRG
367
368 SelectObject( (HDC) dc, sel? penShadow : penLight);
4676948b
JS
369 wxDrawLine((HDC) dc, left+1, top+1, right-2, top+1);
370 wxDrawLine((HDC) dc, left+1, top+2, left+1, bottom-2);
5ab1fa8e
GRG
371
372 SelectObject( (HDC) dc, sel? penLight : penShadow);
4676948b
JS
373 wxDrawLine((HDC) dc, left+1, bottom-2, right-1, bottom-2);
374 wxDrawLine((HDC) dc, right-2, bottom-3, right-2, top);
5ab1fa8e
GRG
375
376 SelectObject( (HDC) dc, sel? penHiLight : penDkShadow);
4676948b
JS
377 wxDrawLine((HDC) dc, left, bottom-1, right+2, bottom-1);
378 wxDrawLine((HDC) dc, right-1, bottom-2, right-1, top-1);
5ab1fa8e
GRG
379
380 // delete allocated resources
381 SelectObject((HDC) dc,oldp);
382 DeleteObject(penHiLight);
383 DeleteObject(penLight);
384 DeleteObject(penShadow);
385 DeleteObject(penDkShadow);
386 DeleteObject(brushFace);
387}
388
a265d21a
DS
389void wxBitmapButton::DrawButtonFocus( WXHDC dc, int left, int top, int right,
390 int bottom, bool WXUNUSED(sel) )
2bda0e17 391{
fd3f686c
VZ
392 RECT rect;
393 rect.left = left;
394 rect.top = top;
395 rect.right = right;
396 rect.bottom = bottom;
5ab1fa8e
GRG
397 InflateRect( &rect, - FOCUS_MARGIN, - FOCUS_MARGIN );
398
399 // GRG: the focus rectangle should not move when the button is pushed!
400/*
fd3f686c 401 if ( sel )
5ab1fa8e
GRG
402 OffsetRect( &rect, 1, 1 );
403*/
a265d21a 404
5ab1fa8e 405 DrawFocusRect( (HDC) dc, &rect );
2bda0e17
KB
406}
407
d50dbf7c
VZ
408void
409wxBitmapButton::DrawButtonDisable( WXHDC dc,
410 int left, int top, int right, int bottom,
411 bool with_marg )
2bda0e17 412{
d50dbf7c
VZ
413 if ( !m_brushDisabled.Ok() )
414 {
415 // draw a bitmap with two black and two background colour pixels
416 wxBitmap bmp(2, 2);
417 wxMemoryDC dc;
418 dc.SelectObject(bmp);
419 dc.SetPen(*wxBLACK_PEN);
420 dc.DrawPoint(0, 0);
421 dc.DrawPoint(1, 1);
422 dc.SetPen(GetBackgroundColour());
423 dc.DrawPoint(0, 1);
424 dc.DrawPoint(1, 0);
425
426 m_brushDisabled = wxBrush(bmp);
427 }
428
429 SelectInHDC selectBrush((HDC)dc, GetHbrushOf(m_brushDisabled));
2bda0e17 430
2b268535
VZ
431 // ROP for "dest |= pattern" operation -- as it doesn't have a standard
432 // name, give it our own
a265d21a 433 static const DWORD PATTERNPAINT = 0xFA0089UL;
d9c8e68e
VZ
434
435 if ( with_marg )
436 {
437 left += m_marginX;
438 top += m_marginY;
439 right -= 2 * m_marginX;
440 bottom -= 2 * m_marginY;
441 }
442
a265d21a 443 ::PatBlt( (HDC) dc, left, top, right, bottom, PATTERNPAINT);
2bda0e17
KB
444}
445
0655ad29
VZ
446void wxBitmapButton::SetDefault()
447{
448 wxButton::SetDefault();
449}
1e6feb95 450
c046274e
RD
451wxSize wxBitmapButton::DoGetBestSize() const
452{
9266e0ec 453 if ( m_bmpNormal.Ok() )
c046274e 454 {
31582e4e 455 wxSize best(m_bmpNormal.GetWidth() + 2*m_marginX,
9266e0ec 456 m_bmpNormal.GetHeight() + 2*m_marginY);
31582e4e
RD
457 CacheBestSize(best);
458 return best;
c046274e 459 }
e8153940 460
9266e0ec
VZ
461 // no idea what our best size should be, defer to the base class
462 return wxBitmapButtonBase::DoGetBestSize();
c046274e
RD
463}
464
1e6feb95 465#endif // wxUSE_BMPBUTTON