Added wxRadioButton::MSWWindowProc to reset m_focusJustSet -- otherwise,
[wxWidgets.git] / src / msw / radiobut.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/radiobut.cpp
3 // Purpose: wxRadioButton
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
20 #ifdef __GNUG__
21 #pragma implementation "radiobut.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_RADIOBTN
32
33 #ifndef WX_PRECOMP
34 #include "wx/radiobut.h"
35 #include "wx/settings.h"
36 #include "wx/brush.h"
37 #include "wx/dcscreen.h"
38 #endif
39
40 #include "wx/msw/private.h"
41
42 // ============================================================================
43 // wxRadioButton implementation
44 // ============================================================================
45
46 // ----------------------------------------------------------------------------
47 // wxRadioButton creation
48 // ----------------------------------------------------------------------------
49
50 IMPLEMENT_DYNAMIC_CLASS(wxRadioButton, wxControl)
51
52 void wxRadioButton::Init()
53 {
54 m_focusJustSet = FALSE;
55 }
56
57 bool wxRadioButton::Create(wxWindow *parent,
58 wxWindowID id,
59 const wxString& label,
60 const wxPoint& pos,
61 const wxSize& size,
62 long style,
63 const wxValidator& validator,
64 const wxString& name)
65 {
66 if ( !CreateControl(parent, id, pos, size, style, validator, name) )
67 return FALSE;
68
69 long msStyle = HasFlag(wxRB_GROUP) ? WS_GROUP : 0;
70
71 msStyle |= BS_AUTORADIOBUTTON;
72
73 if ( HasFlag(wxCLIP_SIBLINGS) )
74 msStyle |= WS_CLIPSIBLINGS;
75
76 if ( !MSWCreateControl(_T("BUTTON"), msStyle, pos, size, label, 0) )
77 return FALSE;
78
79 // for compatibility with wxGTK, the first radio button in a group is
80 // always checked (this makes sense anyhow as you need to ensure that at
81 // least one button in the group is checked and this is the simlpest way to
82 // do it)
83 if ( HasFlag(wxRB_GROUP) )
84 SetValue(TRUE);
85
86 return TRUE;
87 }
88
89 // ----------------------------------------------------------------------------
90 // wxRadioButton functions
91 // ----------------------------------------------------------------------------
92
93 void wxRadioButton::SetValue(bool value)
94 {
95 // BST_CHECKED is defined as 1, BST_UNCHECKED as 0, so we can just pass
96 // value as is (we don't sue BST_XXX here as they're not defined for Win16)
97 (void)::SendMessage(GetHwnd(), BM_SETCHECK, (WPARAM)value, 0L);
98 }
99
100 bool wxRadioButton::GetValue() const
101 {
102 // NB: this will also return TRUE for BST_INDETERMINATE value if we ever
103 // have 3-state radio buttons
104 return ::SendMessage(GetHwnd(), BM_GETCHECK, 0, 0L) != 0;
105 }
106
107 // ----------------------------------------------------------------------------
108 // wxRadioButton event processing
109 // ----------------------------------------------------------------------------
110
111 void wxRadioButton::Command (wxCommandEvent& event)
112 {
113 SetValue(event.m_commandInt != 0);
114 ProcessCommand(event);
115 }
116
117 void wxRadioButton::SetFocus()
118 {
119 // when the radio button receives a WM_SETFOCUS message it generates a
120 // BN_CLICKED which is totally unexpected and leads to catastrophic results
121 // if you pop up a dialog from the radio button event handler as, when the
122 // dialog is dismissed, the focus is returned to the radio button which
123 // generates BN_CLICKED which leads to showing another dialog and so on
124 // without end!
125 //
126 // to aviod this, we drop the pseudo BN_CLICKED events generated when the
127 // button gains focus
128 m_focusJustSet = TRUE;
129
130 wxControl::SetFocus();
131 }
132
133 bool wxRadioButton::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
134 {
135 if ( param != BN_CLICKED )
136 return FALSE;
137
138 if ( m_focusJustSet )
139 {
140 // see above: we want to ignore this event
141 m_focusJustSet = FALSE;
142 }
143 else // a real clicked event
144 {
145 wxCommandEvent event(wxEVT_COMMAND_RADIOBUTTON_SELECTED, GetId());
146 event.SetEventObject( this );
147 event.SetInt( GetValue() );
148
149 ProcessCommand(event);
150 }
151
152 return TRUE;
153 }
154
155 // ----------------------------------------------------------------------------
156 // wxRadioButton geometry
157 // ----------------------------------------------------------------------------
158
159 wxSize wxRadioButton::DoGetBestSize() const
160 {
161 static int s_radioSize = 0;
162
163 if ( !s_radioSize )
164 {
165 wxScreenDC dc;
166 dc.SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
167
168 s_radioSize = dc.GetCharHeight();
169 }
170
171 wxString str = GetLabel();
172
173 int wRadio, hRadio;
174 if ( !str.empty() )
175 {
176 GetTextExtent(str, &wRadio, &hRadio);
177 wRadio += s_radioSize + GetCharWidth();
178
179 if ( hRadio < s_radioSize )
180 hRadio = s_radioSize;
181 }
182 else
183 {
184 wRadio = s_radioSize;
185 hRadio = s_radioSize;
186 }
187
188 return wxSize(wRadio, hRadio);
189 }
190
191 long wxRadioButton::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
192 {
193 if (nMsg == WM_SETFOCUS)
194 {
195 m_focusJustSet = TRUE;
196
197 long ret = wxControl::MSWWindowProc(nMsg, wParam, lParam);
198
199 m_focusJustSet = FALSE;
200
201 return ret;
202 }
203 return wxControl::MSWWindowProc(nMsg, wParam, lParam);
204 }
205
206 #endif // wxUSE_RADIOBTN