1
2
3
4
5
6 using System;
7 using System.Collections;
8
9 namespace System.Windows
10 {
11 public enum ButtonStyle : long
12 {
13 BS_PUSHBUTTON = 0,
14 BS_DEFPUSHBUTTON = 1,
15 BS_3STATE = 5,
16 BS_AUTO3STATE = 6,
17 BS_AUTOCHECKBOX = 3,
18 BS_AUTORADIOBUTTON = 9,
19 BS_BITMAP = 128u,
20 BS_BOTTOM = 2048,
21 BS_CENTER = 768,
22 BS_CHECKBOX = 2,
23 BS_GROUPBOX = 7,
24 BS_ICON = 64,
25 BS_FLAT = 32768u,
26 BS_LEFT = 256,
27 BS_LEFTTEXT = 32,
28 BS_MULTILINE = 8192,
29 BS_NOTIFY = 16384,
30 BS_OWNERDRAW = 11,
31 BS_PUSHLIKE = 4096,
32 BS_RADIOBUTTON = 4,
33 BS_RIGHT = 512,
34 BS_TOP = 1024,
35 BS_TYPEMASK = 15,
36 BS_VCENTER = 3072
37 }
38
39 public abstract class ButtonBase : Control
40 {
41 public ButtonBase(const string& windowClassName, WindowClassStyle windowClassStyle, WindowStyle style, ExtendedWindowStyle exStyle,
42 const Color& backgroundColor, const string& text, const Point& location, const Size& size, Dock dock, Anchors anchors) :
43 base(windowClassName, windowClassStyle, style, exStyle, backgroundColor, text, location, size, dock, anchors)
44 {
45 }
46 public ButtonBase(ControlCreateParams& controlCreateParams) : base(controlCreateParams)
47 {
48 }
49 [nodiscard]
50 internal Result<bool> OnClickInternal()
51 {
52 ClickEventArgs args;
53 auto result = OnClick(args);
54 if (result.Error()) return result;
55 if (args.errorId != 0)
56 {
57 return Result<bool>(ErrorId(args.errorId));
58 }
59 return Result<bool>(true);
60 }
61 [nodiscard]
62 public Result<bool> DoClick()
63 {
64 ClickEventArgs args;
65 auto result = OnClick(args);
66 if (result.Error()) return result;
67 if (args.errorId != 0)
68 {
69 return Result<bool>(ErrorId(args.errorId));
70 }
71 return Result<bool>(true);
72 }
73 }
74
75 public ControlCreateParams& ButtonControlCreateParams(ControlCreateParams& controlCreateParams, ButtonStyle buttonStyle)
76 {
77 controlCreateParams.SetWindowClassName("BUTTON");
78 controlCreateParams.SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | buttonStyle));
79 controlCreateParams.SetWindowClassBackgroundColor(SystemColor.COLOR_BTNFACE);
80 controlCreateParams.SetBackgroundColor(GetSystemColor(SystemColor.COLOR_BTNFACE));
81 return controlCreateParams;
82 }
83
84 public ControlCreateParams& ButtonControlCreateParams(ControlCreateParams& controlCreateParams, bool setDefault)
85 {
86 ButtonStyle buttonStyle = ButtonStyle();
87 if (setDefault)
88 {
89 buttonStyle = cast<ButtonStyle>(buttonStyle | ButtonStyle.BS_DEFPUSHBUTTON | ButtonStyle.BS_NOTIFY);
90 }
91 else
92 {
93 buttonStyle = cast<ButtonStyle>(buttonStyle | ButtonStyle.BS_PUSHBUTTON | ButtonStyle.BS_NOTIFY);
94 }
95 return ButtonControlCreateParams(controlCreateParams, buttonStyle);
96 }
97
98 public ControlCreateParams& ButtonControlCreateParams(ControlCreateParams& controlCreateParams)
99 {
100 return ButtonControlCreateParams(controlCreateParams, false);
101 }
102
103 public class ButtonCreateParams
104 {
105 public ButtonCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_)
106 {
107 }
108 public ButtonCreateParams& Defaults()
109 {
110 return *this;
111 }
112 public ControlCreateParams& controlCreateParams;
113 }
114
115 public class Button : ButtonBase
116 {
117 private enum Flags : sbyte
118 {
119 none = 0, defaultButton = 1 << 0
120 }
121 public Button(ButtonStyle buttonStyle, const Color& backgroundColor, const string& text, const Point& location, const Size& size,
122 Dock dock, Anchors anchors) :
123 base("BUTTON", DefaultWindowClassStyle(), cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | buttonStyle),
124 DefaultExtendedWindowStyle(),
125 backgroundColor, text, location, size, dock, anchors), flags(Flags.none), dialogResult(DialogResult.none)
126 {
127 SetFlagsFromButtonStyle(buttonStyle);
128 }
129 public Button(const string& text, const Point& location, const Size& size, Dock dock, Anchors anchors) :
130 this(cast<ButtonStyle>(ButtonStyle.BS_PUSHBUTTON | ButtonStyle.BS_NOTIFY), GetSystemColor(SystemColor.COLOR_BTNFACE), text, location, size, dock, anchors)
131 {
132 }
133 public Button(ButtonStyle buttonStyle, const string& text, const Point& location, const Size& size) :
134 this(buttonStyle, GetSystemColor(SystemColor.COLOR_BTNFACE), text, location, size, Dock.none, cast<Anchors>(Anchors.top | Anchors.left))
135 {
136 }
137 public Button(const string& text, const Point& location, const Size& size) :
138 this(cast<ButtonStyle>(ButtonStyle.BS_PUSHBUTTON | ButtonStyle.BS_NOTIFY), text, location, size)
139 {
140 }
141 public Button(ButtonCreateParams& createParams) :
142 base(createParams.controlCreateParams), flags(Flags.none), dialogResult(DialogResult.none)
143 {
144 SetFlagsFromButtonStyle(cast<ButtonStyle>(cast<long>(createParams.controlCreateParams.windowStyle)));
145 }
146 protected override Result<bool> OnCreated()
147 {
148 auto result = base->OnCreated();
149 if (result.Error())
150 {
151 return Result<bool>(ErrorId(result.GetErrorId()));
152 }
153 auto graphicsResult = Graphics.FromWindowHandle(Handle());
154 if (graphicsResult.Error())
155 {
156 return Result<bool>(ErrorId(graphicsResult.GetErrorId()));
157 }
158 else
159 {
160 Graphics& graphics = graphicsResult.Value();
161 Result<FontHandle*> fontHandleResult = GetFontHandle(graphics);
162 if (fontHandleResult.Error())
163 {
164 return Result<bool>(ErrorId(fontHandleResult.GetErrorId()));
165 }
166 else
167 {
168 FontHandle* fontHandle = fontHandleResult.Value();
169 if (!fontHandle->IsNull())
170 {
171 SendSetFontMessage(*fontHandle);
172 }
173 }
174 }
175 return Result<bool>(true);
176 }
177 [nodiscard]
178 protected override Result<bool> OnGotFocus()
179 {
180 auto result = base->OnGotFocus();
181 if (result.Error()) return result;
182 if (!IsDefault())
183 {
184 Window* window = GetWindow();
185 if (window != null)
186 {
187 Button* defaultButton = window->DefaultButton();
188 if (defaultButton != null)
189 {
190 defaultButton->ResetDefaultButtonStyle();
191 }
192 }
193 SetDefaultButtonStyle();
194 }
195 return Result<bool>(true);
196 }
197 [nodiscard]
198 protected override Result<bool> OnLostFocus()
199 {
200 auto result = base->OnLostFocus();
201 if (result.Error()) return result;
202 if (!IsDefault())
203 {
204 ResetDefaultButtonStyle();
205 Window* window = GetWindow();
206 if (window != null)
207 {
208 Button* defaultButton = window->DefaultButton();
209 if (defaultButton != null)
210 {
211 defaultButton->SetDefaultButtonStyle();
212 }
213 }
214 }
215 return Result<bool>(true);
216 }
217 [nodiscard]
218 protected override Result<bool> OnClick(ClickEventArgs& args)
219 {
220 auto result = base->OnClick(args);
221 if (result.Error()) return result;
222 if (dialogResult != DialogResult.none)
223 {
224 Window* window = GetWindow();
225 if (window != null)
226 {
227 window->SetDialogResult(dialogResult);
228 }
229 }
230 return Result<bool>(true);
231 }
232 [nodiscard]
233 protected override Result<bool> OnKeyDown(KeyEventArgs& args)
234 {
235 auto result = base->OnKeyDown(args);
236 if (result.Error()) return result;
237 if (!args.handled)
238 {
239 switch (args.key)
240 {
241 case Keys.enter:
242 {
243 ClickEventArgs clickEventArgs;
244 result = OnClick(clickEventArgs);
245 if (result.Error()) return result;
246 if (clickEventArgs.errorId != 0)
247 {
248 return Result<bool>(ErrorId(clickEventArgs.errorId));
249 }
250 break;
251 }
252 }
253 }
254 return Result<bool>(true);
255 }
256 [nodiscard]
257 public override Result<bool> PrintWindowTree(int level)
258 {
259 LogView* log = Application.GetLogView();
260 if (log != null)
261 {
262 auto handleResult = ToHexString(cast<ulong>(Handle()));
263 if (handleResult.Error())
264 {
265 return Result<bool>(ErrorId(handleResult.GetErrorId()));
266 }
267 const string& handleStr = handleResult.Value();
268 auto parentTextResult = ParentText();
269 if (parentTextResult.Error())
270 {
271 return Result<bool>(ErrorId(parentTextResult.GetErrorId()));
272 }
273 const string& parentText = parentTextResult.Value();
274 auto result = log->WriteLine(string(' ', level) + "Button." + Text() + ".handle=" + handleStr + " " + parentText +
275 "[" + Rect(Point(), GetSize()).ToString() + "]");
276 if (result.Error()) return result;
277 }
278 return Result<bool>(true);
279 }
280 public inline DialogResult GetDialogResult() const
281 {
282 return dialogResult;
283 }
284 public inline void SetDialogResult(DialogResult dialogResult_)
285 {
286 dialogResult = dialogResult_;
287 }
288 private void SetFlagsFromButtonStyle(ButtonStyle buttonStyle)
289 {
290 if ((buttonStyle & ButtonStyle.BS_DEFPUSHBUTTON) != 0)
291 {
292 flags = cast<Flags>(flags | Flags.defaultButton);
293 }
294 }
295 public inline bool IsDefault() const
296 {
297 return (flags & Flags.defaultButton) != Flags.none;
298 }
299 public void SetDefault()
300 {
301 flags = cast<Flags>(flags | Flags.defaultButton);
302 SetDefaultButtonStyle();
303 }
304 public void ResetDefault()
305 {
306 flags = cast<Flags>(flags & ~Flags.defaultButton);
307 ResetDefaultButtonStyle();
308 }
309 private void SetDefaultButtonStyle()
310 {
311 if (Handle() != null)
312 {
313 WinSendMessage(Handle(), BM_SETSTYLE, cast<uint>(GetWindowStyle() | ButtonStyle.BS_DEFPUSHBUTTON), cast<long>(true));
314 }
315 }
316 private void ResetDefaultButtonStyle()
317 {
318 if (Handle() != null)
319 {
320 WinSendMessage(Handle(), BM_SETSTYLE, cast<uint>(GetWindowStyle() & ~ButtonStyle.BS_DEFPUSHBUTTON), cast<long>(true));
321 }
322 }
323 private Flags flags;
324 private DialogResult dialogResult;
325 }