1
2
3
4
5
6 using System;
7
8 namespace System.Windows
9 {
10 public class delegate void CheckedChangedEventHandler();
11
12 public ControlCreateParams& CheckBoxControlCreateParams(ControlCreateParams& controlCreateParams, ButtonStyle buttonStyle)
13 {
14 controlCreateParams.SetWindowClassName("BUTTON");
15 controlCreateParams.SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | buttonStyle));
16 controlCreateParams.SetBackgroundColor(DefaultControlBackgroundColor());
17 return controlCreateParams;
18 }
19
20 public ControlCreateParams& CheckBoxControlCreateParams(ControlCreateParams& controlCreateParams)
21 {
22 return CheckBoxControlCreateParams(controlCreateParams, cast<ButtonStyle>(ButtonStyle.BS_CHECKBOX | ButtonStyle.BS_NOTIFY));
23 }
24
25 public class CheckBoxCreateParams
26 {
27 public CheckBoxCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_), autoSize(true)
28 {
29 }
30 public CheckBoxCreateParams& Defaults()
31 {
32 return *this;
33 }
34 public CheckBoxCreateParams& SetAutoSize(bool autoSize_)
35 {
36 autoSize = autoSize_;
37 return *this;
38 }
39 public ControlCreateParams& controlCreateParams;
40 public bool autoSize;
41 }
42
43 public class CheckBox : ButtonBase
44 {
45 private enum Flags : sbyte
46 {
47 none = 0, checked = 1 << 0, autoSize = 1 << 1, autoSized = 1 << 2
48 }
49 public CheckBox(const Color& backgroundColor, const string& text, const Point& location, const Size& size, Dock dock, Anchors anchors, bool autoSize) :
50 base("BUTTON", DefaultWindowClassStyle(),
51 cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | ButtonStyle.BS_CHECKBOX | ButtonStyle.BS_NOTIFY),
52 DefaultExtendedWindowStyle(), backgroundColor, text, location, size, dock, anchors), flags(Flags.none)
53 {
54 if (autoSize)
55 {
56 SetAutoSizeFlag();
57 }
58 else
59 {
60 ResetAutoSizeFlag();
61 }
62 }
63 public CheckBox(const string& text, const Point& location, const Size& size, Dock dock, Anchors anchors, bool autoSize) :
64 this(DefaultControlBackgroundColor(), text, location, size, dock, anchors, autoSize)
65 {
66 }
67 public CheckBox(CheckBoxCreateParams& createParams) : base(createParams.controlCreateParams)
68 {
69 if (createParams.autoSize)
70 {
71 SetAutoSizeFlag();
72 }
73 else
74 {
75 ResetAutoSizeFlag();
76 }
77 }
78 public bool Checked()
79 {
80 return GetCheckedFlag();
81 }
82 public void SetChecked(bool checked)
83 {
84 if (checked)
85 {
86 SetCheckedFlag();
87 if (Handle() != null)
88 {
89 WinSendMessage(Handle(), BM_SETCHECK, BST_CHECKED, 0);
90 }
91 }
92 else
93 {
94 ResetCheckedFlag();
95 if (Handle() != null)
96 {
97 WinSendMessage(Handle(), BM_SETCHECK, BST_UNCHECKED, 0);
98 }
99 }
100 }
101 protected override Result<bool> OnCreated()
102 {
103 auto baseResult = base->OnCreated();
104 if (baseResult.Error())
105 {
106 return Result<bool>(ErrorId(baseResult.GetErrorId()));
107 }
108 auto graphicsResult = Graphics.FromWindowHandle(Handle());
109 if (graphicsResult.Error())
110 {
111 return Result<bool>(ErrorId(graphicsResult.GetErrorId()));
112 }
113 Graphics& graphics = graphicsResult.Value();
114 auto fontHandleResult = GetFontHandle(graphics);
115 if (fontHandleResult.Error())
116 {
117 return Result<bool>(ErrorId(fontHandleResult.GetErrorId()));
118 }
119 FontHandle* fontHandle = fontHandleResult.Value();
120 if (!fontHandle->IsNull())
121 {
122 SendSetFontMessage(*fontHandle);
123 }
124 if (GetCheckedFlag())
125 {
126 SetChecked(true);
127 }
128 else
129 {
130 SetChecked(false);
131 }
132 if (GetAutoSizeFlag())
133 {
134 auto result = DoAutoSize();
135 if (result.Error())
136 {
137 return Result<bool>(ErrorId(result.GetErrorId()));
138 }
139 }
140 return Result<bool>(true);
141 }
142 [nodiscard]
143 protected override Result<bool> OnClick(ClickEventArgs& args)
144 {
145 auto result = base->OnClick(args);
146 if (result.Error()) return result;
147 SetChecked(!GetCheckedFlag());
148 return Result<bool>(true);
149 }
150 [nodiscard]
151 protected override Result<bool> OnTextChanged()
152 {
153 auto result = base->OnTextChanged();
154 if (result.Error())
155 {
156 return Result<bool>(ErrorId(result.GetErrorId()));
157 }
158 if (GetAutoSizeFlag())
159 {
160 ResetAutoSized();
161 auto result = DoAutoSize();
162 if (result.Error())
163 {
164 return Result<bool>(ErrorId(result.GetErrorId()));
165 }
166 }
167 return Result<bool>(true);
168 }
169 protected virtual void OnCheckedChanged()
170 {
171 checkedChangedEvent.Fire();
172 }
173 public Event<CheckedChangedEventHandler>& CheckedChangedEvent() const
174 {
175 return checkedChangedEvent;
176 }
177 private void RetrieveCheckedState()
178 {
179 long result = WinSendMessage(Handle(), BM_GETCHECK, 0u, 0);
180 if (result == BST_CHECKED)
181 {
182 SetCheckedFlag();
183 }
184 else
185 {
186 ResetCheckedFlag();
187 }
188 }
189 private Result<bool> DoAutoSize()
190 {
191 if (AutoSized()) return Result<bool>(true);
192 if (Handle() == null) return Result<bool>(false);
193 auto graphicsResult = Graphics.FromWindowHandle(Handle());
194 if (graphicsResult.Error())
195 {
196 return Result<bool>(ErrorId(graphicsResult.GetErrorId()));
197 }
198 Graphics& graphics = graphicsResult.Value();
199 const Font& font = GetFont();
200 StringFormat stringFormat;
201 if (stringFormat.Error())
202 {
203 return Result<bool>(ErrorId(stringFormat.GetErrorId()));
204 }
205 auto measureResult = graphics.MeasureStringRectF(Text(), font, PointF(0, 0), stringFormat);
206 if (measureResult.Error())
207 {
208 return Result<bool>(ErrorId(measureResult.GetErrorId()));
209 }
210 RectF r = measureResult.Value();
211 Size checkSize = GetCheckSize();
212 Size borderSize = GetBorderSize();
213 r.size.w = r.size.w + checkSize.w + borderSize.w;
214 r.size.h = Max(r.size.h, checkSize.h + borderSize.h);
215 auto result = SetSize(Size(cast<int>(r.size.w), cast<int>(r.size.h)));
216 if (result.Error()) return result;
217 SetAutoSized();
218 return Result<bool>(true);
219 }
220 private Size GetCheckSize()
221 {
222 int x = GetSystemMetrics(SystemMetricsId.SM_CXMENUCHECK);
223 int y = GetSystemMetrics(SystemMetricsId.SM_CYMENUCHECK);
224 return Size(x, y);
225 }
226 private Size GetBorderSize()
227 {
228 int x = GetSystemMetrics(SystemMetricsId.SM_CXBORDER);
229 int y = GetSystemMetrics(SystemMetricsId.SM_CYBORDER);
230 return Size(x, y);
231 }
232 private inline bool GetCheckedFlag() const
233 {
234 return (flags & Flags.checked) != Flags.none;
235 }
236 private void SetCheckedFlag()
237 {
238 if (!GetCheckedFlag())
239 {
240 flags = cast<Flags>(flags | Flags.checked);
241 OnCheckedChanged();
242 }
243 }
244 private void ResetCheckedFlag()
245 {
246 if (GetCheckedFlag())
247 {
248 flags = cast<Flags>(flags & ~Flags.checked);
249 OnCheckedChanged();
250 }
251 }
252 private inline bool GetAutoSizeFlag() const
253 {
254 return (flags & Flags.autoSize) != Flags.none;
255 }
256 private inline void SetAutoSizeFlag()
257 {
258 flags = cast<Flags>(flags | Flags.autoSize);
259 }
260 private inline void ResetAutoSizeFlag()
261 {
262 flags = cast<Flags>(flags & ~Flags.autoSize);
263 }
264 private inline bool AutoSized() const
265 {
266 return (flags & Flags.autoSized) != Flags.none;
267 }
268 private inline void SetAutoSized()
269 {
270 flags = cast<Flags>(flags | Flags.autoSized);
271 }
272 private inline void ResetAutoSized()
273 {
274 flags = cast<Flags>(flags & ~Flags.autoSized);
275 }
276 private Flags flags;
277 private Event<CheckedChangedEventHandler> checkedChangedEvent;
278 }