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 class SelectedIndexChangedEventArgs
 11     {
 12         public SelectedIndexChangedEventArgs() : errorId(0)
 13         {
 14         }
 15         public int errorId;
 16     }
 17     
 18     public class delegate void SelectedIndexChangedEventHandler(SelectedIndexChangedEventArgs& args);
 19 
 20     public enum ListBoxStyle : long
 21     {
 22         LBS_COMBOBOX = 32768u
 23         LBS_DISABLENOSCROLL = 4096
 24         LBS_EXTENDEDSEL = 2048
 25         LBS_HASSTRINGS = 64
 26         LBS_MULTICOLUMN = 512
 27         LBS_MULTIPLESEL = 8
 28         LBS_NODATA = 8192
 29         LBS_NOINTEGRALHEIGHT = 256
 30         LBS_NOREDRAW = 4
 31         LBS_NOSEL = 16384
 32         LBS_NOTIFY = 1
 33         LBS_OWNERDRAWFIXED = 16
 34         LBS_OWNERDRAWVARIABLE = 32
 35         LBS_SORT = 2
 36         LBS_STANDARD = LBS_NOTIFY | LBS_SORT | WindowStyle.WS_VSCROLL | WindowStyle.WS_BORDER
 37         LBS_USETABSTOPS = 128u
 38         LBS_WANTKEYBOARDINPUT = 1024
 39     }
 40 
 41     public ControlCreateParams& ListBoxControlCreateParams(ControlCreateParams& controlCreateParamsListBoxStyle listBoxStyle)
 42     {
 43         return controlCreateParams.SetWindowClassName("LISTBOX").
 44             SetWindowClassBackgroundColor(SystemColor.COLOR_WINDOW).SetBackgroundColor(Color.White()).
 45             SetWindowStyle(cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | WindowStyle.WS_VSCROLL | listBoxStyle));
 46     }
 47 
 48     public ControlCreateParams& ListBoxControlCreateParams(ControlCreateParams& controlCreateParams)
 49     {
 50         return ListBoxControlCreateParams(controlCreateParamscast<ListBoxStyle>(ListBoxStyle.LBS_NOTIFY | ListBoxStyle.LBS_HASSTRINGS));
 51     }
 52 
 53     public class ListBoxCreateParams
 54     {
 55         public ListBoxCreateParams(ControlCreateParams& controlCreateParams_) : controlCreateParams(controlCreateParams_)
 56         {
 57         }
 58         public ListBoxCreateParams& Defaults()
 59         {
 60             return *this;
 61         }
 62         public ControlCreateParams& controlCreateParams;
 63     }
 64 
 65     public class ListBox : Control
 66     {
 67         public ListBox(ListBoxStyle listBoxStyleconst Color& backgroundColorconst string& textconst Point& locationconst Size& size
 68             Dock dockAnchors anchors) : 
 69             base("LISTBOX"DefaultWindowClassStyle()cast<WindowStyle>(DefaultChildWindowStyle() | WindowStyle.WS_TABSTOP | listBoxStyle)
 70                 DefaultExtendedWindowStyle()backgroundColortextlocationsizedockanchors)
 71         {
 72         }
 73         public ListBox(const Point& locationconst Size& sizeDock dockAnchors anchors) : 
 74             this(cast<ListBoxStyle>(ListBoxStyle.LBS_NOTIFY | ListBoxStyle.LBS_HASSTRINGS | WindowStyle.WS_VSCROLL)Color.White()
 75             string()locationsizedockanchors)
 76         {
 77         }
 78         public ListBox(ListBoxCreateParams& createParams) : base(createParams.controlCreateParams)
 79         {
 80         }
 81         [nodiscard]
 82         public Result<bool> AddItem(const string& item)
 83         {
 84             if (Handle() != null)
 85             {
 86                 auto utf16Result = ToUtf16(item);
 87                 if (utf16Result.Error())
 88                 {
 89                     return Result<bool>(ErrorId(utf16Result.GetErrorId()));
 90                 }
 91                 wstring wstr(Rvalue(utf16Result.Value()));
 92                 WinSendMessage(Handle()LB_ADDSTRING0ucast<long>(cast<ulong>(cast<void*>(wstr.Chars()))));
 93             }
 94             return Result<bool>(true);
 95         }
 96         public void DeleteItem(int itemIndex)
 97         {
 98             if (Handle() != null)
 99             {
100                 WinSendMessage(Handle()LB_DELETESTRINGcast<uint>(itemIndex)0);
101             }
102         }
103         [nodiscard]
104         public Result<bool> InsertItem(int indexconst string& item)
105         {
106             if (Handle() != null)
107             {
108                 auto utf16Result = ToUtf16(item);
109                 if (utf16Result.Error())
110                 {
111                     return Result<bool>(ErrorId(utf16Result.GetErrorId()));
112                 }
113                 wstring wstr(Rvalue(utf16Result.Value()));
114                 WinSendMessage(Handle()LB_INSERTSTRINGcast<uint>(index)cast<long>(cast<ulong>(cast<void*>(wstr.Chars()))));
115             }
116             return Result<bool>(true);
117         }
118         [nodiscard]
119         public Result<string> GetItem(int index)
120         {
121             if (Handle() != null)
122             {
123                 int size = cast<int>(WinSendMessage(Handle()LB_GETTEXTLENcast<uint>(index)0));
124                 UniquePtr<wchar> buf(cast<wchar*>(MemAlloc(size * sizeof(wchar))));
125                 WinSendMessage(Handle()LB_GETTEXTcast<uint>(index)cast<long>(cast<ulong>(cast<void*>(buf.Get()))));
126                 auto utf8Result = ToUtf8(buf.Get());
127                 if (utf8Result.Error())
128                 {
129                     return Result<string>(ErrorId(utf8Result.GetErrorId()));
130                 }
131                 return Result<string>(utf8Result.Value());
132             }
133             return Result<string>(string());
134         }
135         [nodiscard]
136         public Result<bool> SetItem(int indexconst string& item)
137         {
138             DeleteItem(index);
139             auto insertResult = InsertItem(indexitem);
140             if (insertResult.Error())
141             {
142                 return Result<bool>(ErrorId(insertResult.GetErrorId()));
143             }
144             return Result<bool>(true);
145         }
146         public int GetItemCount() const
147         {
148             if (Handle() != null)
149             {
150                 return cast<int>(WinSendMessage(Handle()LB_GETCOUNT0u0));
151             }
152             else
153             {
154                 return -1;
155             }
156         }
157         public int GetTopIndex() const
158         {
159             if (Handle() != null)
160             {
161                 return cast<int>(WinSendMessage(Handle()LB_GETTOPINDEX0u0));
162             }
163             else
164             {
165                 return -1;
166             }
167         }
168         public void SetTopIndex(int topIndex)
169         {
170             if (Handle() != null)
171             {
172                 WinSendMessage(Handle()LB_SETTOPINDEXcast<uint>(topIndex)0);
173             }
174         }
175         public int GetSelectedIndex() const
176         {
177             if (Handle() != null)
178             {
179                 return cast<int>(WinSendMessage(Handle()LB_GETCURSEL0u0));
180             }
181             else
182             {
183                 return -1;
184             }
185         }
186         public void SetSelectedIndex(int selectedIndex)
187         {
188             if (Handle() != null)
189             {
190                 WinSendMessage(Handle()LB_SETCURSELcast<uint>(selectedIndex)0);
191             }
192         }
193         protected override Result<bool> OnCreated()
194         {
195             auto result = base->OnCreated();
196             if (result.Error())
197             {
198                 return Result<bool>(ErrorId(result.GetErrorId()));
199             }
200             auto graphicsResult = Graphics.FromWindowHandle(Handle());
201             if (graphicsResult.Error())
202             {
203                 return Result<bool>(ErrorId(graphicsResult.GetErrorId()));
204             }
205             else
206             {
207                 Graphics graphics = Rvalue(graphicsResult.Value());
208                 Result<FontHandle*> fontHandleResult = GetFontHandle(graphics);
209                 if (fontHandleResult.Error())
210                 {
211                     return Result<bool>(ErrorId(fontHandleResult.GetErrorId()));
212                 }
213                 else
214                 {
215                     FontHandle* fontHandle = fontHandleResult.Value();
216                     if (!fontHandle->IsNull())
217                     {
218                         SendSetFontMessage(*fontHandle);
219                     }
220                 }
221             }
222             return Result<bool>(true);
223         }
224         [nodiscard]
225         internal Result<bool> SelectedIndexChangedInternal()
226         {
227             SelectedIndexChangedEventArgs args;
228             return OnSelectedIndexChanged(args);
229         }
230         protected virtual Result<bool> OnSelectedIndexChanged(SelectedIndexChangedEventArgs& args)
231         {
232             selectedIndexChangedEvent.Fire(args);
233             if (args.errorId != 0)
234             {
235                 return Result<bool>(ErrorId(args.errorId));
236             }
237             return Result<bool>(true);
238         }
239         public Event<SelectedIndexChangedEventHandlerSelectedIndexChangedEventArgs>& SelectedIndexChangedEvent() const
240         {
241             return selectedIndexChangedEvent;
242         }
243         private Event<SelectedIndexChangedEventHandlerSelectedIndexChangedEventArgs> selectedIndexChangedEvent;
244     }