]> git.saurik.com Git - wxWidgets.git/blob - src/msw/button.cpp
Improved wxFileDialog behaviour wrt to remembering filenames
[wxWidgets.git] / src / msw / button.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        button.cpp
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
9 // Licence:     wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19 #ifdef __GNUG__
20     #pragma implementation "button.h"
21 #endif
22
23 // For compilers that support precompilation, includes "wx.h".
24 #include "wx/wxprec.h"
25
26 #ifdef __BORLANDC__
27     #pragma hdrstop
28 #endif
29
30 #ifndef WX_PRECOMP
31     #include "wx/button.h"
32     #include "wx/brush.h"
33     #include "wx/panel.h"
34     #include "wx/bmpbuttn.h"
35     #include "wx/settings.h"
36     #include "wx/dcscreen.h"
37 #endif
38
39 #include "wx/msw/private.h"
40
41 // ----------------------------------------------------------------------------
42 // macros
43 // ----------------------------------------------------------------------------
44
45 #if !USE_SHARED_LIBRARY
46     IMPLEMENT_DYNAMIC_CLASS(wxButton, wxControl)
47 #endif
48
49 // this macro tries to adjust the default button height to a reasonable value
50 // using the char height as the base
51 #define BUTTON_HEIGHT_FROM_CHAR_HEIGHT(cy) (11*EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy)/10)
52
53 // ============================================================================
54 // implementation
55 // ============================================================================
56
57 // ----------------------------------------------------------------------------
58 // creation/destruction
59 // ----------------------------------------------------------------------------
60
61 bool wxButton::Create(wxWindow *parent,
62                       wxWindowID id,
63                       const wxString& label,
64                       const wxPoint& pos,
65                       const wxSize& size,
66                       long style,
67                       const wxValidator& validator,
68                       const wxString& name)
69 {
70     if ( !CreateBase(parent, id, pos, size, style, validator, name) )
71         return FALSE;
72
73     // Validator was set in CreateBase
74     //SetValidator(validator);
75
76     parent->AddChild((wxButton *)this);
77
78     m_backgroundColour = parent->GetBackgroundColour() ;
79     m_foregroundColour = parent->GetForegroundColour() ;
80
81     m_hWnd = (WXHWND)CreateWindowEx
82                      (
83                       MakeExtendedStyle(m_windowStyle),
84                       _T("BUTTON"),
85                       label,
86                       WS_VISIBLE | WS_TABSTOP | WS_CHILD,
87                       0, 0, 0, 0,
88                       GetWinHwnd(parent),
89                       (HMENU)m_windowId,
90                       wxGetInstance(),
91                       NULL
92                      );
93
94     // Subclass again for purposes of dialog editing mode
95     SubclassWin(m_hWnd);
96
97     SetFont(parent->GetFont());
98
99     SetSize(pos.x, pos.y, size.x, size.y);
100
101     // bad hack added by Robert to make buttons at least
102     // 80 pixels wide. There are probably better ways...
103     // TODO. FIXME.
104     wxSize nsize( GetSize() );
105     if ((nsize.x < 80) || (nsize.y < 23))
106     {
107         if ((size.x == -1) && (nsize.x < 80)) nsize.x = 80;
108         if ((size.y == -1) && (nsize.y < 23)) nsize.y = 23;
109         SetSize( nsize );
110     }
111
112     return TRUE;
113 }
114
115 wxButton::~wxButton()
116 {
117     wxPanel *panel = wxDynamicCast(GetParent(), wxPanel);
118     if ( panel )
119     {
120         if ( panel->GetDefaultItem() == this )
121         {
122             // don't leave the panel with invalid default item
123             panel->SetDefaultItem(NULL);
124         }
125     }
126 }
127
128 // ----------------------------------------------------------------------------
129 // size management including autosizing
130 // ----------------------------------------------------------------------------
131
132 wxSize wxButton::DoGetBestSize()
133 {
134     wxString label = wxGetWindowText(GetHWND());
135     int wBtn;
136     GetTextExtent(label, &wBtn, NULL);
137
138     int wChar, hChar;
139     wxGetCharSize(GetHWND(), &wChar, &hChar, &GetFont());
140
141     // add a margin - the button is wider than just its label
142     wBtn += 3*wChar;
143
144     // the button height is proportional to the height of the font used
145     int hBtn = BUTTON_HEIGHT_FROM_CHAR_HEIGHT(hChar);
146
147     return wxSize(wBtn, hBtn);
148 }
149
150 /* static */
151 wxSize wxButton::GetDefaultSize()
152 {
153     static wxSize s_sizeBtn;
154
155     if ( s_sizeBtn.x == 0 )
156     {
157         wxScreenDC dc;
158         dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
159
160         // the size of a standard button in the dialog units is 50x14,
161         // translate this to pixels
162         // NB1: the multipliers come from the Windows convention
163         // NB2: the extra +1/+2 were needed to get the size be the same as the
164         //      size of the buttons in the standard dialog - I don't know how
165         //      this happens, but on my system this size is 75x23 in pixels and
166         //      23*8 isn't even divisible by 14... Would be nice to understand
167         //      why these constants are needed though!
168         s_sizeBtn.x = (50 * (dc.GetCharWidth() + 1))/4;
169         s_sizeBtn.y = ((14 * dc.GetCharHeight()) + 2)/8;
170     }
171
172     return s_sizeBtn;
173 }
174
175 // ----------------------------------------------------------------------------
176 // set this button as the default one in its panel
177 // ----------------------------------------------------------------------------
178
179 void wxButton::SetDefault()
180 {
181     wxWindow *parent = GetParent();
182     wxButton *btnOldDefault = NULL;
183     wxPanel *panel = wxDynamicCast(parent, wxPanel);
184     if ( panel )
185     {
186         btnOldDefault = panel->GetDefaultItem();
187         panel->SetDefaultItem(this);
188     }
189
190     if ( parent )
191     {
192         SendMessage(GetWinHwnd(parent), DM_SETDEFID, m_windowId, 0L);
193     }
194
195     // this doesn't work with bitmap buttons because it also removes the
196     // "ownerdrawn" style...
197     if ( btnOldDefault && !wxDynamicCast(btnOldDefault, wxBitmapButton) )
198     {
199         // remove the BS_DEFPUSHBUTTON style from the other button
200         long style = GetWindowLong(GetHwndOf(btnOldDefault), GWL_STYLE);
201         style &= ~BS_DEFPUSHBUTTON;
202         SendMessage(GetHwndOf(btnOldDefault), BM_SETSTYLE, style, 1L);
203     }
204
205     // set this button as the default
206     long style = GetWindowLong(GetHwnd(), GWL_STYLE);
207     style |= BS_DEFPUSHBUTTON;
208     SendMessage(GetHwnd(), BM_SETSTYLE, style, 1L);
209 }
210
211 // ----------------------------------------------------------------------------
212 // helpers
213 // ----------------------------------------------------------------------------
214
215 bool wxButton::SendClickEvent()
216 {
217     wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
218     event.SetEventObject(this);
219
220     return ProcessCommand(event);
221 }
222
223 void wxButton::Command(wxCommandEvent & event)
224 {
225     ProcessCommand(event);
226 }
227
228 // ----------------------------------------------------------------------------
229 // event/message handlers
230 // ----------------------------------------------------------------------------
231
232 bool wxButton::MSWCommand(WXUINT param, WXWORD id)
233 {
234     bool processed = FALSE;
235     switch ( param )
236     {
237         case 1:                                             // 1 for accelerator
238         case BN_CLICKED:
239             processed = SendClickEvent();
240             break;
241     }
242
243     return processed;
244 }
245
246 WXHBRUSH wxButton::OnCtlColor(WXHDC pDC,
247                               WXHWND pWnd,
248                               WXUINT nCtlColor,
249                               WXUINT message,
250                               WXWPARAM wParam,
251                               WXLPARAM lParam)
252 {
253   wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID);
254
255   return (WXHBRUSH) backgroundBrush->GetResourceHandle();
256 }
257