1 // =================================
  2 // Copyright (c) 2021 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 using System;
  7 
  8 namespace System.Windows
  9 {
 10     public class delegate void WindowClosingEventHandler(bool& cancelClose);
 11 
 12     public class delegate void WindowClosedEventHandler();
 13 
 14     public delegate int GetDialogResultFunction(void* dialogWindowPtr);
 15 
 16     public delegate void DialogWindowKeyPreviewFunction(void* windowPtruint keyCodebool shiftbool controlbool altbool keyDownbool& handled);
 17 
 18     public delegate void ModelessWindowKeyPreviewFunction(uint keyCodebool shiftbool controlbool altbool keyDownbool& handled);
 19 
 20     public class delegate void KeyPreviewMethod(Keys keybool shiftbool controlbool altbool keyDownbool& handled);
 21 
 22     public nothrow Color DefaultWindowBackgroundColor()
 23     {
 24         return GetSystemColor(SystemColor.COLOR_WINDOW);
 25     }
 26 
 27     public string DefaultWindowFontFamilyName()
 28     {
 29         return "Microsoft Sans Serif";
 30     }
 31 
 32     public nothrow float DefaultWindowFontSize()
 33     {
 34         return 8.25f;
 35     }
 36 
 37     internal class DialogGuard
 38     {
 39         public nothrow DialogGuard(Window* window_) : window(window_)
 40         {
 41             window->SetShowingDialog();
 42         }
 43         public ~DialogGuard()
 44         {
 45             window->ResetShowingDialog();
 46         }
 47         private Window* window;
 48     }
 49 
 50     public nothrow ControlCreateParams& WindowControlCreateParams(ControlCreateParams& controlCreateParams
 51         const string& windowClassNameconst string& captionconst Point& locationconst Size& size)
 52     {
 53         return controlCreateParams.SetWindowClassName(windowClassName).
 54             SetWindowClassStyle(cast<WindowClassStyle>(WindowClassStyle.CS_VREDRAW | WindowClassStyle.CS_HREDRAW)).
 55             SetWindowStyle(WindowStyle.WS_OVERLAPPEDWINDOW).SetText(caption).SetLocation(location).SetSize(size);
 56     }
 57 
 58     public nothrow ControlCreateParams& WindowControlCreateParams(ControlCreateParams& controlCreateParamsconst string& caption)
 59     {
 60         return WindowControlCreateParams(controlCreateParams"System.Windows.Window"captionPoint.Default()Size.Default());
 61     }
 62     
 63     public class WindowCreateParams
 64     {
 65         public nothrow WindowCreateParams(ControlCreateParams& controlCreateParams_) : 
 66             controlCreateParams(controlCreateParams_)
 67             fontFamilyName(DefaultWindowFontFamilyName())
 68             fontSize(DefaultWindowFontSize())
 69             fontStyle(FontStyle.regular)
 70             state(WindowState.normal)
 71         {
 72         }
 73         public nothrow WindowCreateParams& Defaults()
 74         {
 75             return *this;
 76         }
 77         public nothrow WindowCreateParams& SetFontFamilyName(const string& fontFamilyName_)
 78         {
 79             fontFamilyName = fontFamilyName_;
 80             return *this;
 81         }
 82         public nothrow WindowCreateParams& SetFontSize(float fontSize_)
 83         {
 84             fontSize = fontSize_;
 85             return *this;
 86         }
 87         public nothrow WindowCreateParams& SetFontStyle(FontStyle fontStyle_)
 88         {
 89             fontStyle = fontStyle_;
 90             return *this;
 91         }
 92         public nothrow WindowCreateParams& SetWindowState(WindowState state_)
 93         {
 94             state = state_;
 95             return *this;
 96         }
 97         public ControlCreateParams& controlCreateParams;
 98         public string fontFamilyName;
 99         public float fontSize;
100         public FontStyle fontStyle;
101         public WindowState state;
102     }
103 
104     public class Window : ContainerControl
105     {
106         private enum Flags : sbyte
107         {
108             none = 0mainWindow = 1 << 0showingDialog = 1 << 1
109         }
110         public Window(const string& windowClassNameWindowClassStyle classStyleWindowStyle styleExtendedWindowStyle exStyle
111             const Color& backgroundColorconst string& textconst Point& locationconst Size& sizeDock dockAnchors anchors
112             const string& fontFamilyName_float fontSize_FontStyle fontStyle_WindowState state_) : 
113             base(windowClassNameclassStylestyleexStylebackgroundColortextlocationsizedockanchors)flags(Flags.none)state(state_)
114             menuBar(null)contextMenu(null)defaultButton(null)cancelButton(null)focusedControl(null)dialogResult(DialogResult.none)
115             keyPreviewMethod()fontFamilyName(fontFamilyName_)fontSize(fontSize_)fontStyle(fontStyle_)
116         {
117             Init();
118         }
119         public Window(const string& windowClassNameWindowClassStyle classStyleWindowStyle styleExtendedWindowStyle exStyle
120             const Color& backgroundColorconst string& textconst Point& locationconst Size& sizeDock dockAnchors anchorsWindowState state) : 
121             this(windowClassNameclassStylestyleexStylebackgroundColortextlocationsizedockanchors
122                 DefaultWindowFontFamilyName()DefaultWindowFontSize()FontStyle.regularstate)
123         {
124         }
125         public Window(const string& windowClassNameWindowStyle styleExtendedWindowStyle exStyleconst string& textconst Point& location
126             const Size& sizeDock dockAnchors anchors
127             const string& fontFamilyName_float fontSize_FontStyle fontStyle_WindowState state) : 
128             this(windowClassNamecast<WindowClassStyle>(WindowClassStyle.CS_VREDRAW | WindowClassStyle.CS_HREDRAW)styleexStyle
129             DefaultWindowBackgroundColor()textlocationsizedockanchorsfontFamilyName_fontSize_fontStyle_state)
130         {
131         }
132         public Window(const string& windowClassNameWindowStyle styleExtendedWindowStyle exStyleconst string& textconst Point& location
133             const Size& sizeDock dockAnchors anchorsWindowState state) : 
134             this(windowClassNamestyleexStyletextlocationsizedockanchorsDefaultWindowFontFamilyName()DefaultWindowFontSize()
135             FontStyle.regularstate)
136         {
137         }
138         public Window(const string& captionconst string& fontFamilyName_float fontSize_FontStyle fontStyle_) : 
139             this("System.Windows.Window"WindowStyle.WS_OVERLAPPEDWINDOWDefaultExtendedWindowStyle()
140             captionPoint.Default()Size.Default()Dock.noneAnchors.nonefontFamilyName_fontSize_fontStyle_WindowState.normal)
141         {
142         }
143         public Window(const string& caption) : 
144             this(captionDefaultWindowFontFamilyName()DefaultWindowFontSize()FontStyle.regular)
145         {
146         }
147         public Window(WindowCreateParams& createParams) : 
148             base(createParams.controlCreateParams)
149             flags(Flags.none)state(createParams.state)
150             menuBar(null)contextMenu(null)defaultButton(null)cancelButton(null)focusedControl(null)dialogResult(DialogResult.none)
151             keyPreviewMethod()fontFamilyName(createParams.fontFamilyName)fontSize(createParams.fontSize)fontStyle(createParams.fontStyle)
152         {
153             Init();
154         }
155         private void Init()
156         {
157             SetKeyPreviewMethod(DefaultKeyPreview);
158             if (Handle() != null)
159             {
160                 OnCreated();
161             }
162             if (!fontFamilyName.IsEmpty())
163             {
164                 SetFont(Font(FontFamily(fontFamilyName)fontSizefontStyleUnit.point));
165             }
166         }
167         public DialogResult ShowDialog(Window& parentWindow)
168         {
169             DialogGuard guard(this);
170             Point parentLoc = parentWindow.Location();
171             Size parentSize = parentWindow.GetSize();
172             Size size = GetSize();
173             SetLocation(Point(Max(cast<int>(0)parentLoc.x + (parentSize.w - size.w) / 2)Max(cast<int>(0)parentLoc.y + (parentSize.h - size.h) / 2)));
174             SetDialogResult(DialogResult.none);
175             GetDialogResultFunction dialogResultFunction = System.Windows.GetDialogResult;
176             DialogWindowKeyPreviewFunction keyPreviewFunction = System.Windows.DialogWindowKeyPreview;
177             int result = WinDialogWindowMessageLoop(Handle()parentWindow.Handle()cast<void*>(dialogResultFunction)cast<void*>(keyPreviewFunction)this);
178             return cast<DialogResult>(result);
179         }
180         protected override void OnCreated()
181         {
182             if (!BaseOnCreatedCalled())
183             {
184                 SetBaseOnCreatedCalled();
185                 base->OnCreated();
186             }
187             if (!ScreenMetrics.Calculated())
188             {
189                 Graphics graphics = Graphics.FromWindowHandle(Handle());
190                 ScreenMetrics.Calculate(graphics);
191             }
192         }
193         public override void PrintWindowTree(int level)
194         {
195             LogView* log = Application.GetLogView();
196             if (log != null)
197             {
198                 log->WriteLine(string(' 'level) + "Window." + Text() + ".handle=" + ToHexString(cast<ulong>(Handle())) + " " + ParentText() + "[" + Rect(Point()GetSize()).ToString() + "]");
199             }
200             Component* child = Children().FirstChild();
201             while (child != null)
202             {
203                 if (child is Control*)
204                 {
205                     Control* childControl = cast<Control*>(child);
206                     childControl->PrintWindowTree(level + 1);
207                 }
208                 child = child->NextSibling();
209             }
210         }
211         protected override bool ProcessMessage(Message& message)
212         {
213             switch (message.msg)
214             {
215                 case WM_CLOSE:
216                 {
217                     bool cancelClose = false;
218                     OnWindowClosing(cancelClose);
219                     if (cancelClose)
220                     {
221                         message.result = 0;
222                         return true;
223                     }
224                     break;
225                 }
226                 case WM_DESTROY:
227                 {
228                     bool processed = false;
229                     OnWindowClosed(processed);
230                     if (processed)
231                     {
232                         message.result = 0;
233                         return true;
234                     }
235                     break;
236                 }
237                 case WM_COMMAND: case WM_MOVE: case WM_SIZE: case WM_PAINT: case WM_MOUSEMOVE: case WM_MOUSELEAVE: case WM_LBUTTONDOWN:
238                 case WM_LBUTTONUP: case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: case WM_RBUTTONUP:
239                 case WM_CHAR: case WM_KEYDOWN: case WM_KEYUP: case WM_SYSCOMMAND: case WM_HSCROLL: case WM_VSCROLL: case WM_MOUSEWHEEL:
240                 case WM_TIMER: case WM_SETFOCUS: case WM_KILLFOCUS:
241                 case WM_SHOWWINDOW: case WM_CLIPBOARDUPDATE:
242                 {
243                     return base->ProcessMessage(message);
244                 }
245             }
246             return false;
247         }
248         public void Close()
249         {
250             PostMessage(Handle()WM_CLOSE0u0);
251         }
252         protected virtual void OnWindowClosing(bool& cancelClose)
253         {
254             windowClosingEvent.Fire(cancelClose);
255         }
256         protected virtual void OnWindowClosed(bool& processed)
257         {
258             if (windowClosedEvent.Handlers().IsEmpty())
259             {
260                 if (IsMainWindow())
261                 {
262                     Application.Exit();
263                     processed = true;
264                 }
265             }
266             else
267             {
268                 windowClosedEvent.Fire();
269                 processed = true;
270             }
271         }
272         protected override void OnControlAdded(ControlEventArgs& args)
273         {
274             base->OnControlAdded(args);
275             Control* control = args.control;
276             if (control is MenuBar*)
277             {
278                 menuBar = cast<MenuBar*>(control);
279             }
280             else if (control is Button*)
281             {
282                 Button* button = cast<Button*>(control);
283                 if (button->IsDefault())
284                 {
285                     SetDefaultButton(button);
286                 }
287             }
288         }
289         protected override void OnControlRemoved(ControlEventArgs& args)
290         {
291             base->OnControlRemoved(args);
292             Control* control = args.control;
293             if (control == menuBar)
294             {
295                 menuBar = null;
296             }
297             else if (control == defaultButton)
298             {
299                 defaultButton = null;
300             }
301             else if (control == cancelButton)
302             {
303                 cancelButton = null;
304             }
305         }
306         public void DefaultKeyPreview(Keys keybool shiftbool controlbool altbool keyDownbool& handled)
307         {
308             if (keyDown)
309             {
310                 Keys modifierKeys = Keys.none;
311                 if (shift)
312                 {
313                     modifierKeys = cast<Keys>(modifierKeys | Keys.shiftModifier);
314                 }
315                 if (control)
316                 {
317                     modifierKeys = cast<Keys>(modifierKeys | Keys.controlModifier);
318                 }
319                 if (alt)
320                 {
321                     modifierKeys = cast<Keys>(modifierKeys | Keys.altModifier);
322                 }
323                 key = cast<Keys>(key | modifierKeys);
324                 switch (key)
325                 {
326                     case Keys.enter:
327                     {
328                         if (ShowingDialog())
329                         {
330                             if (focusedControl != null)
331                             {
332                                 if (focusedControl is TextBox*)
333                                 {
334                                     TextBox* textBox = cast<TextBox*>(focusedControl);
335                                     if (textBox->IsMultiline())
336                                     {
337                                         break;
338                                     }
339                                 }
340                             }
341                             if (focusedControl != null)
342                             {
343                                 if (focusedControl is Button*)
344                                 {
345                                     Button* button = cast<Button*>(focusedControl);
346                                     button->OnClickInternal();
347                                     handled = true;
348                                 }
349                             }
350                             if (!handled)
351                             {
352                                 if (defaultButton != null && defaultButton->IsEnabled())
353                                 {
354                                     defaultButton->OnClickInternal();
355                                     handled = true;
356                                 }
357                             }
358                         }
359                         break;
360                     }
361                     case Keys.escape:
362                     {
363                         if (ShowingDialog())
364                         {
365                             if (cancelButton != null)
366                             {
367                                 cancelButton->OnClickInternal();
368                                 handled = true;
369                             }
370                         }
371                         break;
372                     }
373                     case Keys.tab:
374                     {
375                         FocusNext();
376                         handled = true;
377                         break;
378                     }
379                     case cast<Keys>(Keys.shiftModifier | Keys.tab):
380                     {
381                         FocusPrev();
382                         handled = true;
383                         break;
384                     }
385                 }
386             }
387         }
388         protected override void OnKeyDown(KeyEventArgs& args)
389         {
390             base->OnKeyDown(args);
391             if (!args.handled)
392             {
393                 switch (args.key)
394                 {
395                     case Keys.enter:
396                     {
397                         if (ShowingDialog())
398                         {
399                             if (focusedControl != null)
400                             {
401                                 if (focusedControl is Button*)
402                                 {
403                                     Button* button = cast<Button*>(focusedControl);
404                                     button->OnClickInternal();
405                                     args.handled = true;
406                                 }
407                             }
408                             if (!args.handled)
409                             {
410                                 if (defaultButton != null && defaultButton->IsEnabled())
411                                 {
412                                     defaultButton->OnClickInternal();
413                                     args.handled = true;
414                                 }
415                             }
416                         }
417                         break;
418                     }
419                     case Keys.escape:
420                     {
421                         if (ShowingDialog())
422                         {
423                             if (cancelButton != null)
424                             {
425                                 cancelButton->OnClickInternal();
426                                 args.handled = true;
427                             }
428                         }
429                         break;
430                     }
431                     case Keys.tab:
432                     {
433                         FocusNext();
434                         args.handled = true;
435                         break;
436                     }
437                     case cast<Keys>(Keys.shiftModifier | Keys.tab):
438                     {
439                         FocusPrev();
440                         args.handled = true;
441                         break;
442                     }
443                 }
444             }
445         }
446         protected override void OnMouseMove(MouseEventArgs& args)
447         {
448             base->OnMouseMove(args);
449             if (menuBar != null)
450             {
451                 menuBar->MouseMoveInternal(args);
452             }
453         }
454         protected override void OnMouseDown(MouseEventArgs& args)
455         {
456             base->OnMouseDown(args);
457             if (menuBar != null)
458             {
459                 menuBar->MouseDownInternal(args);
460             }
461         }
462         protected override void OnMouseUp(MouseEventArgs& args)
463         {
464             base->OnMouseUp(args);
465             if (menuBar != null)
466             {
467                 menuBar->MouseUpInternal(args);
468             }
469         }
470         protected override void OnPaint(PaintEventArgs& args)
471         {
472             try
473             {
474                 if (Debug.Paint())
475                 {
476                     Rect r(Point()GetSize());
477                     LogView* log = Application.GetLogView();
478                     if (log != null)
479                     {
480                         log->WriteLine("Window.OnPaint: " + r.ToString());
481                     }
482                 }
483                 args.graphics.Clear(BackgroundColor());
484                 base->OnPaint(args);
485             }
486             catch (const Exception& ex)
487             {
488                 MessageBox.Show(ex.Message());
489             }
490         }
491         protected override void OnGotFocus()
492         {
493             LogView* log = Application.GetLogView();
494             if (log != null)
495             {
496                 log->WriteLine("Window.OnGotFocus: " + Text());
497             }
498             base->OnGotFocus();
499             Application.SetActiveWindow(this);
500             FocusNext();
501         }
502         protected override void OnLostFocus()
503         {
504             LogView* log = Application.GetLogView();
505             if (log != null)
506             {
507                 log->WriteLine("Window.OnLostFocus: " + Text());
508             }
509             base->OnLostFocus();
510             Application.SetActiveWindow(null);
511         }
512         public WindowState GetWindowState() const
513         {
514             return state;
515         }
516         public void SetWindowState(WindowState newState)
517         {
518             if (state != newState)
519             {
520                 switch (state)
521                 {
522                     case WindowState.normal:
523                     {
524                         switch (newState)
525                         {
526                             case WindowState.minimized:
527                             {
528                                 ShowWindow(ShowCommand.SW_MINIMIZE);
529                                 break;
530                             }
531                             case WindowState.maximized:
532                             {
533                                 ShowWindow(ShowCommand.SW_MAXIMIZE);
534                                 break;
535                             }
536                         }
537                         break;
538                     }
539                     case WindowState.minimized: case WindowState.maximized:
540                     {
541                         switch (newState)
542                         {
543                             case WindowState.normal:
544                             {
545                                 ShowWindow(ShowCommand.SW_RESTORE);
546                                 break;
547                             }
548                             case WindowState.minimized:
549                             {
550                                 ShowWindow(ShowCommand.SW_MINIMIZE);
551                                 break;
552                             }
553                             case WindowState.maximized:
554                             {
555                                 ShowWindow(ShowCommand.SW_MAXIMIZE);
556                                 break;
557                             }
558                         }
559                         break;
560                     }
561                 }
562                 state = newState;
563             }
564         }
565         public nothrow MenuBar* GetMenuBar() const
566         {
567             return menuBar;
568         }
569         public nothrow ContextMenu* GetContextMenu() const
570         {
571             return contextMenu;
572         }
573         public nothrow void SetContextMenu(ContextMenu* contextMenu_)
574         {
575             RemoveContextMenu();
576             contextMenu = contextMenu_;
577             AddChild(contextMenu);
578         }
579         public nothrow void RemoveContextMenu()
580         {
581             if (contextMenu != null)
582             {
583                 HideContextMenu();
584                 RemoveChild(contextMenu);
585                 contextMenu = null;
586             }
587         }
588         public nothrow void ShowContextMenu(ContextMenu* contextMenu_const Point& ptInScreenCoords)
589         {
590             SetContextMenu(contextMenu_);
591             Point windowLoc = Location();
592             Size windowSize = GetSize();
593             Point windowEdgeLoc(windowLoc.x + windowSize.wwindowLoc.y + windowSize.h);
594             Point screenWindowEdgeLoc = ClientToScreen(windowEdgeLoc);
595             contextMenu->CalculateSize();
596             Size contextMenuSize = contextMenu->GetSize();
597             if (ptInScreenCoords.x + contextMenuSize.w >= screenWindowEdgeLoc.x)
598             {
599                 ptInScreenCoords.Offset(-contextMenuSize.w0);
600             }
601             if (ptInScreenCoords.y + contextMenuSize.h >= screenWindowEdgeLoc.y)
602             {
603                 ptInScreenCoords.Offset(0-contextMenuSize.h);
604             }
605             Point loc = ScreenToClient(ptInScreenCoords);
606             contextMenu->SetLocation(loc);
607             contextMenu->BringToFront();
608             contextMenu->Show();
609             contextMenu->Invalidate();
610             contextMenu->Update();
611         }
612         public nothrow void HideContextMenu()
613         {
614             if (contextMenu != null)
615             {
616                 Rect rect(contextMenu->Location()contextMenu->GetSize());
617                 contextMenu->Hide();
618                 Invalidate(rect);
619             }
620         }
621         public nothrow Event<WindowClosingEventHandlerbool>& WindowClosingEvent()
622         {
623             return windowClosingEvent;
624         }
625         public nothrow Event<WindowClosedEventHandler>& WindowClosedEvent()
626         {
627             return windowClosedEvent;
628         }
629         public void SetIcon(const Icon& icon)
630         {
631             SetClassLong(Handle()ClassLongIndex.GCL_HICONcast<long>(cast<ulong>(icon.Handle())));
632         }
633         public void SetSmallIcon(const Icon& icon)
634         {
635             SetClassLong(Handle()ClassLongIndex.GCL_HICONSMcast<long>(cast<ulong>(icon.Handle())));
636         }
637         internal inline nothrow int GetDialogResult() const
638         {
639             return cast<int>(dialogResult);
640         }
641         public inline nothrow void SetDialogResult(DialogResult dialogResult_)
642         {
643             dialogResult = dialogResult_;
644         }
645         public void FocusNext()
646         {
647             LogView* logView = Application.GetLogView();
648             if (focusedControl == null)
649             {
650                 Component* child = Children().FirstChild();
651                 while (child != null)
652                 {
653                     if (child is Control*)
654                     {
655                         Control* control = cast<Control*>(child);
656                         Control* tabStopChild = control->GetFirstEnabledTabStopControl();
657                         if (tabStopChild != null)
658                         {
659                             tabStopChild->SetFocus();
660                             focusedControl = tabStopChild;
661                             if (logView != null)
662                             {
663                                 logView->WriteLine("focused: " + string(typename(*focusedControl)) + ": " + focusedControl->Text());
664                             }
665                             return;
666                         }
667                     }
668                     child = child->NextSibling();
669                 }
670             }
671             else
672             {
673                 Component* parent = null;
674                 Component* child = focusedControl;
675                 Container* container = child->GetContainer();
676                 if (container != null)
677                 {
678                     parent = container->Parent();
679                 }
680                 while (child != null)
681                 {
682                     child = child->NextSibling();
683                     while (child != null)
684                     {
685                         if (child is Control*)
686                         {
687                             Control* control = cast<Control*>(child);
688                             Control* tabStopChild = control->GetFirstEnabledTabStopControl();
689                             if (tabStopChild != null)
690                             {
691                                 tabStopChild->SetFocus();
692                                 focusedControl = tabStopChild;
693                                 return;
694                             }
695                         }
696                         child = child->NextSibling();
697                     }
698                     child = parent;
699                     if (parent != null)
700                     {
701                         container = parent->GetContainer();
702                         if (container != null)
703                         {
704                             parent = container->Parent();
705                         }
706                         else
707                         {
708                             parent = null;
709                         }
710                     }
711                 }
712                 focusedControl = null;
713                 FocusNext();
714             }
715         }
716         public void FocusPrev()
717         {
718             LogView* logView = Application.GetLogView();
719             if (focusedControl == null)
720             {
721                 Component* child = Children().LastChild();
722                 while (child != null)
723                 {
724                     if (child is Control*)
725                     {
726                         Control* control = cast<Control*>(child);
727                         Control* tabStopChild = control->GetLastEnabledTabStopControl();
728                         if (tabStopChild != null)
729                         {
730                             tabStopChild->SetFocus();
731                             focusedControl = tabStopChild;
732                             if (logView != null)
733                             {
734                                 logView->WriteLine("focused: " + string(typename(*focusedControl)) + ": " + focusedControl->Text());
735                             }
736                             return;
737                         }
738                     }
739                     child = child->PrevSibling();
740                 }
741             }
742             else
743             {
744                 Component* parent = null;
745                 Component* child = focusedControl;
746                 Container* container = child->GetContainer();
747                 if (container != null)
748                 {
749                     parent = container->Parent();
750                 }
751                 while (child != null)
752                 {
753                     child = child->PrevSibling();
754                     while (child != null)
755                     {
756                         if (child is Control*)
757                         {
758                             Control* control = cast<Control*>(child);
759                             Control* tabStopChild = control->GetLastEnabledTabStopControl();
760                             if (tabStopChild != null)
761                             {
762                                 tabStopChild->SetFocus();
763                                 focusedControl = tabStopChild;
764                                 return;
765                             }
766                         }
767                         child = child->PrevSibling();
768                     }
769                     child = parent;
770                     if (parent != null)
771                     {
772                         container = parent->GetContainer();
773                         if (container != null)
774                         {
775                             parent = container->Parent();
776                         }
777                         else
778                         {
779                             parent = null;
780                         }
781                     }
782                 }
783                 focusedControl = null;
784                 FocusPrev();
785             }
786         }
787         public inline nothrow Control* GetFocusedControl() const
788         {
789             return focusedControl;
790         }
791         public nothrow void ResetFocusedControl()
792         {
793             focusedControl = null;
794         }
795         internal inline nothrow void SetFocusedControl(Control* focusedControl_)
796         {
797             focusedControl = focusedControl_;
798         }
799         public inline nothrow const KeyPreviewMethod& GetKeyPreviewMethod() const
800         {
801             return keyPreviewMethod;
802         }
803         public nothrow void SetKeyPreviewMethod(const KeyPreviewMethod& keyPreviewMethod_)
804         {
805             keyPreviewMethod = keyPreviewMethod_;
806         }
807         public inline nothrow bool IsMainWindow() const
808         {
809             return (flags & Flags.mainWindow) != Flags.none;
810         }
811         public inline nothrow void SetAsMainWindow()
812         {
813             flags = cast<Flags>(flags | Flags.mainWindow);
814         }
815         public inline nothrow Button* DefaultButton() const
816         {
817             return defaultButton;
818         }
819         public nothrow void SetDefaultButton(Button* defaultButton_)
820         {
821             if (defaultButton != defaultButton_)
822             {
823                 if (defaultButton != null)
824                 {
825                     defaultButton->ResetDefault();
826                 }
827                 defaultButton = defaultButton_;
828                 if (defaultButton != null)
829                 {
830                     defaultButton->SetDefault();
831                 }
832             }
833         }
834         public inline nothrow Button* CancelButton() const
835         {
836             return cancelButton;
837         }
838         public nothrow void SetCancelButton(Button* cancelButton_)
839         {
840             cancelButton = cancelButton_;
841         }
842         internal void MouseUpNotificationInternal(MouseEventArgs& args)
843         {
844             MouseUpNotification(args);
845         }
846         protected virtual void MouseUpNotification(MouseEventArgs& args)
847         {
848         }
849         private inline nothrow bool ShowingDialog() const
850         {
851             return (flags & Flags.showingDialog) != Flags.none;
852         }
853         internal inline nothrow void SetShowingDialog()
854         {
855             flags = cast<Flags>(flags | Flags.showingDialog);
856         }
857         internal inline nothrow void ResetShowingDialog()
858         {
859             flags = cast<Flags>(flags & ~Flags.showingDialog);
860         }
861         private Flags flags;
862         private WindowState state;
863         private MenuBar* menuBar;
864         private ContextMenu* contextMenu;
865         private Button* defaultButton;
866         private Button* cancelButton;
867         private Control* focusedControl;
868         private string fontFamilyName;
869         private float fontSize;
870         private FontStyle fontStyle;
871         private Event<WindowClosingEventHandlerbool> windowClosingEvent;
872         private Event<WindowClosedEventHandler> windowClosedEvent;
873         private DialogResult dialogResult;
874         private KeyPreviewMethod keyPreviewMethod;
875     }
876 
877     internal int GetDialogResult(void* dialogWindowPtr)
878     {
879         Window* dialogWindow = cast<Window*>(dialogWindowPtr);
880         return dialogWindow->GetDialogResult();
881     }
882 
883     internal void DialogWindowKeyPreview(void* dialogWindowPtruint keyCodebool shiftbool controlbool altbool keyDownbool& handled)
884     {
885         Window* dialogWindow = cast<Window*>(dialogWindowPtr);
886         Keys key = cast<Keys>(cast<int>(keyCode));
887         KeyPreviewMethod keyPreview = dialogWindow->GetKeyPreviewMethod();
888         if (keyPreview != KeyPreviewMethod())
889         {
890             keyPreview(keyshiftcontrolaltkeyDownhandled);
891         }
892     }
893 
894     internal void ModelessWindowKeyPreview(uint keyCodebool shiftbool controlbool altbool keyDownbool& handled)
895     {
896         Window* activeWindow = Application.GetActiveWindow();
897         if (activeWindow != null)
898         {
899             Keys key = cast<Keys>(cast<int>(keyCode));
900             KeyPreviewMethod keyPreview = activeWindow->GetKeyPreviewMethod();
901             if (keyPreview != KeyPreviewMethod())
902             {
903                 keyPreview(keyshiftcontrolaltkeyDownhandled);
904             }
905         }
906     }
907 }