1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 using System.Collections;
  8 
  9 namespace System.Windows
 10 {
 11     public enum ButtonStyle : long
 12     {
 13         BS_PUSHBUTTON = 0x0
 14         BS_DEFPUSHBUTTON = 0x1
 15         BS_3STATE = 0x5
 16         BS_AUTO3STATE = 0x6
 17         BS_AUTOCHECKBOX = 0x3
 18         BS_AUTORADIOBUTTON = 0x9
 19         BS_BITMAP = 0x80
 20         BS_BOTTOM = 0x800
 21         BS_CENTER = 0x300
 22         BS_CHECKBOX = 0x2
 23         BS_GROUPBOX = 0x7
 24         BS_ICON = 0x40
 25         BS_FLAT = 0x8000
 26         BS_LEFT = 0x100
 27         BS_LEFTTEXT = 0x20
 28         BS_MULTILINE = 0x2000
 29         BS_NOTIFY = 0x4000
 30         BS_OWNERDRAW = 0x0B
 31         BS_PUSHLIKE = 0x1000
 32         BS_RADIOBUTTON = 0x4
 33         BS_RIGHT = 0x200
 34         BS_TOP = 0x400
 35         BS_TYPEMASK = 0xF
 36         BS_VCENTER = 0xC00
 37     }
 38 
 39     public abstract class ButtonBase : Control
 40     {
 41         public ButtonBase(const string& windowClassNameWindowClassStyle windowClassStyleWindowStyle styleExtendedWindowStyle exStyle
 42             const Color& backgroundColorconst string& textconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
 43             base(windowClassNamewindowClassStylestyleexStylebackgroundColortextlocationsizedockanchors)
 44         {
 45         }
 46         public ButtonBase(ControlCreateParams& controlCreateParams) : base(controlCreateParams)
 47         {
 48         }
 49         internal void OnClickInternal()
 50         {
 51             OnClick();
 52         }
 53         public void DoClick()
 54         {
 55             OnClick();
 56         }
 57     }
 58 
 59     public nothrow ControlCreateParams& ButtonControlCreateParams(ControlCreateParams& controlCreateParamsButtonStyle buttonStyle)
 60     {
 61         controlCreateParams.SetWindowClassName("BUTTON");
 62         controlCreateParams.SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | buttonStyle));
 63         controlCreateParams.SetWindowClassBackgroundColor(SystemColor.COLOR_BTNFACE);
 64         controlCreateParams.SetBackgroundColor(GetSystemColor(SystemColor.COLOR_BTNFACE));
 65         return controlCreateParams;
 66     }
 67 
 68     public nothrow ControlCreateParams& ButtonControlCreateParams(ControlCreateParams& controlCreateParamsbool setDefault)
 69     {
 70         ButtonStyle buttonStyle = ButtonStyle();
 71         if (setDefault)
 72         {
 73             buttonStyle = cast<ButtonStyle>(buttonStyle | ButtonStyle.BS_DEFPUSHBUTTON | ButtonStyle.BS_NOTIFY);
 74         }
 75         else
 76         {
 77             buttonStyle = cast<ButtonStyle>(buttonStyle | ButtonStyle.BS_PUSHBUTTON | ButtonStyle.BS_NOTIFY);
 78         }
 79         return ButtonControlCreateParams(controlCreateParamsbuttonStyle);
 80     }
 81 
 82     public nothrow ControlCreateParams& ButtonControlCreateParams(ControlCreateParams& controlCreateParams)
 83     {
 84         return ButtonControlCreateParams(controlCreateParamsfalse);
 85     }
 86 
 87     public class ButtonCreateParams
 88     {
 89         public ButtonCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_)
 90         {
 91         }
 92         public nothrow ButtonCreateParams& Defaults()
 93         {
 94             return *this;
 95         }
 96         public ControlCreateParams& controlCreateParams;
 97     }
 98 
 99     public class Button : ButtonBase
100     {
101         private enum Flags : sbyte
102         {
103             none = 0defaultButton = 1 << 0
104         }
105         public Button(ButtonStyle buttonStyleconst Color& backgroundColorconst string& textconst Point& locationconst Size& size
106             Dock dockAnchors anchors) : 
107             base("BUTTON"DefaultWindowClassStyle()cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | buttonStyle)
108             DefaultExtendedWindowStyle()
109             backgroundColortextlocationsizedockanchors)flags(Flags.none)dialogResult(DialogResult.none)
110         {
111             SetFlagsFromButtonStyle(buttonStyle);
112         }
113         public Button(const string& textconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
114             this(cast<ButtonStyle>(ButtonStyle.BS_PUSHBUTTON | ButtonStyle.BS_NOTIFY)GetSystemColor(SystemColor.COLOR_BTNFACE)textlocationsizedockanchors)
115         {
116         }
117         public Button(ButtonStyle buttonStyleconst string& textconst Point& locationconst Size& size) : 
118             this(buttonStyleGetSystemColor(SystemColor.COLOR_BTNFACE)textlocationsizeDock.nonecast<Anchors>(Anchors.top | Anchors.left))
119         {
120         }
121         public Button(const string& textconst Point& locationconst Size& size) : 
122             this(cast<ButtonStyle>(ButtonStyle.BS_PUSHBUTTON | ButtonStyle.BS_NOTIFY)textlocationsize)
123         {
124         }
125         public Button(ButtonCreateParams& createParams) : 
126             base(createParams.controlCreateParams)flags(Flags.none)dialogResult(DialogResult.none)
127         {
128             SetFlagsFromButtonStyle(cast<ButtonStyle>(cast<long>(createParams.controlCreateParams.windowStyle)));
129         }
130         protected override void OnCreated()
131         {
132             base->OnCreated();
133             Graphics graphics = Graphics.FromWindowHandle(Handle());
134             const FontHandle& fontHandle = GetFontHandle(graphics);
135             if (!fontHandle.IsNull())
136             {
137                 SendSetFontMessage(fontHandle);
138             }
139         }
140         protected override void OnGotFocus()
141         {
142             base->OnGotFocus();
143             if (!IsDefault())
144             {
145                 Window* window = GetWindow();
146                 if (window != null)
147                 {
148                     Button* defaultButton = window->DefaultButton();
149                     if (defaultButton != null)
150                     {
151                         defaultButton->ResetDefaultButtonStyle();
152                     }
153                 }
154                 SetDefaultButtonStyle();
155             }
156         }
157         protected override void OnLostFocus()
158         {
159             base->OnLostFocus();
160             if (!IsDefault())
161             {
162                 ResetDefaultButtonStyle();
163                 Window* window = GetWindow();
164                 if (window != null)
165                 {
166                     Button* defaultButton = window->DefaultButton();
167                     if (defaultButton != null)
168                     {
169                         defaultButton->SetDefaultButtonStyle();
170                     }
171                 }
172             }
173         }
174         protected override void OnClick()
175         {
176             base->OnClick();
177             if (dialogResult != DialogResult.none)
178             {
179                 Window* window = GetWindow();
180                 if (window != null)
181                 {
182                     window->SetDialogResult(dialogResult);
183                 }
184             }
185         }
186         protected override void OnKeyDown(KeyEventArgs& args)
187         {
188             base->OnKeyDown(args);
189             if (!args.handled)
190             {
191                 switch (args.key)
192                 {
193                     case Keys.enter:
194                     {
195                         OnClick();
196                         break;
197                     }
198                 }
199             }
200         }
201         public override void PrintWindowTree(int level)
202         {
203             LogView* log = Application.GetLogView();
204             if (log != null)
205             {
206                 log->WriteLine(string(' 'level) + "Button." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point()GetSize()).ToString() + "]");
207             }
208         }
209         public inline nothrow DialogResult GetDialogResult() const
210         {
211             return dialogResult;
212         }
213         public inline nothrow void SetDialogResult(DialogResult dialogResult_)
214         {
215             dialogResult = dialogResult_;
216         }
217         private nothrow void SetFlagsFromButtonStyle(ButtonStyle buttonStyle)
218         {
219             if ((buttonStyle & ButtonStyle.BS_DEFPUSHBUTTON) != 0)
220             {
221                 flags = cast<Flags>(flags | Flags.defaultButton);
222             }
223         }
224         public inline nothrow bool IsDefault() const
225         {
226             return (flags & Flags.defaultButton) != Flags.none;
227         }
228         public void SetDefault()
229         {
230             flags = cast<Flags>(flags | Flags.defaultButton);
231             SetDefaultButtonStyle();
232         }
233         public void ResetDefault()
234         {
235             flags = cast<Flags>(flags & ~Flags.defaultButton);
236             ResetDefaultButtonStyle();
237         }
238         private void SetDefaultButtonStyle()
239         {
240             if (Handle() != null)
241             {
242                 WinSendMessage(Handle()BM_SETSTYLEcast<uint>(GetWindowStyle() | ButtonStyle.BS_DEFPUSHBUTTON)cast<long>(true));
243             }
244         }
245         private void ResetDefaultButtonStyle()
246         {
247             if (Handle() != null)
248             {
249                 WinSendMessage(Handle()BM_SETSTYLEcast<uint>(GetWindowStyle() & ~ButtonStyle.BS_DEFPUSHBUTTON)cast<long>(true));
250             }
251         }
252         private Flags flags;
253         private DialogResult dialogResult;
254     }
255 }