1 // =================================
  2 // Copyright (c) 2024 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Windows
  9 {
 10     public enum TextBoxStyle : long
 11     {
 12         ES_AUTOHSCROLL = 128u
 13         ES_AUTOVSCROLL = 64
 14         ES_CENTER = 1
 15         ES_LEFT = 0
 16         ES_LOWERCASE = 16
 17         ES_MULTILINE = 4
 18         ES_NOHIDESEL = 256
 19         ES_NUMBER = 8192
 20         ES_OEMCONVERT = 1024
 21         ES_PASSWORD = 32
 22         ES_READONLY = 2048
 23         ES_RIGHT = 2
 24         ES_UPPERCASE = 8
 25         ES_WANTRETURN = 4096
 26     }
 27 
 28     public ControlCreateParams& TextBoxControlCreateParams(ControlCreateParams& controlCreateParamsTextBoxStyle textBoxStyle)
 29     {
 30         return controlCreateParams.SetWindowClassName("EDIT").SetWindowClassBackgroundColor(SystemColor.COLOR_WINDOW).SetBackgroundColor(Color.White()).
 31             SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | textBoxStyle));
 32     }
 33 
 34     public ControlCreateParams& TextBoxControlCreateParams(ControlCreateParams& controlCreateParams)
 35     {
 36         return TextBoxControlCreateParams(controlCreateParamscast<TextBoxStyle>(TextBoxStyle.ES_LEFT | TextBoxStyle.ES_AUTOHSCROLL));
 37     }
 38 
 39     public class TextBoxCreateParams
 40     {
 41         public TextBoxCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_)
 42         {
 43         }
 44         public TextBoxCreateParams& Defaults()
 45         {
 46             return *this;
 47         }
 48         public ControlCreateParams& controlCreateParams;
 49     }
 50 
 51     public class TextBox : Control
 52     {
 53         private enum Flags : sbyte
 54         {
 55             none = 0selectAll = 1 << 0multiline = 1 << 1
 56         }
 57 
 58         public TextBox(TextBoxStyle textBoxStyleconst Color& backgroundColorconst string& textconst Point& locationconst Size& size
 59             Dock dockAnchors anchors) : 
 60             base("EDIT"DefaultWindowClassStyle()cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | textBoxStyle)
 61             DefaultExtendedWindowStyle()backgroundColortextlocationsizedockanchors)
 62         {
 63             if ((textBoxStyle & TextBoxStyle.ES_MULTILINE) != 0)
 64             {
 65                 SetMultiline();
 66             }
 67         }
 68         public TextBox(const string& textconst Point& locationconst Size& sizeDock dockAnchors anchors) : 
 69             this(cast<TextBoxStyle>(TextBoxStyle.ES_LEFT | TextBoxStyle.ES_AUTOHSCROLL)Color.White()textlocationsizedockanchors)
 70         {
 71         }
 72         public TextBox(const string& text) : this(textPoint()Size()Dock.noneAnchors.none)
 73         {
 74         }
 75         public TextBox(TextBoxCreateParams& createParams) : base(createParams.controlCreateParams)
 76         {
 77             if ((cast<TextBoxStyle>(cast<long>(createParams.controlCreateParams.windowStyle)) & TextBoxStyle.ES_MULTILINE) != 0)
 78             {
 79                 SetMultiline();
 80             }
 81         }
 82         public inline bool IsMultiline() const
 83         {
 84             return (flags & Flags.multiline) != Flags.none;
 85         }
 86         private inline void SetMultiline()
 87         {
 88             flags = cast<Flags>(flags | Flags.multiline);
 89         }
 90         private inline void ResetMultiline()
 91         {
 92             flags = cast<Flags>(flags & ~Flags.multiline);
 93         }
 94         public void SelectAll()
 95         {
 96             if (Handle() != null)
 97             {
 98                 WinSendMessage(Handle()EM_SETSEL0u-1);
 99             }
100             else
101             {
102                 SetSelectAllFlag();
103             }
104         }
105         [nodiscard]
106         public Result<bool> Clear()
107         {
108             return SetText(string());
109         }
110         protected override Result<bool> OnCreated()
111         {
112             auto result = base->OnCreated();
113             if (result.Error())
114             {
115                 return Result<bool>(ErrorId(result.GetErrorId()));
116             }
117             auto graphicsResult = Graphics.FromWindowHandle(Handle());
118             if (graphicsResult.Error())
119             {
120                 return Result<bool>(ErrorId(graphicsResult.GetErrorId()));
121             }
122             Graphics& graphics = graphicsResult.Value();
123             Result<FontHandle*> fontHandleResult = GetFontHandle(graphics);
124             if (fontHandleResult.Error())
125             {
126                 return Result<bool>(ErrorId(fontHandleResult.GetErrorId()));
127             }
128             else
129             {
130                 FontHandle* fontHandle = fontHandleResult.Value();
131                 if (!fontHandle->IsNull())
132                 {
133                     SendSetFontMessage(*fontHandle);
134                 }
135                 if (SelectAllFlagSet())
136                 {
137                     ResetSelectAllFlag();
138                     SelectAll();
139                 }
140             }
141             return Result<bool>(true);
142         }
143         [nodiscard]
144         protected override Result<bool> OnGotFocus()
145         {
146             auto result = base->OnGotFocus();
147             if (result.Error()) return result;
148             SelectAll();
149             return Result<bool>(true);
150         }
151         private inline bool SelectAllFlagSet() const
152         {
153             return (flags & Flags.selectAll) != Flags.none;
154         }
155         private inline void SetSelectAllFlag()
156         {
157             flags = cast<Flags>(flags | Flags.selectAll);
158         }
159         private inline void ResetSelectAllFlag()
160         {
161             flags = cast<Flags>(flags & ~Flags.selectAll);
162         }
163         private Flags flags;
164     }