1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048 |
- using System.ComponentModel;
- using System.Drawing;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- namespace System.Windows.Forms
- {
- public partial class Control : IComponent, IDisposable
- {
- private bool isDisposed;
- private Bitmap bitmapBuffer;
- private WriteableBitmap writeableBitmap;
- private bool isPainting;
- private bool updatingControlSize;
- private bool isMouseDblClicked;
- protected ControlStyles controlStyle;
- internal LayoutEngine LayoutEngine { get; }
- [Browsable(false)]
- public System.Windows.Controls.Control control { get; private set; }
- public string Name { get; set; }
- [Browsable(false)]
- public ControlCollection Controls { get; private set; }
- private Control parent;
- [Browsable(false)]
- public Control Parent
- {
- get => parent;
- set
- {
- if (parent != value)
- {
- if (parent != null)
- parent.Controls.Remove(this);
- if (value != null)
- value.Controls.Add(this);
- SetParent(value);
- }
- }
- }
- public bool Enabled
- {
- get => control.IsEnabled;
- set => control.IsEnabled = value;
- }
- public virtual bool Visible
- {
- get => control.Visibility == System.Windows.Visibility.Visible;
- set
- {
- control.Visibility = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Hidden; // Collapsed has issues with pmV2 (designer's preview, chart editor, etc)
- if (Dock != DockStyle.None)
- Parent?.UpdateLayout();
- }
- }
- [Browsable(false)]
- public bool Focused => control.IsFocused;
- public virtual bool AutoSize { get; set; }
- [Browsable(false)]
- public Padding Margin { get; set; } // ignored
- public virtual Padding Padding
- {
- get => Helper.ThicknessToPadding(control.Padding);
- set => control.Padding = Helper.PaddingToThickness(value);
- }
- internal Padding DefaultPadding { get; set; } // used in GroupBox to compensate for its header
- public AnchorStyles Anchor { get; set; }
- private DockStyle dock;
- public virtual DockStyle Dock
- {
- get => dock;
- set
- {
- if (dock != value)
- {
- dock = value;
- Parent?.UpdateLayout();
- }
- }
- }
- public virtual int Left
- {
- get => (int)Math.Round(control.Margin.Left * DpiScale);
- set
- {
- if (value != Left)
- {
- SetControlLeft(value);
- OnLocationChanged(EventArgs.Empty);
- }
- }
- }
- public virtual int Top
- {
- get => (int)Math.Round(control.Margin.Top * DpiScale);
- set
- {
- if (value != Top)
- {
- SetControlTop(value);
- OnLocationChanged(EventArgs.Empty);
- }
- }
- }
- private int height;
- public virtual int Height
- {
- get => AutoSize ? AutoSizeValue.Height : height;
- set
- {
- if (!AutoSize && value != height)
- {
- UpdateLayout(0, value - height);
- height = value;
- if (value >= 0 && !updatingControlSize)
- SetControlHeight(value);
- if (Dock != DockStyle.None)
- Parent?.UpdateLayout();
- OnResize(EventArgs.Empty);
- }
- else
- {
- // fix issue with FR LabelControl (setting size while AutoSize is on)
- height = value;
- }
- }
- }
- private int width;
- public virtual int Width
- {
- get => AutoSize ? AutoSizeValue.Width : width;
- set
- {
- if (!AutoSize && value != width)
- {
- UpdateLayout(value - width, 0);
- width = value;
- if (value >= 0 && !updatingControlSize)
- SetControlWidth(value);
- if (Dock != DockStyle.None)
- Parent?.UpdateLayout();
- OnResize(EventArgs.Empty);
- }
- else
- {
- // fix issue with FR LabelControl (setting size while AutoSize is on)
- width = value;
- }
- }
- }
- [Browsable(false)]
- public int Right => Left + Width;
- [Browsable(false)]
- public int Bottom => Top + Height;
- public System.Drawing.Point Location
- {
- get => new System.Drawing.Point(Left, Top);
- set
- {
- Left = value.X;
- Top = value.Y;
- }
- }
- public System.Drawing.Size Size
- {
- get => new System.Drawing.Size(Width, Height);
- set
- {
- Width = value.Width;
- Height = value.Height;
- }
- }
- [Browsable(false)]
- public Rectangle Bounds
- {
- get => new Rectangle(Left, Top, Width, Height);
- set
- {
- Location = value.Location;
- Size = value.Size;
- }
- }
- [Browsable(false)]
- public virtual Rectangle DisplayRectangle => new Rectangle(0, 0, Width, Height);
- [Browsable(false)]
- public virtual Rectangle ClientRectangle => DisplayRectangle;
- [Browsable(false)]
- public virtual System.Drawing.Size ClientSize
- {
- get => Size;
- set => Size = value;
- }
- private System.Drawing.Size minimumSize;
- public System.Drawing.Size MinimumSize
- {
- get => minimumSize;
- set
- {
- minimumSize = value;
- control.MinHeight = value.Height / DpiScale;
- control.MinWidth = value.Width / DpiScale;
- }
- }
- private System.Drawing.Size maximumSize;
- public System.Drawing.Size MaximumSize
- {
- get => maximumSize;
- set
- {
- maximumSize = value;
- control.MaxHeight = value.Height / DpiScale;
- control.MaxWidth = value.Width / DpiScale;
- }
- }
- [Browsable(false)]
- public virtual System.Drawing.Size PreferredSize => new System.Drawing.Size(Width, Height);
- [Browsable(false)]
- public int PreferredHeight => PreferredSize.Height;
- [Browsable(false)]
- public int PreferredWidth => PreferredSize.Width;
- public virtual System.Drawing.Color BackColor
- {
- get => Helper.GetColor(control.Background);
- set
- {
- control.Background = Helper.GetBrush(value);
- OnBackColorChanged(EventArgs.Empty);
- Refresh();
- }
- }
- public virtual System.Drawing.Color ForeColor
- {
- get => Helper.GetColor(control.Foreground);
- set => control.Foreground = Helper.GetBrush(value);
- }
- public virtual Image BackgroundImage { get; set; } // TODO?
- public virtual ImageLayout BackgroundImageLayout { get; set; } // TODO?
- public Font Font
- {
- get => Helper.GetFont(control);
- set
- {
- Helper.SetFont(control, value);
- ResetAutoSizeValue(false);
- OnFontChanged(EventArgs.Empty);
- }
- }
- public virtual BorderStyle BorderStyle
- {
- get => control.BorderThickness.Left == 0 ? BorderStyle.None : BorderStyle.FixedSingle;
- set => control.BorderThickness = new System.Windows.Thickness(value == BorderStyle.None ? 0 : 1);
- }
- private Cursor cursor = Cursors.Default;
- public Cursor Cursor
- {
- get => cursor;
- set
- {
- cursor = value;
- // reset global cursor
- Cursor.Current = null;
- control.Cursor = value.cursor;
- OnCursorChanged(EventArgs.Empty);
- }
- }
- private string text;
- public virtual string Text
- {
- get => text;
- set
- {
- text = value;
- ResetAutoSizeValue(false);
- }
- }
- public bool AllowDrop
- {
- get => control.AllowDrop;
- set => control.AllowDrop = value;
- }
- public int TabIndex
- {
- get => control.TabIndex == int.MaxValue ? 0 : control.TabIndex;
- set => control.TabIndex = value;
- }
- public bool TabStop
- {
- get => control.IsTabStop;
- set => control.IsTabStop = value;
- }
- public RightToLeft RightToLeft
- {
- get
- {
- return control.ReadLocalValue(FrameworkElement.FlowDirectionProperty) == DependencyProperty.UnsetValue ?
- RightToLeft.Inherit :
- (control.FlowDirection == FlowDirection.LeftToRight ? RightToLeft.No : RightToLeft.Yes);
- }
- set
- {
- if (value != RightToLeft)
- {
- if (value == RightToLeft.No)
- control.FlowDirection = FlowDirection.LeftToRight;
- else if (value == RightToLeft.Yes)
- control.FlowDirection = FlowDirection.RightToLeft;
- else
- control.ClearValue(FrameworkElement.FlowDirectionProperty);
- OnRightToLeftChanged();
- }
- }
- }
- public ContextMenuStrip ContextMenuStrip { get; set; }
- public string AccessibleName { get; set; }
- public AccessibleRole AccessibleRole { get; set; }
- public object Tag { get; set; }
- [Browsable(false)]
- public IntPtr Handle => IntPtr.Zero;
- [Browsable(false)]
- public ISite Site { get; set; }
- public ImeMode ImeMode { get; set; }
- [Browsable(false)]
- public int DeviceDpi => (int)(DpiScale * 96);
- [Browsable(false)]
- public double DpiScale => Helper.GetDpiScale(control);
- internal float _dpi(float value) => (float)(value * DpiScale);
- internal int _dpi(int value) => (int)(value * DpiScale);
- [Browsable(false)]
- public bool IsDisposed => isDisposed;
- public static Keys ModifierKeys => Helper.GetKeyModifiers(Input.Keyboard.Modifiers);
- public event EventHandler GotFocus;
- public event EventHandler Enter;
- public event EventHandler LostFocus;
- public event EventHandler Leave;
- public event MouseEventHandler MouseDown;
- public event MouseEventHandler MouseMove;
- public event MouseEventHandler MouseUp;
- public event MouseEventHandler MouseWheel;
- public event EventHandler MouseEnter;
- public event EventHandler MouseLeave;
- public event EventHandler MouseHover; // TODO?
- public event EventHandler Click;
- public event MouseEventHandler MouseClick;
- public event MouseEventHandler MouseDoubleClick;
- public event EventHandler DoubleClick;
- public event DragEventHandler DragEnter;
- public event EventHandler DragLeave;
- public event DragEventHandler DragOver;
- public event DragEventHandler DragDrop;
- public event KeyEventHandler KeyDown;
- public event KeyEventHandler KeyUp;
- public event KeyPressEventHandler KeyPress;
- public event PreviewKeyDownEventHandler PreviewKeyDown;
- public event PaintEventHandler Paint;
- public event EventHandler LocationChanged;
- public event EventHandler SizeChanged;
- public event EventHandler Resize;
- public event EventHandler BackColorChanged;
- public event EventHandler CursorChanged;
- public event EventHandler FontChanged;
- public event InvalidateEventHandler Invalidated;
- public event EventHandler RightToLeftChanged;
- public event EventHandler TextChanged;
- public event EventHandler EnabledChanged;
- public event EventHandler VisibleChanged;
- public event ControlEventHandler ControlAdded;
- public event ControlEventHandler ControlRemoved;
- public event EventHandler Disposed;
- private void WireEvents()
- {
- control.SizeChanged += Size_Changed;
- control.IsEnabledChanged += (sender, e) =>
- {
- OnEnabledChanged(EventArgs.Empty);
- Refresh();
- };
- control.IsVisibleChanged += (sender, e) =>
- {
- OnVisibleChanged(EventArgs.Empty);
- Refresh();
- };
- control.GotKeyboardFocus += (sender, e) =>
- {
- // commented: OnGotFocus is not called in PG textbox
- //if (!control.IsKeyboardFocusWithin)
- OnGotFocus(e);
- };
- control.LostFocus += (sender, e) =>
- {
- //if (!control.IsKeyboardFocusWithin)
- OnLostFocus(e);
- };
- control.MouseDown += (sender, e) =>
- {
- control.CaptureMouse();
- e.Handled = true;
- var args = Helper.GetMouseEventArgs(control, e);
- OnMouseDown(args);
- if (control.Focusable)
- control.Focus();
- // MouseDoubleClick event in WPF goes down to the root element regardless of e.Handled flag.
- // That's why we handle it here. Note that some controls such as TextBox does not work with this and use its own logic to fire OnDoubleClick.
- if (e.ClickCount == 2)
- isMouseDblClicked = true;
- if (e.ClickCount == 1)
- OnMouseClick(args);
- };
- control.MouseMove += (sender, e) =>
- {
- e.Handled = true;
- OnMouseMove(Helper.GetMouseEventArgs(control, e));
- };
- control.MouseUp += (sender, e) =>
- {
- e.Handled = true;
- var args = Helper.GetMouseEventArgs(control, e);
- if (isMouseDblClicked)
- {
- OnMouseDoubleClick(args);
- OnDoubleClick(EventArgs.Empty);
- isMouseDblClicked = false;
- }
- OnMouseUp(args);
- control.ReleaseMouseCapture();
- // SWF consistency - "ghost" mousemove event after mouseup (FR designer issue with TableObject's row/column context menu)
- OnMouseMove(new MouseEventArgs(MouseButtons.None, 0, args.X, args.Y, 0));
-
- if (e.ChangedButton == Input.MouseButton.Right)
- OnContextMenu(args);
- };
- control.MouseLeftButtonUp += (sender, e) => OnClick(e);
- control.MouseWheel += (sender, e) => OnMouseWheel(Helper.GetMouseEventArgs(control, e));
- control.MouseEnter += (sender, e) => OnMouseEnter(e); // note that these two events do not fire properly with parent/child controls
- control.MouseLeave += (sender, e) => OnMouseLeave(e); //
- control.DragEnter += (sender, e) => OnDragEnter(Helper.GetDragEventArgs(control, e));
- control.DragLeave += (sender, e) => OnDragLeave(Helper.GetDragEventArgs(control, e));
- control.DragOver += (sender, e) =>
- {
- var args = Helper.GetDragEventArgs(control, e);
- args.Effect = DragDropEffects.None;
- OnDragOver(args);
- e.Effects = (Windows.DragDropEffects)args.Effect;
- e.Handled = true;
- };
- control.Drop += (sender, e) => OnDragDrop(Helper.GetDragEventArgs(control, e));
- control.KeyDown += (sender, e) =>
- {
- // - do not handle keys pressed in the TextBox outside of TextBox. Case: keys typed in the inplace edit of FR table cell swallowed in the table's KeyDown handler
- // - keep in mind how TextBox is built here (ContentControl + either TextBox or PasswordBox)
- // - also note the Tag check: we need to handle events coming from internal textbox of some controls such as ComboBox (case: FR FontSizeComboBox, handle Enter key)
- if (e.OriginalSource is System.Windows.Controls.TextBox tb && tb.Tag != null && tb.Tag != this)
- return;
- var args = Helper.GetKeyEventArgs(e);
- OnKeyDown(args);
- if (IsInputKey(args.KeyData))
- args.Handled = true;
- e.Handled = args.Handled;
- };
- control.KeyUp += (sender, e) =>
- {
- var args = Helper.GetKeyEventArgs(e);
- OnKeyUp(args);
- e.Handled = args.Handled;
- };
- control.PreviewKeyDown += (sender, e) =>
- {
- var args = Helper.GetKeyEventArgs(e);
- if (ProcessDialogKey(args.KeyData))
- e.Handled = true;
- //var args1 = new PreviewKeyDownEventArgs(args.KeyData);
- //OnPreviewKeyDown(args1);
- //if (args1.IsInputKey)
- //e.Handled = true;
- };
- control.PreviewTextInput += (sender, e) =>
- {
- if (!string.IsNullOrEmpty(e.Text))
- {
- var args = new KeyPressEventArgs(e.Text[0]);
- OnKeyPress(args);
- e.Handled = args.Handled;
- }
- };
- }
- private void OnContextMenu(MouseEventArgs e)
- {
- if (ContextMenuStrip != null)
- ContextMenuStrip.Show(this, e.Location);
- }
- // these 4 are used in the TabItem control because it needs special handling
- protected virtual void SetControlLeft(int value) =>
- control.Margin = new System.Windows.Thickness(value / DpiScale, control.Margin.Top, control.Margin.Right, control.Margin.Bottom);
- protected virtual void SetControlTop(int value) =>
- control.Margin = new System.Windows.Thickness(control.Margin.Left, value / DpiScale, control.Margin.Right, control.Margin.Bottom);
- protected virtual void SetControlWidth(int value) =>
- control.Width = value / DpiScale;
- protected virtual void SetControlHeight(int value) =>
- control.Height = value / DpiScale;
- protected virtual void SetParent(Control parent) => this.parent = parent;
- // override in controls that don't use Margin to position itself (such as ToolStripItem)
- internal protected virtual SizeF GetControlDesiredSize()
- {
- // DesiredSize includes margin
- // if margin is negative and control is outside visible area, DesiredSize returns zero (case: FR dialog page controls when inserting a new label or checkbox)
- if (control.DesiredSize.Width == 0 || control.DesiredSize.Height == 0)
- return SizeF.Empty;
- return new SizeF((float)(control.DesiredSize.Width - control.Margin.Left), (float)(control.DesiredSize.Height - control.Margin.Top));
- }
- protected internal void Size_Changed(object sender, System.Windows.SizeChangedEventArgs e)
- {
- updatingControlSize = true; // needed to correctly restore maximized window
- if (e.WidthChanged)
- Width = (int)(e.NewSize.Width * DpiScale);
- if (e.HeightChanged)
- Height = (int)(e.NewSize.Height * DpiScale);
- updatingControlSize = false;
- }
- private void OnRightToLeftChanged()
- {
- OnRightToLeftChanged(EventArgs.Empty);
- ResetAutoSizeValue(AutoSize);
- foreach (Control c in Controls)
- {
- c.RightToLeft = RightToLeft;
- c.OnParentRightToLeftChanged(EventArgs.Empty);
- }
- }
- protected bool DesignMode => false;
- private System.Drawing.Size autoSizeValue;
- internal System.Drawing.Size AutoSizeValue
- {
- get
- {
- if (autoSizeValue.IsEmpty)
- {
- // commented out due to problems with button's GrowOnly
- // uncommented due to problems with button's GrowAndShrink
- control.Width = double.NaN;
- control.Height = double.NaN;
- control.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
- SizeF desiredSize = GetControlDesiredSize();
- autoSizeValue.Width = (int)Math.Round(desiredSize.Width * DpiScale);
- autoSizeValue.Height = (int)Math.Round(desiredSize.Height * DpiScale);
- }
- return autoSizeValue;
- }
- }
- internal void ResetAutoSizeValue(bool hardReset)
- {
- if (hardReset)
- control.Measure(new Size(10000, 10000));
- autoSizeValue = System.Drawing.Size.Empty;
- }
- internal virtual void AddChild(Control child) { }
- internal virtual void RemoveChild(Control child) { }
- internal virtual void SetChildIndex(Control child, int index) { }
- internal void DoControlAdded(Control c) => OnControlAdded(new ControlEventArgs(c));
- internal void DoControlRemoved(Control c) => OnControlRemoved(new ControlEventArgs(c));
- internal void UpdateLayout(int dx, int dy) => LayoutEngine.AddTransaction(dx, dy);
- internal void UpdateLayout() => LayoutEngine.AddTransaction();
- internal void OnLayout() => OnLayout(new LayoutEventArgs((IComponent)null, ""));
- private bool IsPaintingRequired()
- {
- // check if we have child controls with Dock = Fill that obscure this control. Take Padding into account
- if (Padding == Padding.Empty)
- {
- foreach (Control c in Controls)
- if (c.Dock == DockStyle.Fill)
- return false;
- }
- return true;
- }
- internal void DoPaint(System.Windows.Media.DrawingContext drawingContext)
- {
- if (Width <= 0 || Height <= 0 || !control.IsVisible)
- return;
- if (!IsPaintingRequired())
- return;
- isPainting = true;
- try
- {
- if (bitmapBuffer == null || bitmapBuffer.Width != Width || bitmapBuffer.Height != Height)
- {
- writeableBitmap = new WriteableBitmap(Width, Height, Helper.ScreenDpi, Helper.ScreenDpi, PixelFormats.Bgra32, null);
- bitmapBuffer?.Dispose();
- // share pixel buffer between gdi+ and wpf bitmap
- bitmapBuffer = new Bitmap(Width, Height, writeableBitmap.BackBufferStride, Drawing.Imaging.PixelFormat.Format32bppArgb, writeableBitmap.BackBuffer);
- }
- writeableBitmap.Lock();
- using (var g = Graphics.FromImage(bitmapBuffer))
- {
- var args = new PaintEventArgs(g, new Rectangle(0, 0, bitmapBuffer.Width, bitmapBuffer.Height));
- OnPaintBackground(args);
- OnPaint(args);
- }
- writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, Width, Height));
- writeableBitmap.Unlock();
- if (control.FlowDirection == FlowDirection.RightToLeft)
- drawingContext.PushTransform(new MatrixTransform(-1, 0, 0, 1, Width / DpiScale, 0));
- drawingContext.DrawImage(writeableBitmap, new Rect(0, 0, Width / DpiScale, Height / DpiScale));
- }
- catch
- {
- drawingContext.DrawRectangle(Media.Brushes.White, null, new Rect(0, 0, Width, Height));
- drawingContext.DrawLine(new Media.Pen(Media.Brushes.Red, 1), new Point(0, 0), new Point(Width, Height));
- drawingContext.DrawLine(new Media.Pen(Media.Brushes.Red, 1), new Point(Width, 0), new Point(0, Height));
- }
- isPainting = false;
- }
- protected virtual void OnPaintBackground(PaintEventArgs e)
- {
- var color = BackColor;
- if (color == System.Drawing.Color.Transparent || (controlStyle & ControlStyles.SupportsTransparentBackColor) != 0)
- {
- // find parent control with non-transparent background
- var parent = Parent;
- while (parent != null)
- {
- if (parent.BackColor != System.Drawing.Color.Transparent)
- {
- color = parent.BackColor;
- break;
- }
- parent = parent.Parent;
- }
- }
- e.Graphics.Clear(color);
- }
- protected virtual void OnPaint(PaintEventArgs e) => Paint?.Invoke(this, e);
- protected virtual void OnGotFocus(EventArgs e)
- {
- GotFocus?.Invoke(this, e);
- Enter?.Invoke(this, e);
- }
- protected virtual void OnLostFocus(EventArgs e)
- {
- LostFocus?.Invoke(this, e);
- Leave?.Invoke(this, e);
- }
- protected virtual void OnMouseDown(MouseEventArgs e) => MouseDown?.Invoke(this, e);
- protected virtual void OnMouseMove(MouseEventArgs e) => MouseMove?.Invoke(this, e);
- protected virtual void OnMouseUp(MouseEventArgs e) => MouseUp?.Invoke(this, e);
- protected virtual void OnMouseWheel(MouseEventArgs e) => MouseWheel?.Invoke(this, e);
- protected virtual void OnMouseEnter(EventArgs e) => MouseEnter?.Invoke(this, e);
- protected virtual void OnMouseLeave(EventArgs e) => MouseLeave?.Invoke(this, e);
- protected virtual void OnClick(EventArgs e) => Click?.Invoke(this, e);
- protected virtual void OnDoubleClick(EventArgs e) => DoubleClick?.Invoke(this, e);
- protected virtual void OnMouseClick(MouseEventArgs e) => MouseClick?.Invoke(this, e);
- protected virtual void OnMouseDoubleClick(MouseEventArgs e) => MouseDoubleClick?.Invoke(this, e);
- protected virtual void OnDragEnter(DragEventArgs e) => DragEnter?.Invoke(this, e);
- protected virtual void OnDragLeave(EventArgs e) => DragLeave?.Invoke(this, e);
- protected virtual void OnDragOver(DragEventArgs e) => DragOver?.Invoke(this, e);
- protected virtual void OnDragDrop(DragEventArgs e) => DragDrop?.Invoke(this, e);
- protected virtual void OnKeyDown(KeyEventArgs e) => KeyDown?.Invoke(this, e);
- protected virtual void OnKeyUp(KeyEventArgs e) => KeyUp?.Invoke(this, e);
- protected virtual void OnKeyPress(KeyPressEventArgs e) => KeyPress?.Invoke(this, e);
- protected virtual void OnPreviewKeyDown(PreviewKeyDownEventArgs e) => PreviewKeyDown?.Invoke(this, e);
- protected virtual void OnLayout(LayoutEventArgs e) { }
- protected virtual void OnResize(EventArgs e)
- {
- OnSizeChanged(e);
- Resize?.Invoke(this, e);
- }
- protected virtual void OnLocationChanged(EventArgs e) => LocationChanged?.Invoke(this, e);
- protected virtual void OnSizeChanged(EventArgs e) => SizeChanged?.Invoke(this, e);
- protected virtual void OnInvalidated(InvalidateEventArgs e) => Invalidated?.Invoke(this, e);
- protected virtual void OnBackColorChanged(EventArgs e) => BackColorChanged?.Invoke(this, e);
- protected virtual void OnSystemColorsChanged(EventArgs e) { } // TODO?
- protected virtual void OnCursorChanged(EventArgs e) => CursorChanged?.Invoke(this, e);
- protected virtual void OnFontChanged(EventArgs e) => FontChanged?.Invoke(this, e);
- protected virtual void OnRightToLeftChanged(EventArgs e) => RightToLeftChanged?.Invoke(this, e);
- protected virtual void OnParentRightToLeftChanged(EventArgs e) { }
- protected virtual void OnTextChanged(EventArgs e) => TextChanged?.Invoke(this, e);
- protected virtual void OnEnabledChanged(EventArgs e) => EnabledChanged?.Invoke(this, e);
- protected virtual void OnVisibleChanged(EventArgs e) => VisibleChanged?.Invoke(this, e);
- protected virtual void OnControlAdded(ControlEventArgs e) => ControlAdded?.Invoke(this, e);
- protected virtual void OnControlRemoved(ControlEventArgs e) => ControlRemoved?.Invoke(this, e);
- protected virtual object GetService(object service) => null;
- protected virtual object GetService(Type serviceType) => null;
- protected void SetStyle(ControlStyles flag, bool value)
- {
- controlStyle = (value ? (controlStyle | flag) : (controlStyle & ~flag));
- // FR designer's smarttag button depends on this
- control.Focusable = (controlStyle & ControlStyles.Selectable) != 0;
- }
- protected virtual void ScaleCore(float dx, float dy)
- {
- if (control is not Window)
- Location = new System.Drawing.Point((int)(Location.X * dx), (int)(Location.Y * dy));
- if (!AutoSize)
- ClientSize = new System.Drawing.Size((int)(ClientSize.Width * dx), (int)(ClientSize.Height * dy));
- }
- protected virtual bool IsInputKey(Keys keyData) => false;
- protected virtual bool ProcessDialogKey(Keys keyData) => false;
- protected void SetControl(System.Windows.Controls.Control control)
- {
- this.control = control;
- control.Tag = this;
- control.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
- control.VerticalAlignment = System.Windows.VerticalAlignment.Top;
- Controls = new ControlCollection(this);
- WireEvents();
- AllowDrop = false;
- }
- protected virtual void Dispose(bool disposing)
- {
- if (!disposing)
- return;
- if (parent != null)
- parent.Controls.Remove(this);
- for (int i = 0; i < Controls.Count; i++)
- {
- Control control = Controls[i];
- control.parent = null;
- control.Dispose();
- }
- isDisposed = true;
- bitmapBuffer?.Dispose();
- bitmapBuffer = null;
- Disposed?.Invoke(this, EventArgs.Empty);
- }
- protected virtual System.Drawing.Size DefaultSize => new Drawing.Size(Width, Height);
- public void Dispose()
- {
- Dispose(true);
- }
- public void DoDragDrop(object data, DragDropEffects allowedEffects) =>
- System.Windows.DragDrop.DoDragDrop(control, data, (System.Windows.DragDropEffects)allowedEffects);
- // this is used in drag/drop operations which already return client coords, so do nothing
- public System.Drawing.Point PointToClient(System.Drawing.Point pos) => pos;
- public void Scale(float dx, float dy)
- {
- if (dx == 1 && dy == 1)
- return;
-
- SuspendLayout();
- ScaleCore(dx, dy);
- ResetAutoSizeValue(false);
-
- for (int i = 0; i < Controls.Count; i++)
- {
- Control c = Controls[i];
- c.Scale(dx, dy);
- }
- ResumeLayout(false);
- OnLayout();
- }
- private void EnumControls(Control control, Action<Control> action)
- {
- action(control);
- foreach (Control c in control.Controls)
- EnumControls(c, action);
- }
- public void Scale(SizeF scale)
- {
- if (this.DeviceDpi != Helper.ScreenDpi)
- {
- float sc = (float)Helper.ScreenDpi / 96;
- Scale(sc, sc);
- sc = scale.Width / sc;
- // we have to return correct width & height to the calling method
- width = (int)(width * sc);
- height = (int)(height * sc);
- // necessary for cases like 120->144 scale (case: FR connection form)
- int saveWidth = width;
- int saveHeight = height;
- bool layoutComplete = false;
- EnumControls(this, c => c.SuspendLayout());
- control.Dispatcher.InvokeAsync(() =>
- {
- Size = new Drawing.Size(saveWidth, saveHeight);
- EnumControls(this, c =>
- {
- if (c is ContainerControl ctl)
- ctl.ScaleInternals(sc, sc);
- c.ResumeLayout(false);
- c.Refresh();
- });
- layoutComplete = true;
- }, Threading.DispatcherPriority.Render);
- // return to the calling method when layout completed to make rtl working properly (case: connection form & rtl & pmV2)
- while (!layoutComplete)
- Application.DoEvents();
- return;
- }
- Scale(scale.Width, scale.Height);
- }
- internal void BeforeDpiChange()
- {
- SuspendLayout();
- }
- internal virtual void AfterDpiChange(float rescale)
- {
- if (!double.IsNaN(control.Width))
- width = (int)(control.Width * DpiScale);
- else
- width = (int)(control.ActualWidth * DpiScale);
- if (!double.IsNaN(control.Height))
- height = (int)(control.Height * DpiScale);
- else
- height = (int)(control.ActualHeight * DpiScale);
-
- ResetAutoSizeValue(false);
- ResumeLayout(false);
- OnLayout();
- }
- public void SetBounds(int left, int top, int width, int height) => Bounds = new Rectangle(left, top, width, height);
- public void Focus() => control.Focus();
- public void Show() => Visible = true;
- public void Hide() => Visible = false;
- public void BringToFront() => Parent?.Controls.SetChildIndex(this, 0);
- public void SendToBack() => Parent?.Controls.SetChildIndex(this, Parent.Controls.Count - 1);
- public virtual void Select() { }
- public virtual void Refresh()
- {
- if (isPainting)
- return;
- control.InvalidateVisual();
- }
- public void Invalidate()
- {
- Refresh();
- OnInvalidated(new InvalidateEventArgs(DisplayRectangle));
- }
-
- public void Invalidate(bool flag) => Invalidate();
- public void Invalidate(Rectangle rect) => Invalidate();
- public void Update() { }
- public Form FindForm() => System.Windows.Window.GetWindow(control)?.Tag as Form;
- public void SuspendLayout() => LayoutEngine.SuspendLayout();
- public virtual void ResumeLayout(bool resume)
- {
- LayoutEngine.ResumeLayout(resume);
- if (!resume)
- UpdateLayout(); // update docked controls (case: barcode editor form with tvData docked incorrectly)
- }
- public void ResumeLayout() => ResumeLayout(true);
- public void PerformLayout() { }
- public void CreateControl() { }
- public void ResetText() => Text = "";
- public Graphics CreateGraphics() => Graphics.FromImage(new Bitmap(1, 1)); // TODO: FIXME all use cases
- public void Invoke(Action action) => control.Dispatcher.Invoke(action);
- public virtual Drawing.Point PointToScreen(Drawing.Point point)
- {
- if (!control.IsLoaded)
- return point;
- var pt = control.PointToScreen(new Point(point.X / DpiScale, point.Y / DpiScale));
- // pt is already in screen physical coords, no need to dpi-scale it
- return new Drawing.Point((int)(pt.X), (int)(pt.Y));
- }
- public virtual void DrawToBitmap(Bitmap bitmap, Rectangle rect)
- {
- Helper.DrawControl(control, bitmap, Width, Height, DeviceDpi);
- }
- public Control()
- {
- LayoutEngine = new(this);
- Anchor = AnchorStyles.Left | AnchorStyles.Top;
- controlStyle = ControlStyles.Selectable;
- SetControl(new OwnerDrawControl(this));
- }
- ~Control()
- {
- Dispose(false);
- }
- }
- }
|