// Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (c) 2004-2005 Novell, Inc. // // Authors: // Peter Bartok pbartok@novell.com // // NOT COMPLETE using System; using System.Drawing; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.Collections; using System.Runtime.InteropServices; using System.Threading; namespace System.Windows.Forms { [DesignerCategory("Form")] [DesignTimeVisible(false)] [Designer("System.Windows.Forms.Design.FormDocumentDesigner, " + Consts.AssemblySystem_Design, typeof(IRootDesigner))] [DefaultEvent("Load")] [ToolboxItem(false)] public class Form : ContainerControl { #region Local Variables internal static Form active_form; internal bool closing; FormBorderStyle form_border_style; private bool autoscale; private Size autoscale_base_size; private static Icon default_icon; internal bool is_modal; internal bool end_modal; // This var is being monitored by the application modal loop private bool control_box; private bool minimize_box; private bool maximize_box; private bool help_button; private bool show_in_taskbar; private bool topmost; private IButtonControl accept_button; private IButtonControl cancel_button; private DialogResult dialog_result; private FormStartPosition start_position; private Form owner; private Form.ControlCollection owned_forms; private MdiClient mdi_container; private MdiChildContext mdi_child_context; private Form mdi_parent; private bool key_preview; private MainMenu menu; private Icon icon; private Size maximum_size; private Size minimum_size; private SizeGripStyle size_grip_style; private Rectangle maximized_bounds; private Rectangle default_maximized_bounds; private double opacity; Color transparency_key; #endregion // Local Variables #region Private & Internal Methods static Form () { default_icon = (Icon)Locale.GetResource("mono.ico"); } #endregion // Private & Internal Methods #region Public Classes public new class ControlCollection : Control.ControlCollection { Form form_owner; public ControlCollection(Form owner) : base(owner) { this.form_owner = owner; } public override void Add(Control value) { if (Contains (value)) return; AddToList (value); ((Form)value).owner=(Form)owner; } public override void Remove(Control value) { ((Form)value).owner = null; base.Remove (value); } } #endregion // Public Classes #region Public Constructor & Destructor public Form () { SizeF current_scale = GetAutoScaleSize (DeviceContext, Font); autoscale = true; autoscale_base_size = new Size ((int)current_scale.Width, (int) current_scale.Height); closing = false; is_modal = false; end_modal = false; dialog_result = DialogResult.None; start_position = FormStartPosition.WindowsDefaultLocation; form_border_style = FormBorderStyle.Sizable; key_preview = false; opacity = 1D; menu = null; icon = default_icon; minimum_size = new Size(0, 0); maximum_size = new Size(0, 0); control_box = true; minimize_box = true; maximize_box = true; help_button = false; show_in_taskbar = true; ime_mode = ImeMode.NoControl; is_visible = false; is_toplevel = true; size_grip_style = SizeGripStyle.Auto; maximized_bounds = Rectangle.Empty; default_maximized_bounds = Rectangle.Empty; owned_forms = new Form.ControlCollection(this); transparency_key = Color.Empty; } #endregion // Public Constructor & Destructor #region Public Static Properties public static Form ActiveForm { get { Control active; active = FromHandle(XplatUI.GetActive()); if (active != null) { if ( !(active is Form)) { Control parent; parent = active.Parent; while (parent != null) { if (parent is Form) { return (Form)parent; } parent = parent.Parent; } } else { return (Form)active; } } return null; } } #endregion // Public Static Properties #region Public Instance Properties [DefaultValue(null)] public IButtonControl AcceptButton { get { return accept_button; } set { accept_button = value; } } [MonoTODO("Figure out a way for transparency support in windows")] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool AllowTransparency { get { return false; } set { } } [DefaultValue(true)] public bool AutoScale { get { return autoscale; } set { autoscale = value; } } [Localizable(true)] [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Advanced)] public virtual Size AutoScaleBaseSize { get { return autoscale_base_size; } set { autoscale_base_size = value; } } [Localizable(true)] public override bool AutoScroll { get { return base.AutoScroll; } set { base.AutoScroll = value; } } public override Color BackColor { get { return base.BackColor; } set { base.BackColor = value; } } [DefaultValue(null)] public IButtonControl CancelButton { get { return cancel_button; } set { cancel_button = value; } } [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [Localizable(true)] public Size ClientSize { get { return base.ClientSize; } set { base.ClientSize = value; } } [DefaultValue(true)] public bool ControlBox { get { return control_box; } set { if (control_box != value) { control_box = value; UpdateStyles(); } } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Rectangle DesktopBounds { get { return new Rectangle(Location, Size); } set { Bounds = value; } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Point DesktopLocation { get { return Location; } set { Location = value; } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public DialogResult DialogResult { get { return dialog_result; } set { dialog_result = value; if (is_modal && (dialog_result != DialogResult.None)) { end_modal = true; } } } [DefaultValue(FormBorderStyle.Sizable)] [DispId(-504)] public FormBorderStyle FormBorderStyle { get { return form_border_style; } set { form_border_style = value; if (IsHandleCreated) { XplatUI.SetBorderStyle(window.Handle, form_border_style); } UpdateStyles(); } } [DefaultValue(false)] public bool HelpButton { get { return help_button; } set { if (help_button != value) { help_button = value; UpdateStyles(); } } } [Localizable(true)] [AmbientValue(null)] public Icon Icon { get { return icon; } set { if (icon != value) { icon = value; if (IsHandleCreated) { XplatUI.SetIcon(Handle, icon); } } } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsMdiChild { get { return mdi_parent != null; } } [DefaultValue(false)] public bool IsMdiContainer { get { return mdi_container != null; } set { if (value && mdi_container == null) { mdi_container = new MdiClient(); Controls.Add(mdi_container); } else if (!value && mdi_container != null) { Controls.Remove(mdi_container); mdi_container.Dispose(); } } } public Form ActiveMdiChild { get { if (!IsMdiContainer) return null; return (Form) mdi_container.ActiveMdiChild; } } [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Advanced)] public bool IsRestrictedWindow { get { return false; } } [DefaultValue(false)] public bool KeyPreview { get { return key_preview; } set { key_preview = value; } } [DefaultValue(true)] public bool MaximizeBox { get { return maximize_box; } set { if (maximize_box != value) { maximize_box = value; UpdateStyles(); } } } [DefaultValue("{Width=0, Height=0}")] [Localizable(true)] [RefreshProperties(RefreshProperties.Repaint)] public Size MaximumSize { get { return maximum_size; } set { if (maximum_size != value) { maximum_size = value; OnMaximumSizeChanged(EventArgs.Empty); } } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Form[] MdiChildren { get { if (mdi_container != null) { Form[] form_list; form_list = new Form[mdi_container.Controls.Count]; for (int i = 0; i < mdi_container.Controls.Count; i++) { form_list[i] = (Form)mdi_container.Controls[i]; } return form_list; } else { return new Form[0]; } } } [MonoTODO("Finish setter")] [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Form MdiParent { get { return mdi_parent; } set { SuspendLayout (); // TopLevel = true; if (!value.IsMdiContainer) throw new ArgumentException (); if (mdi_parent != null) { mdi_parent.MdiContainer.Controls.Remove (this); } mdi_parent = value; if (mdi_parent != null) { mdi_child_context = new MdiChildContext (this, mdi_parent.MdiContainer); mdi_parent.MdiContainer.Controls.Add (this); } ResumeLayout (); } } internal MdiClient MdiContainer { get { return mdi_container; } } [DefaultValue(null)] public MainMenu Menu { get { return menu; } set { if (menu != value) { menu = value; if (menu != null) { menu.SetForm (this); MenuAPI.SetMenuBarWindow (menu.Handle, this); if (IsHandleCreated) { XplatUI.SetMenu (window.Handle, menu.Handle); } UpdateBounds (bounds.X, bounds.Y, bounds.Width, bounds.Height, ClientSize.Width, ClientSize.Height - ThemeEngine.Current.CalcMenuBarSize (DeviceContext, menu.Handle, ClientSize.Width)); } else UpdateBounds (); } } } [DefaultValue(true)] public bool MinimizeBox { get { return minimize_box; } set { if (minimize_box != value) { minimize_box = value; UpdateStyles(); } } } [DefaultValue("{Width=0, Height=0}")] [Localizable(true)] [RefreshProperties(RefreshProperties.Repaint)] public Size MinimumSize { get { return minimum_size; } set { if (minimum_size != value) { minimum_size = value; OnMinimumSizeChanged(EventArgs.Empty); } } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Modal { get { return is_modal; } } [MonoTODO("Investigate ways to implement opacity")] [DefaultValue(1D)] [TypeConverter(typeof(OpacityConverter))] public double Opacity { get { return opacity; } set { opacity = value; } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Form[] OwnedForms { get { Form[] form_list; form_list = new Form[owned_forms.Count]; for (int i=0; i 0) { w = Width; } else { w = DefaultSize.Width; } if (Height > 0) { h = Height; } else { h = DefaultSize.Height; } ctl = null; if (parent != null) { ctl = parent; } else if (owner != null) { ctl = owner; } if (owner != null) { this.Location = new Point(ctl.Left + ctl.Width / 2 - w /2, ctl.Top + ctl.Height / 2 - h / 2); } } protected void CenterToScreen() { Size DisplaySize; int w; int h; if (Width > 0) { w = Width; } else { w = DefaultSize.Width; } if (Height > 0) { h = Height; } else { h = DefaultSize.Height; } XplatUI.GetDisplaySize(out DisplaySize); this.Location = new Point(DisplaySize.Width / 2 - w / 2, DisplaySize.Height / 2 - h / 2); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override Control.ControlCollection CreateControlsInstance() { return base.CreateControlsInstance (); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void CreateHandle() { base.CreateHandle (); if (icon != null) { XplatUI.SetIcon(window.Handle, icon); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void DefWndProc(ref Message m) { base.DefWndProc (ref m); } protected override void Dispose(bool disposing) { base.Dispose (disposing); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnActivated(EventArgs e) { if (Activated != null) { Activated(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnClosed(EventArgs e) { if (Closed != null) { Closed(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnClosing(System.ComponentModel.CancelEventArgs e) { if (Closing != null) { Closing(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnCreateControl() { base.OnCreateControl (); if (this.ActiveControl == null) { bool visible; // This visible hack is to work around CanSelect always being false if one of the parents // is not visible; and we by default create Form invisible... visible = this.is_visible; this.is_visible = true; if (SelectNextControl(this, true, true, true, true) == false) { Select(this); } this.is_visible = visible; } if (!IsMdiChild) { switch (StartPosition) { case FormStartPosition.CenterScreen: this.CenterToScreen(); break; case FormStartPosition.CenterParent: this.CenterToParent (); break; } } else { Left = 25 * MdiParent.MdiContainer.ChildrenCreated + 1; Top = 25 * MdiParent.MdiContainer.ChildrenCreated + 1; MdiParent.MdiContainer.ChildrenCreated++; } if (menu != null) { XplatUI.SetMenu(window.Handle, menu.Handle); } OnLoad(EventArgs.Empty); // Send initial location OnLocationChanged(EventArgs.Empty); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnDeactivate(EventArgs e) { if (Deactivate != null) { Deactivate(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnFontChanged(EventArgs e) { base.OnFontChanged (e); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnHandleCreated(EventArgs e) { XplatUI.SetBorderStyle(window.Handle, form_border_style); base.OnHandleCreated (e); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed (e); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnInputLanguageChanged(InputLanguageChangedEventArgs e) { if (InputLanguageChanged!=null) { InputLanguageChanged(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnInputLanguageChanging(InputLanguageChangingEventArgs e) { if (InputLanguageChanging!=null) { InputLanguageChanging(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnLoad(EventArgs e) { if (Load != null) { Load(this, e); } if (AutoScale){ ApplyAutoScaling (); AutoScale = false; } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnMaximizedBoundsChanged(EventArgs e) { if (MaximizedBoundsChanged != null) { MaximizedBoundsChanged(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnMaximumSizeChanged(EventArgs e) { if (MaximumSizeChanged != null) { MaximumSizeChanged(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnMdiChildActivate(EventArgs e) { if (MdiChildActivate != null) { MdiChildActivate(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnMenuComplete(EventArgs e) { if (MenuComplete != null) { MenuComplete(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnMenuStart(EventArgs e) { if (MenuStart != null) { MenuStart(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected virtual void OnMinimumSizeChanged(EventArgs e) { if (MinimumSizeChanged != null) { MinimumSizeChanged(this, e); } } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnPaint (PaintEventArgs pevent) { base.OnPaint (pevent); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnResize(EventArgs e) { base.OnResize(e); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnStyleChanged(EventArgs e) { base.OnStyleChanged (e); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnTextChanged(EventArgs e) { base.OnTextChanged (e); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void OnVisibleChanged(EventArgs e) { base.OnVisibleChanged (e); } protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { if (base.ProcessCmdKey (ref msg, keyData)) { return true; } // Give our menu a shot if (menu != null) { return menu.ProcessCmdKey(ref msg, keyData); } return false; } // LAMESPEC - Not documented that Form overrides ProcessDialogChar; class-status showed [EditorBrowsable (EditorBrowsableState.Advanced)] protected override bool ProcessDialogChar(char charCode) { return base.ProcessDialogChar (charCode); } protected override bool ProcessDialogKey(Keys keyData) { if ((keyData & Keys.Modifiers) == 0) { if (keyData == Keys.Enter && accept_button != null) { accept_button.PerformClick(); return true; } else if (keyData == Keys.Escape && cancel_button != null) { cancel_button.PerformClick(); return true; } } return base.ProcessDialogKey(keyData); } protected override bool ProcessKeyPreview(ref Message msg) { if (key_preview) { if (ProcessKeyEventArgs(ref msg)) { return true; } } return base.ProcessKeyPreview (ref msg); } protected override bool ProcessTabKey(bool forward) { return SelectNextControl(ActiveControl, forward, true, true, true); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void ScaleCore(float dx, float dy) { base.ScaleCore (dx, dy); } protected override void Select(bool directed, bool forward) { Form parent; if (directed) { base.SelectNextControl(null, forward, true, true, true); } parent = this.ParentForm; if (parent != null) { parent.ActiveControl = this; } Activate(); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) { base.SetBoundsCore (x, y, width, height, specified); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void SetClientSizeCore(int x, int y) { if ((minimum_size.Width != 0) && (x < minimum_size.Width)) { x = minimum_size.Width; } else if ((maximum_size.Width != 0) && (x > maximum_size.Width)) { x = maximum_size.Width; } if ((minimum_size.Height != 0) && (y < minimum_size.Height)) { y = minimum_size.Height; } else if ((maximum_size.Height != 0) && (y > maximum_size.Height)) { y = maximum_size.Height; } Rectangle ClientRect = new Rectangle(0, 0, x, y); Rectangle WindowRect; CreateParams cp = this.CreateParams; IntPtr menu_handle = (menu == null)?IntPtr.Zero:menu.Handle; if (XplatUI.CalculateWindowRect(Handle, ref ClientRect, cp.Style, cp.ExStyle, menu_handle, out WindowRect) ) SetBoundsCore(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void SetVisibleCore(bool value) { base.SetVisibleCore (value); } protected override void UpdateDefaultButton() { base.UpdateDefaultButton (); } [EditorBrowsable(EditorBrowsableState.Advanced)] protected override void WndProc(ref Message m) { if (IsMdiChild && mdi_child_context != null && mdi_child_context.HandleMessage (ref m)) { return; } switch((Msg)m.Msg) { case Msg.WM_CLOSE: { CancelEventArgs args = new CancelEventArgs(); OnClosing(args); if (!args.Cancel) { OnClosed(EventArgs.Empty); closing = true; base.WndProc(ref m); break; } break; } case Msg.WM_ACTIVATE: { if (m.WParam != (IntPtr)WindowActiveFlags.WA_INACTIVE) { OnActivated(EventArgs.Empty); } else { OnDeactivate(EventArgs.Empty); } return; } case Msg.WM_KILLFOCUS: { base.WndProc(ref m); return; } case Msg.WM_SETFOCUS: { if (ActiveControl != null && ActiveControl != this) { ActiveControl.Focus(); return; // FIXME - do we need to run base.WndProc, even though we just changed focus? } base.WndProc(ref m); return; } // Menu drawing case Msg.WM_NCLBUTTONDOWN: { if (this.menu != null) { int x = LowOrder ((int) m.LParam.ToInt32 ()) ; int y = HighOrder ((int) m.LParam.ToInt32 ()); menu.OnMouseDown(this, new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), mouse_clicks, x, y, 0)); } base.WndProc(ref m); return; } case Msg.WM_NCMOUSEMOVE: { if (this.menu != null) { menu.OnMouseMove(this, new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 0)); } base.WndProc(ref m); return; } case Msg.WM_NCPAINT: { if (this.menu != null) { Point pnt = XplatUI.GetMenuOrigin(window.Handle); MenuAPI.DrawMenuBar (menu.Handle, new Rectangle (pnt.X, pnt.Y, ClientSize.Width, 0)); } base.WndProc(ref m); return; } // This message is only received under Win32 case Msg.WM_NCCALCSIZE: { XplatUIWin32.NCCALCSIZE_PARAMS ncp; if ((menu != null) && (m.WParam == (IntPtr)1)) { ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(XplatUIWin32.NCCALCSIZE_PARAMS)); // Adjust for menu ncp.rgrc1.top += ThemeEngine.Current.CalcMenuBarSize (DeviceContext, menu.menu_handle, ClientSize.Width); Marshal.StructureToPtr(ncp, m.LParam, true); } DefWndProc(ref m); break; } case Msg.WM_GETMINMAXINFO: { XplatUIWin32.MINMAXINFO mmi; if (m.LParam != IntPtr.Zero) { mmi = (XplatUIWin32.MINMAXINFO)Marshal.PtrToStructure(m.LParam, typeof(XplatUIWin32.MINMAXINFO)); default_maximized_bounds = new Rectangle(mmi.ptMaxPosition.x, mmi.ptMaxPosition.y, mmi.ptMaxSize.x, mmi.ptMaxSize.y); if (maximized_bounds != Rectangle.Empty) { mmi.ptMaxSize.x = maximized_bounds.Width; mmi.ptMaxSize.y = maximized_bounds.Height; } Marshal.StructureToPtr(mmi, m.LParam, false); } break; } default: { base.WndProc (ref m); break; } } } #endregion // Protected Instance Methods #region Events public event EventHandler Activated; public event EventHandler Closed; public event CancelEventHandler Closing; public event EventHandler Deactivate; public event InputLanguageChangedEventHandler InputLanguageChanged; public event InputLanguageChangingEventHandler InputLanguageChanging; public event EventHandler Load; public event EventHandler MaximizedBoundsChanged; public event EventHandler MaximumSizeChanged; public event EventHandler MdiChildActivate; public event EventHandler MenuComplete; public event EventHandler MenuStart; public event EventHandler MinimumSizeChanged; [Browsable(false)] [EditorBrowsable(EditorBrowsableState.Never)] public new event EventHandler TabIndexChanged; #endregion // Events } }