123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 |
- using System.Drawing;
- namespace System.Windows.Forms
- {
- public class Form : ContainerControl, IWin32Window
- {
- private bool isDisposed;
- private bool isClosing;
- private bool isModal;
- public System.Windows.Window window { get; }
- public static bool UseCustomWindowChrome = false;
- public bool IsCustomWindowChrome => window is CustomControls.ChromeWindow;
- private DialogResult dialogResult;
- public DialogResult DialogResult
- {
- get => dialogResult;
- set
- {
- dialogResult = value;
- if (value == DialogResult.None)
- return;
- if (!isClosing)
- window.Close();
- }
- }
- public override string Text
- {
- get => window.Title;
- set => window.Title = value;
- }
- public override int Left
- {
- get => (int)(window.Left * DpiScale);
- set => window.Left = value / DpiScale;
- }
- public override int Top
- {
- get => (int)(window.Top * DpiScale);
- set => window.Top = value / DpiScale;
- }
- public override System.Drawing.Size ClientSize
- {
- get
- {
- var delta = ((IForm)window).ClientSizeDelta;
- return new Drawing.Size(Width - delta.Width, Height - delta.Height);
- }
- set
- {
- var delta = ((IForm)window).ClientSizeDelta;
- Width = value.Width + delta.Width;
- Height = value.Height + delta.Height;
- }
- }
- public FormBorderStyle FormBorderStyle
- {
- get => ((IForm)window).FormBorderStyle;
- set => ((IForm)window).FormBorderStyle = value;
- }
- public bool MaximizeBox
- {
- get => ((IForm)window).MaximizeBox;
- set => ((IForm)window).MaximizeBox = value;
- }
- public bool MinimizeBox
- {
- get => ((IForm)window).MinimizeBox;
- set => ((IForm)window).MinimizeBox = value;
- }
- public bool KeyPreview { get; set; } // TODO
- public bool ShowIcon
- {
- get => ((IForm)window).ShowIcon;
- set => ((IForm)window).ShowIcon = value;
- }
- public Form MdiParent { get; set; } // TODO?
- private Icon icon;
- public Icon Icon
- {
- get => icon;
- set
- {
- icon = value;
- window.Icon = Helper.GetIcon(icon);
- }
- }
- public bool TopMost
- {
- get => window.Topmost;
- set => window.Topmost = value;
- }
- public bool ShowInTaskbar
- {
- get => window.ShowInTaskbar;
- set => window.ShowInTaskbar = value;
- }
- public FormStartPosition StartPosition { get; set; }
- private Button acceptButton;
- public Button AcceptButton
- {
- get => acceptButton;
- set
- {
- if (value != acceptButton)
- {
- if (acceptButton != null)
- (acceptButton.control as System.Windows.Controls.Button).IsDefault = false;
- if (value != null)
- (value.control as System.Windows.Controls.Button).IsDefault = true;
- acceptButton = value;
- }
- }
- }
- private Button cancelButton;
- public Button CancelButton
- {
- get => cancelButton;
- set
- {
- if (value != cancelButton)
- {
- if (cancelButton != null)
- (cancelButton.control as System.Windows.Controls.Button).IsCancel = true;
- if (value != null)
- (value.control as System.Windows.Controls.Button).IsCancel = true;
- cancelButton = value;
- }
- }
- }
- public Form Owner
- {
- get => window.Owner?.Tag as Form;
- set => window.Owner = value?.window;
- }
- public Control ActiveControl // TODO?
- {
- get
- {
- var el = System.Windows.Input.FocusManager.GetFocusedElement(window);
- if (el is System.Windows.Controls.Control ctl && ctl.Tag is Control c)
- return c;
- return null;
- }
- set
- {
- if (value != null)
- {
- value.Focus();
- }
- }
- }
- public FormWindowState WindowState
- {
- get => (FormWindowState)window.WindowState;
- set => window.WindowState = (Windows.WindowState)value;
- }
- public bool IsDisposed => isDisposed;
- public override Rectangle DisplayRectangle => new Rectangle(new System.Drawing.Point(0, 0), ClientSize);
- public event EventHandler Load;
- public event EventHandler Shown;
- public event EventHandler Closed;
- public event FormClosingEventHandler FormClosing;
- public event FormClosedEventHandler FormClosed;
- private void CenterWindowOnScreen()
- {
- IntPtr mon = NativeMethods.GetCurrentMonitorFromMousePosition();
- NativeMethods.RECT rect = NativeMethods.WorkAreaBoundsForMointor(mon);
- float dpiScale = (float)NativeMethods.GetDpiForMonitor(mon) / DeviceDpi;
- int newWidth = (int)(Width * dpiScale);
- int newHeight = (int)(Height * dpiScale);
- MoveWindow(rect.left + (rect.Width - newWidth) / 2, rect.top + (rect.Height - newHeight) / 2, newWidth, newHeight);
- }
- private void CenterWindowOnParent()
- {
- if (Owner != null)
- {
- // TODO: check multimonitor dpi!
- window.Left = (Owner.Left + (Owner.Width - Width) / 2) / Owner.DpiScale;
- window.Top = (Owner.Top + (Owner.Height - Height) / 2) / Owner.DpiScale;
- }
- }
- private void SetWindowPosition()
- {
- if (StartPosition == FormStartPosition.CenterScreen)
- {
- CenterWindowOnScreen();
- }
- else if (StartPosition == FormStartPosition.CenterParent)
- {
- CenterWindowOnParent();
- }
- }
- protected virtual void OnLoad(EventArgs e) => Load?.Invoke(this, e);
- protected virtual void OnShown(EventArgs e) => Shown?.Invoke(this, e);
- protected virtual void OnFormClosing(FormClosingEventArgs e) => FormClosing?.Invoke(this, e);
- protected virtual void OnFormClosed(FormClosedEventArgs e)
- {
- FormClosed?.Invoke(this, e);
- OnClosed(EventArgs.Empty);
- isDisposed = true;
- }
- protected virtual void OnClosed(EventArgs e) => Closed?.Invoke(this, e);
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- if (disposing)
- {
- window.Close();
- }
- }
- public override void ResumeLayout(bool resume)
- {
- float scale = DeviceDpi / AutoScaleDimensions.Width;
- if (AutoScaleMode == AutoScaleMode.Dpi || AutoScaleMode == AutoScaleMode.Font)
- {
- if (scale != 1)
- Scale(scale, scale);
- }
- base.ResumeLayout(resume);
- UpdateLayout();
- }
- public new void Show()
- {
- SetWindowPosition();
- OnLoad(EventArgs.Empty);
- isModal = false;
- window.Show();
- }
- public void Show(IWin32Window owner)
- {
- Owner = owner as Form;
- Show();
- }
- public DialogResult ShowDialog()
- {
- // this solves problem with dialog window & click on taskbar button
- if (Owner == null)
- {
- var ownerWindow = NativeMethods.ActiveWindow();
- if (ownerWindow != null && ownerWindow != window && ownerWindow.IsVisible)
- window.Owner = ownerWindow;
- }
- SetWindowPosition();
- OnLoad(EventArgs.Empty);
- isModal = true;
- window.ShowDialog();
- return DialogResult;
- }
- public DialogResult ShowDialog(IWin32Window owner)
- {
- Owner = owner as Form;
- return ShowDialog();
- }
- public void Close() => window.Close();
- public new void Hide() => window.Hide();
- protected virtual void OnDpiChanged(object sender, EventArgs e)
- {
- }
- private void EnumControls(Control control, Action<Control> action)
- {
- action(control);
- foreach (Control c in control.Controls)
- EnumControls(c, action);
- }
- public void MoveWindow(Rectangle rect) => MoveWindow(rect.Left, rect.Top, rect.Width, rect.Height);
- public void MoveWindow(int left, int top, int width, int height)
- {
- NativeMethods.MoveWindow(this, new Rectangle(left, top, width, height));
- Width = (int)(window.Width * DpiScale);
- Height = (int)(window.Height * DpiScale);
- }
- // this method is called by the FR dialog form designer
- public void MoveWindow(int left, int top, System.Windows.Media.Visual target)
- {
- // do default dpi scale
- SuspendLayout();
- ResumeLayout(false);
- // Suspend/Resume pair: fix issue with FR dialog form designer when moved to another monitor (bad anchors)
- SuspendLayout();
- double rescale = Helper.GetDpiScale(target) / DpiScale;
- NativeMethods.MoveWindow(this, new Rectangle(left, top, (int)(Width * rescale), (int)(Height * rescale)));
- AutoScaleDimensions = new SizeF((int)(DeviceDpi * rescale), (int)(DeviceDpi * rescale));
- // this.ResumeLayout will rescale controls, we don't need it
- base.ResumeLayout(false);
- // fix repaint issue
- EnumControls(this, c => { if (c != this) c.AfterDpiChange(1); });
- }
- public Form()
- {
- window = UseCustomWindowChrome ? new CustomControls.ChromeWindow() : new SystemWindow();
- var contentControl = ((IForm)window).ContentControl;
- SetContentControl(window, contentControl);
- contentControl.SizeChanged += (s, e) => UpdateLayout();
- window.UseLayoutRounding = true;
- #if Demo
- var demoLabel = new Controls.TextBlock();
- demoLabel.Text = " Demo version ";
- demoLabel.HorizontalAlignment = Windows.HorizontalAlignment.Center;
- demoLabel.VerticalAlignment = VerticalAlignment.Bottom;
- demoLabel.Opacity = 0.5;
- container.Children.Add(demoLabel);
- #endif
- window.Loaded += (sender, e) => OnShown(e); // this is the SWF Shown equivalent
- window.Closing += (sender, e) =>
- {
- isClosing = true;
- var args = new FormClosingEventArgs(CloseReason.UserClosing, false);
- OnFormClosing(args);
- e.Cancel = args.Cancel;
- if (args.Cancel)
- DialogResult = DialogResult.None;
- isClosing = false;
- };
- window.Closed += (sender, e) => OnFormClosed(new FormClosedEventArgs(CloseReason.UserClosing));
- window.StateChanged += (s, e) =>
- {
- if (window.WindowState == System.Windows.WindowState.Minimized && isModal && !ShowInTaskbar)
- {
- System.Windows.Application.Current.MainWindow.WindowState = System.Windows.WindowState.Minimized;
- }
- };
- DpiRescaler.Install(window, this, container, OnDpiChanged);
- AutoScaleDimensions = new System.Drawing.SizeF(96, 96);
- BackColor = System.Drawing.SystemColors.Control;
- }
- }
- }
|