X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FManaged.Windows.Forms%2FSystem.Windows.Forms%2FControl.cs;h=a2766d204e8e517a21714a9400d3c70550c09636;hb=8751be83f6c97e907e5a5c08ff69e754bf403fd3;hp=9addb9474509798b5347f6006ed9ff115c0fd1b0;hpb=aaec2381c5a9b0be989bc74d49c7dd1d9c32b0e7;p=mono.git diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs index 9addb947450..a2766d204e8 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs @@ -69,6 +69,7 @@ namespace System.Windows.Forms Rectangle explicit_bounds; // explicitly set bounds internal object creator_thread; // thread that created the control internal ControlNativeWindow window; // object for native window handle + private IWindowTarget window_target; string name; // for object naming // State @@ -83,7 +84,6 @@ namespace System.Windows.Forms bool is_recreating; // tracks if the handle for the control is being recreated bool causes_validation; // tracks if validation is executed on changes bool is_focusing; // tracks if Focus has been called on the control and has not yet finished - bool container_selected; // true if Select() or Focus() is called on a container, to prevent child controls from raising their GotFocus event int tab_index; // position in tab order of siblings bool tab_stop; // is the control a tab stop? bool is_disposed; // has the window already been disposed? @@ -128,6 +128,7 @@ namespace System.Windows.Forms BindingContext binding_context; RightToLeft right_to_left; // drawing direction for control ContextMenu context_menu; // Context menu associated with the control + internal bool use_compatible_text_rendering; // double buffering DoubleBuffer backbuffer; @@ -139,7 +140,6 @@ namespace System.Windows.Forms ControlBindingsCollection data_bindings; #if NET_2_0 - internal bool use_compatible_text_rendering; static bool verify_thread_handle; Padding padding; ImageLayout backgroundimage_layout; @@ -167,6 +167,11 @@ namespace System.Windows.Forms } } + protected override void OnHandleChange() + { + this.owner.WindowTarget.OnHandleChange(this.owner.Handle); + } + static internal Control ControlFromHandle(IntPtr hWnd) { ControlNativeWindow window; @@ -194,7 +199,26 @@ namespace System.Windows.Forms } protected override void WndProc(ref Message m) { - owner.WndProc(ref m); + owner.WindowTarget.OnMessage(ref m); + } + } + + private class ControlWindowTarget : IWindowTarget + { + private Control control; + + public ControlWindowTarget(Control control) + { + this.control = control; + } + + public void OnHandleChange(IntPtr newHandle) + { + } + + public void OnMessage(ref Message m) + { + control.WndProc(ref m); } } #endregion @@ -202,13 +226,16 @@ namespace System.Windows.Forms #region Public Classes [ComVisible(true)] public class ControlAccessibleObject : AccessibleObject { - Control owner; + IntPtr handle; #region ControlAccessibleObject Constructors public ControlAccessibleObject(Control ownerControl) : base (ownerControl) { - this.owner = ownerControl; + if (ownerControl == null) + throw new ArgumentNullException ("owner"); + + handle = ownerControl.Handle; } #endregion // ControlAccessibleObject Constructors @@ -227,7 +254,7 @@ namespace System.Windows.Forms public IntPtr Handle { get { - return owner.Handle; + return handle; } set { @@ -259,7 +286,7 @@ namespace System.Windows.Forms public Control Owner { get { - return owner; + return base.owner; } } @@ -282,14 +309,13 @@ namespace System.Windows.Forms return base.GetHelpTopic (out FileName); } - [MonoTODO("Implement this and tie it into Control.AccessibilityNotifyClients")] + [MonoTODO ("Implement this")] public void NotifyClients(AccessibleEvents accEvent) { throw new NotImplementedException(); } - [MonoTODO("Implement this and tie it into Control.AccessibilityNotifyClients")] + [MonoTODO ("Implement this")] public void NotifyClients(AccessibleEvents accEvent, int childID) { - throw new NotImplementedException(); } public override string ToString() { @@ -307,8 +333,7 @@ namespace System.Windows.Forms private Control parent; private bool pending_disposal; - public DoubleBuffer (Control parent) - { + public DoubleBuffer (Control parent) { this.parent = parent; real_graphics = new Stack (); int width = parent.Width; @@ -321,22 +346,19 @@ namespace System.Windows.Forms Invalidate (); } - public void Blit (PaintEventArgs pe) - { + public void Blit (PaintEventArgs pe) { Graphics buffered_graphics; buffered_graphics = XplatUI.GetOffscreenGraphics (back_buffer); XplatUI.BlitFromOffscreen (parent.Handle, pe.Graphics, back_buffer, buffered_graphics, pe.ClipRectangle); buffered_graphics.Dispose (); } - public void Start (PaintEventArgs pe) - { + public void Start (PaintEventArgs pe) { // We need to get the graphics for every paint. real_graphics.Push(pe.SetGraphics (XplatUI.GetOffscreenGraphics (back_buffer))); } - public void End (PaintEventArgs pe) - { + public void End (PaintEventArgs pe) { Graphics buffered_graphics; buffered_graphics = pe.SetGraphics ((Graphics) real_graphics.Pop ()); @@ -349,15 +371,13 @@ namespace System.Windows.Forms buffered_graphics.Dispose (); } - public void Invalidate () - { + public void Invalidate () { if (InvalidRegion != null) InvalidRegion.Dispose (); InvalidRegion = new Region (parent.ClientRectangle); } - public void Dispose () - { + public void Dispose () { if (real_graphics.Count > 0) { pending_disposal = true; return; @@ -373,14 +393,12 @@ namespace System.Windows.Forms } #region IDisposable Members - void IDisposable.Dispose () - { + void IDisposable.Dispose () { Dispose (); } #endregion - ~DoubleBuffer () - { + ~DoubleBuffer () { Dispose (); } } @@ -463,10 +481,22 @@ namespace System.Windows.Forms #endregion // ControlCollection Public Instance Properties #region ControlCollection Instance Methods - public virtual void Add (Control value) - { + public virtual void Add (Control value) { if (value == null) return; + + Form form_value = value as Form; + Form form_owner = owner as Form; + bool owner_permits_toplevels = (owner is MdiClient) || (form_owner != null && form_owner.IsMdiContainer); + bool child_is_toplevel = value.GetTopLevel(); + bool child_is_mdichild = form_value != null && form_value.IsMdiChild; + + if (child_is_toplevel && !(owner_permits_toplevels && child_is_mdichild)) + throw new ArgumentException("Cannot add a top level control to a control.", "value"); + + if (child_is_mdichild && form_value.MdiParent != null && form_value.MdiParent != owner && form_value.MdiParent != owner.Parent) { + throw new ArgumentException ("Form cannot be added to the Controls collection that has a valid MDI parent.", "value"); + } if (Contains (value)) { owner.PerformLayout(); @@ -500,39 +530,47 @@ namespace System.Windows.Forms value.InitLayout(); - owner.UpdateChildrenZOrder(); + if (owner.Visible) + owner.UpdateChildrenZOrder(); owner.PerformLayout(value, "Parent"); owner.OnControlAdded(new ControlEventArgs(value)); } - internal void AddToList (Control c) - { + internal void AddToList (Control c) { all_controls = null; list.Add (c); } - internal virtual void AddImplicit (Control control) - { + internal virtual void AddImplicit (Control control) { if (impl_list == null) impl_list = new ArrayList (); - if (AllContains (control)) + if (AllContains (control)) { + owner.PerformLayout (); return; + } + + if (control.parent != null) { + control.parent.Controls.Remove(control); + } all_controls = null; impl_list.Add (control); control.ChangeParent (owner); control.InitLayout (); - owner.UpdateChildrenZOrder (); - owner.PerformLayout (control, "Parent"); - owner.OnControlAdded (new ControlEventArgs (control)); + if (owner.Visible) + owner.UpdateChildrenZOrder (); + + // If we are adding a new control that isn't + // visible, don't trigger a layout + if (control.VisibleInternal) + owner.PerformLayout (control, "Parent"); } #if NET_2_0 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] #endif - public virtual void AddRange (Control[] controls) - { + public virtual void AddRange (Control[] controls) { if (controls == null) throw new ArgumentNullException ("controls"); @@ -546,8 +584,7 @@ namespace System.Windows.Forms } } - internal virtual void AddRangeImplicit (Control [] controls) - { + internal virtual void AddRangeImplicit (Control [] controls) { if (controls == null) throw new ArgumentNullException ("controls"); @@ -564,8 +601,7 @@ namespace System.Windows.Forms #if NET_2_0 new #endif - public virtual void Clear () - { + public virtual void Clear () { all_controls = null; // MS sends remove events in reverse order @@ -574,16 +610,14 @@ namespace System.Windows.Forms } } - internal virtual void ClearImplicit () - { + internal virtual void ClearImplicit () { if (impl_list == null) return; all_controls = null; impl_list.Clear (); } - public bool Contains (Control value) - { + public bool Contains (Control value) { for (int i = list.Count; i > 0; ) { i--; @@ -595,8 +629,7 @@ namespace System.Windows.Forms return false; } - internal bool ImplicitContains (Control value) - { + internal bool ImplicitContains (Control value) { if (impl_list == null) return false; @@ -611,8 +644,7 @@ namespace System.Windows.Forms return false; } - internal bool AllContains (Control value) - { + internal bool AllContains (Control value) { return Contains (value) || ImplicitContains (value); } @@ -623,19 +655,16 @@ namespace System.Windows.Forms } #endif - void ICollection.CopyTo (Array array, int index) - { + void ICollection.CopyTo (Array array, int index) { CopyTo (array, index); } #if !NET_2_0 - public void CopyTo (Array array, int index) - { + public void CopyTo (Array array, int index) { list.CopyTo(array, index); } - public override bool Equals (object other) - { + public override bool Equals (object other) { if (other is ControlCollection && (((ControlCollection)other).owner==this.owner)) { return(true); } else { @@ -690,19 +719,16 @@ namespace System.Windows.Forms #else public IEnumerator #endif - GetEnumerator () - { + GetEnumerator () { return list.GetEnumerator(); } - internal IEnumerator GetAllEnumerator () - { + internal IEnumerator GetAllEnumerator () { Control [] res = GetAllControls (); return res.GetEnumerator (); } - internal Control [] GetAllControls () - { + internal Control [] GetAllControls () { if (all_controls != null) return all_controls; @@ -719,14 +745,12 @@ namespace System.Windows.Forms } #if !NET_2_0 - public override int GetHashCode() - { + public override int GetHashCode() { return base.GetHashCode(); } #endif - public int IndexOf(Control control) - { + public int IndexOf(Control control) { return list.IndexOf(control); } @@ -744,8 +768,7 @@ namespace System.Windows.Forms } #endif - public virtual void Remove(Control value) - { + public virtual void Remove(Control value) { if (value == null) return; @@ -760,8 +783,7 @@ namespace System.Windows.Forms owner.UpdateChildrenZOrder(); } - internal virtual void RemoveImplicit (Control control) - { + internal virtual void RemoveImplicit (Control control) { if (impl_list != null) { all_controls = null; owner.PerformLayout (control, "Parent"); @@ -775,8 +797,7 @@ namespace System.Windows.Forms #if NET_2_0 new #endif - public void RemoveAt(int index) - { + public void RemoveAt(int index) { if (index < 0 || index >= list.Count) { throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls"); } @@ -791,13 +812,14 @@ namespace System.Windows.Forms if (index >= 0) RemoveAt (index); } - +#endif + +#if NET_2_0 public virtual void #else public void #endif - SetChildIndex(Control child, int newIndex) - { + SetChildIndex(Control child, int newIndex) { if (child == null) throw new ArgumentNullException ("child"); @@ -873,18 +895,21 @@ namespace System.Windows.Forms #region ControlCollection Interface Methods int IList.Add(object value) { - if (value == null) { - throw new ArgumentNullException("value", "Cannot add null controls"); - } - if (!(value is Control)) { throw new ArgumentException("Object of type Control required", "value"); } - if (((Control)value).GetTopLevel()) { - throw new ArgumentException("Cannot add a top level control to a control.", "value"); + if (value == null) { + throw new ArgumentException("value", "Cannot add null controls"); } + bool owner_permits_toplevels = (owner is MdiClient) || (owner is Form && ((Form)owner).IsMdiContainer); + bool child_is_toplevel = ((Control)value).GetTopLevel(); + bool child_is_mdichild = (value is Form && ((Form)value).IsMdiChild); + + if (child_is_toplevel && !(owner_permits_toplevels && child_is_mdichild)) + throw new ArgumentException("Cannot add a top level control to a control.", "value"); + return list.Add(value); } @@ -930,7 +955,7 @@ namespace System.Windows.Forms #endregion // ControlCollection Class #region Public Constructors - public Control() + public Control () { layout_type = LayoutType.Anchor; anchor_style = AnchorStyles.Top | AnchorStyles.Left; @@ -956,6 +981,7 @@ namespace System.Windows.Forms dist_bottom = 0; tab_stop = true; ime_mode = ImeMode.Inherit; + use_compatible_text_rendering = true; #if NET_2_0 backgroundimage_layout = ImageLayout.Tile; @@ -978,24 +1004,23 @@ namespace System.Windows.Forms text = string.Empty; name = string.Empty; + window_target = new ControlWindowTarget(this); window = new ControlNativeWindow(this); child_controls = CreateControlsInstance(); client_size = new Size(DefaultSize.Width, DefaultSize.Height); client_rect = new Rectangle(0, 0, DefaultSize.Width, DefaultSize.Height); - bounds.Size = SizeFromClientSize (client_size); - if ((CreateParams.Style & (int)WindowStyles.WS_CHILD) == 0) { - bounds.X=-1; - bounds.Y=-1; - } + bounds.Size = InternalSizeFromClientSize (client_size); explicit_bounds = bounds; } - public Control(Control parent, string text) : this() { + public Control (Control parent, string text) : this() + { Text=text; Parent=parent; } - public Control(Control parent, string text, int left, int top, int width, int height) : this() { + public Control (Control parent, string text, int left, int top, int width, int height) : this() + { Parent=parent; bounds.X=left; bounds.Y=top; @@ -1005,11 +1030,13 @@ namespace System.Windows.Forms Text=text; } - public Control(string text) : this() { + public Control (string text) : this() + { Text=text; } - public Control(string text, int left, int top, int width, int height) : this() { + public Control (string text, int left, int top, int width, int height) : this() + { bounds.X=left; bounds.Y=top; bounds.Width=width; @@ -1020,7 +1047,8 @@ namespace System.Windows.Forms private delegate void RemoveDelegate(object c); - protected override void Dispose(bool disposing) { + protected override void Dispose (bool disposing) + { if (!is_disposed && disposing) { Capture = false; @@ -1036,8 +1064,8 @@ namespace System.Windows.Forms } if (this.InvokeRequired) { - if (Application.MessageLoop) { - this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null, true); + if (Application.MessageLoop && IsHandleCreated) { + this.BeginInvokeInternal(new MethodInvoker(DestroyHandle), null); } } else { DestroyHandle(); @@ -1060,6 +1088,26 @@ namespace System.Windows.Forms #endregion // Public Constructors #region Internal Properties + // Control is currently selected, like Focused, except maintains state + // when Form loses focus + internal bool InternalSelected { + get { + IContainerControl container; + + container = GetContainerControl(); + + if (container != null && container.ActiveControl == this) + return true; + + return false; + } + } + + // Mouse is currently within the control's bounds + internal bool Entered { + get { return this.is_entered; } + } + internal bool VisibleInternal { get { return is_visible; } } @@ -1088,6 +1136,9 @@ namespace System.Windows.Forms } } } + + internal Size InternalClientSize { set { this.client_size = value; } } + internal virtual bool ActivateOnShow { get { return true; } } #endregion // Internal Properties #region Private & Internal Methods @@ -1114,24 +1165,18 @@ namespace System.Windows.Forms } #endif - internal IAsyncResult BeginInvokeInternal (Delegate method, object [] args, bool disposing) { + internal IAsyncResult BeginInvokeInternal (Delegate method, object [] args) { + return BeginInvokeInternal (method, args, FindControlToInvokeOn ()); + } + + internal IAsyncResult BeginInvokeInternal (Delegate method, object [] args, Control control) { AsyncMethodResult result; AsyncMethodData data; - if (!disposing) { - Control p = this; - do { - if (!p.IsHandleCreated) { - throw new InvalidOperationException("Cannot call Invoke or InvokeAsync on a control until the window handle is created"); - } - p = p.parent; - } while (p != null); - } - result = new AsyncMethodResult (); data = new AsyncMethodData (); - data.Handle = window.Handle; + data.Handle = control.Handle; data.Method = method; data.Args = args; data.Result = result; @@ -1153,13 +1198,11 @@ namespace System.Windows.Forms } - internal void PointToClient (ref int x, ref int y) - { + internal void PointToClient (ref int x, ref int y) { XplatUI.ScreenToClient (Handle, ref x, ref y); } - internal void PointToScreen (ref int x, ref int y) - { + internal void PointToScreen (ref int x, ref int y) { XplatUI.ClientToScreen (Handle, ref x, ref y); } @@ -1178,22 +1221,34 @@ namespace System.Windows.Forms return bmp_g; } } - - private void InvalidateBackBuffer () + + private Control FindControlToInvokeOn () { + Control p = this; + do { + if (p.IsHandleCreated) + break; + p = p.parent; + } while (p != null); + + if (p == null || !p.IsHandleCreated) + throw new InvalidOperationException ("Cannot call Invoke or BeginInvoke on a control until the window handle is created"); + + return p; + } + + private void InvalidateBackBuffer () { if (backbuffer != null) backbuffer.Invalidate (); } - private DoubleBuffer GetBackBuffer () - { + private DoubleBuffer GetBackBuffer () { if (backbuffer == null) backbuffer = new DoubleBuffer (this); return backbuffer; } - private void DisposeBackBuffer () - { + private void DisposeBackBuffer () { if (backbuffer != null) { backbuffer.Dispose (); backbuffer = null; @@ -1245,8 +1300,7 @@ namespace System.Windows.Forms } // This method exists so controls overriding OnPaintBackground can have default background painting done - internal virtual void PaintControlBackground (PaintEventArgs pevent) - { + internal virtual void PaintControlBackground (PaintEventArgs pevent) { if (GetStyle(ControlStyles.SupportsTransparentBackColor) && (BackColor.A != 0xff)) { if (parent != null) { PaintEventArgs parent_pe; @@ -1316,8 +1370,7 @@ namespace System.Windows.Forms DrawBackgroundImage (pevent.Graphics); } - void DrawBackgroundImage (Graphics g) - { + void DrawBackgroundImage (Graphics g) { #if NET_2_0 Rectangle drawing_rectangle = new Rectangle (); g.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle); @@ -1363,22 +1416,19 @@ namespace System.Windows.Forms #endif } - internal virtual void DndEnter (DragEventArgs e) - { + internal virtual void DndEnter (DragEventArgs e) { try { OnDragEnter (e); } catch { } } - internal virtual void DndOver (DragEventArgs e) - { + internal virtual void DndOver (DragEventArgs e) { try { OnDragOver (e); } catch { } } - internal virtual void DndDrop (DragEventArgs e) - { + internal virtual void DndDrop (DragEventArgs e) { try { OnDragDrop (e); } catch (Exception exc) { @@ -1387,22 +1437,19 @@ namespace System.Windows.Forms } } - internal virtual void DndLeave (EventArgs e) - { + internal virtual void DndLeave (EventArgs e) { try { OnDragLeave (e); } catch { } } - internal virtual void DndFeedback(GiveFeedbackEventArgs e) - { + internal virtual void DndFeedback(GiveFeedbackEventArgs e) { try { OnGiveFeedback(e); } catch { } } - internal virtual void DndContinueDrag(QueryContinueDragEventArgs e) - { + internal virtual void DndContinueDrag(QueryContinueDragEventArgs e) { try { OnQueryContinueDrag(e); } catch { } @@ -1424,23 +1471,19 @@ namespace System.Windows.Forms } - internal virtual void FireEnter () - { + internal virtual void FireEnter () { OnEnter (EventArgs.Empty); } - internal virtual void FireLeave () - { + internal virtual void FireLeave () { OnLeave (EventArgs.Empty); } - internal virtual void FireValidating (CancelEventArgs ce) - { + internal virtual void FireValidating (CancelEventArgs ce) { OnValidating (ce); } - internal virtual void FireValidated () - { + internal virtual void FireValidated () { OnValidated (EventArgs.Empty); } @@ -1613,6 +1656,7 @@ namespace System.Windows.Forms OnClick(EventArgs.Empty); #else OnDoubleClick(me); + OnMouseDoubleClick (me); } else { OnClick(me); OnMouseClick (me); @@ -1621,16 +1665,14 @@ namespace System.Windows.Forms } } - internal void CaptureWithConfine (Control ConfineWindow) - { + internal void CaptureWithConfine (Control ConfineWindow) { if (this.IsHandleCreated && !is_captured) { is_captured = true; XplatUI.GrabWindow (this.window.Handle, ConfineWindow.Handle); } } - private void CheckDataBindings () - { + private void CheckDataBindings () { if (data_bindings == null) return; @@ -1661,9 +1703,13 @@ namespace System.Windows.Forms parent = new_parent; - if (IsHandleCreated) + if (IsHandleCreated) { XplatUI.SetParent(Handle, (new_parent == null || !new_parent.IsHandleCreated) ? IntPtr.Zero : new_parent.Handle); + if (this is Form ) { + ((Form) this).ChangingParent (new_parent); + } + } OnParentChanged(EventArgs.Empty); @@ -1703,11 +1749,27 @@ namespace System.Windows.Forms } } + // Sometimes we need to do this calculation without it being virtual (constructor) + internal Size InternalSizeFromClientSize (Size clientSize) + { + Rectangle ClientRect; + Rectangle WindowRect; + CreateParams cp; + + ClientRect = new Rectangle (0, 0, clientSize.Width, clientSize.Height); + cp = this.CreateParams; + + if (XplatUI.CalculateWindowRect (ref ClientRect, cp.Style, cp.ExStyle, null, out WindowRect)) + return new Size (WindowRect.Width, WindowRect.Height); + + return Size.Empty; + } + private void UpdateDistances() { if (parent != null) { - if (bounds.Width > 0) + if (bounds.Width >= 0) dist_right = parent.ClientSize.Width - bounds.X - bounds.Width; - if (bounds.Height > 0) + if (bounds.Height >= 0) dist_bottom = parent.ClientSize.Height - bounds.Y - bounds.Height; } } @@ -1799,11 +1861,15 @@ namespace System.Windows.Forms [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public string AccessibleDefaultActionDescription { get { - return AccessibilityObject.default_action; + if (accessibility_object != null) + return accessibility_object.default_action; + else + return null; } set { - AccessibilityObject.default_action=value; + if (accessibility_object != null) + accessibility_object.default_action = value; } } @@ -1812,11 +1878,15 @@ namespace System.Windows.Forms [MWFCategory("Accessibility")] public string AccessibleDescription { get { - return AccessibilityObject.description; + if (accessibility_object != null) + return accessibility_object.description; + else + return null; } set { - AccessibilityObject.description=value; + if (accessibility_object != null) + accessibility_object.description = value; } } @@ -1825,11 +1895,15 @@ namespace System.Windows.Forms [MWFCategory("Accessibility")] public string AccessibleName { get { - return AccessibilityObject.Name; + if (accessibility_object != null) + return accessibility_object.Name; + else + return null; } set { - AccessibilityObject.Name=value; + if (accessibility_object != null) + accessibility_object.Name = value; } } @@ -1837,11 +1911,15 @@ namespace System.Windows.Forms [MWFDescription("Role of the control"), MWFCategory("Accessibility")] public AccessibleRole AccessibleRole { get { - return AccessibilityObject.role; + if (accessibility_object != null) + return accessibility_object.role; + else + return AccessibleRole.Default; } set { - AccessibilityObject.role=value; + if (accessibility_object != null) + accessibility_object.role = value; } } @@ -1875,8 +1953,12 @@ namespace System.Windows.Forms set { layout_type = LayoutType.Anchor; + if (anchor_style == value) + return; + anchor_style=value; - + dock_style = DockStyle.None; + UpdateDistances (); if (parent != null) @@ -2097,12 +2179,14 @@ namespace System.Windows.Forms } set { - if (this.IsHandleCreated && value != is_captured) { + // Call OnMouseCaptureChanged when we get WM_CAPTURECHANGED. + if (value != is_captured) { if (value) { is_captured = true; - XplatUI.GrabWindow(this.window.Handle, IntPtr.Zero); + XplatUI.GrabWindow(Handle, IntPtr.Zero); } else { - XplatUI.UngrabWindow(this.window.Handle); + if (IsHandleCreated) + XplatUI.UngrabWindow(Handle); is_captured = false; } } @@ -2207,8 +2291,7 @@ namespace System.Windows.Forms } } - internal virtual ContextMenu GetContextMenuInternal () - { + internal virtual ContextMenu GetContextMenuInternal () { return context_menu; } @@ -2339,6 +2422,7 @@ namespace System.Windows.Forms } dock_style = value; + anchor_style = AnchorStyles.Top | AnchorStyles.Left; if (dock_style == DockStyle.None) { if (explicit_bounds == Rectangle.Empty) @@ -2570,13 +2654,14 @@ namespace System.Windows.Forms [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsHandleCreated { get { - if ((window != null) && (window.Handle != IntPtr.Zero)) { - Hwnd hwnd = Hwnd.ObjectFromHandle (window.Handle); - if (hwnd != null && !hwnd.zombie) - return true; - } + if (window == null || window.Handle == IntPtr.Zero) + return false; - return false; + Hwnd hwnd = Hwnd.ObjectFromHandle (window.Handle); + if (hwnd != null && hwnd.zombie) + return false; + + return true; } } @@ -2703,6 +2788,9 @@ namespace System.Windows.Forms // set. if (attrs != null && attrs.Length > 0) a = (AssemblyProductAttribute) attrs [0]; + if (a == null) { + return GetType ().Namespace; + } return a.Product; } } @@ -2958,13 +3046,8 @@ namespace System.Windows.Forms [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public IWindowTarget WindowTarget { - get { - return null; - } - - set { - ; // MS Internal - } + get { return window_target; } + set { window_target = value; } } #endregion // Public Instance Properties @@ -3010,7 +3093,7 @@ namespace System.Windows.Forms create_params.ClassName = XplatUI.DefaultClassName; - create_params.ClassStyle = 0; + create_params.ClassStyle = (int)(XplatUIWin32.ClassStyle.CS_OWNDC | XplatUIWin32.ClassStyle.CS_DBLCLKS); create_params.ExStyle = 0; create_params.Param = 0; @@ -3033,12 +3116,12 @@ namespace System.Windows.Forms } switch (border_style) { - case BorderStyle.FixedSingle: - create_params.Style |= (int) WindowStyles.WS_BORDER; - break; - case BorderStyle.Fixed3D: - create_params.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE; - break; + case BorderStyle.FixedSingle: + create_params.Style |= (int) WindowStyles.WS_BORDER; + break; + case BorderStyle.Fixed3D: + create_params.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE; + break; } return create_params; @@ -3171,19 +3254,24 @@ namespace System.Windows.Forms object [] prms = null; if (method is EventHandler) prms = new object [] { this, EventArgs.Empty }; - return BeginInvokeInternal(method, prms, false); + return BeginInvokeInternal(method, prms); } [EditorBrowsable(EditorBrowsableState.Advanced)] - public IAsyncResult BeginInvoke (Delegate method, object[] args) { - return BeginInvokeInternal (method, args, false); +#if NET_2_0 + public IAsyncResult BeginInvoke (Delegate method, params object[] args) +#else + public IAsyncResult BeginInvoke (Delegate method, object[] args) +#endif + { + return BeginInvokeInternal (method, args); } public void BringToFront() { if (parent != null) { parent.child_controls.SetChildIndex(this, 0); - parent.Refresh(); - } else { + } + else if (IsHandleCreated) { XplatUI.SetZOrder(Handle, IntPtr.Zero, false, false); } } @@ -3198,8 +3286,7 @@ namespace System.Windows.Forms return false; } - public void CreateControl () - { + public void CreateControl () { if (is_disposed) { throw new ObjectDisposedException(GetType().FullName.ToString()); } @@ -3207,27 +3294,23 @@ namespace System.Windows.Forms return; } + if (!is_visible) { + return; + } + if (!IsHandleCreated) { CreateHandle(); } if (!is_created) { is_created = true; - } - - Control [] controls = child_controls.GetAllControls (); - for (int i=0; i 1) { - mouse_clicks = 1; + case Msg.WM_MOUSEHOVER: { + WmMouseHover (ref m); + return; + } + + case Msg.WM_SYSKEYUP: { + WmSysKeyUp (ref m); + return; + } + + case Msg.WM_SYSKEYDOWN: + case Msg.WM_KEYDOWN: + case Msg.WM_KEYUP: + case Msg.WM_SYSCHAR: + case Msg.WM_CHAR: { + WmKeys (ref m); + return; + } + + case Msg.WM_HELP: { + WmHelp (ref m); + return; + } + + case Msg.WM_KILLFOCUS: { + WmKillFocus (ref m); + return; + } + + case Msg.WM_SETFOCUS: { + WmSetFocus (ref m); + return; } - return; - } - case Msg.WM_LBUTTONDOWN: { - if (CanSelect) { - Select (true, true); - } - InternalCapture = true; - OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); - - return; - } + case Msg.WM_SYSCOLORCHANGE: { + WmSysColorChange (ref m); + return; + } - case Msg.WM_LBUTTONDBLCLK: { - InternalCapture = true; - mouse_clicks++; - OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); - return; + case Msg.WM_SETCURSOR: { + WmSetCursor (ref m); + return; + } + + case Msg.WM_CAPTURECHANGED: { + WmCaptureChanged (ref m); + return; + } + + default: + DefWndProc(ref m); + return; } + } + #endregion // Public Instance Methods - case Msg.WM_MBUTTONUP: { - MouseEventArgs me; + #region WM methods + + private void WmDestroy (ref Message m) { + OnHandleDestroyed(EventArgs.Empty); +#if DebugRecreate + IntPtr handle = window.Handle; +#endif + window.InvalidateHandle(); - me = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()) | MouseButtons.Middle, - mouse_clicks, - LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0); + if (is_recreating) { +#if DebugRecreate + Console.WriteLine ("Creating handle for {0:X}", handle.ToInt32()); +#endif + CreateHandle(); +#if DebugRecreate + Console.WriteLine (" + new handle = {0:X}", Handle.ToInt32()); +#endif + is_recreating = false; + } + } - HandleClick(mouse_clicks, me); - OnMouseUp (me); - if (InternalCapture) { - InternalCapture = false; - } - if (mouse_clicks > 1) { - mouse_clicks = 1; + private void WmWindowPosChanged (ref Message m) { + if (Visible) { + Rectangle save_bounds = explicit_bounds; + UpdateBounds(); + explicit_bounds = save_bounds; + if (GetStyle(ControlStyles.ResizeRedraw)) { + Invalidate(); } - return; } - - case Msg.WM_MBUTTONDOWN: { - InternalCapture = true; - OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); + } + + + // Nice description of what should happen when handling WM_PAINT + // can be found here: http://pluralsight.com/wiki/default.aspx/Craig/FlickerFreeControlDrawing.html + // and here http://msdn.microsoft.com/msdnmag/issues/06/03/WindowsFormsPerformance/ + private void WmPaint (ref Message m) { + PaintEventArgs paint_event; + + IntPtr handle = Handle; + + paint_event = XplatUI.PaintEventStart (handle, true); + + if (paint_event == null) return; + + DoubleBuffer current_buffer = null; + if (UseDoubleBuffering) { + current_buffer = GetBackBuffer (); + if (!current_buffer.InvalidRegion.IsVisible (paint_event.ClipRectangle)) { + // Just blit the previous image + current_buffer.Blit (paint_event); + XplatUI.PaintEventEnd (handle, true); + return; + } + current_buffer.Start (paint_event); + } + + if (!GetStyle(ControlStyles.Opaque)) { + OnPaintBackground (paint_event); } - case Msg.WM_MBUTTONDBLCLK: { - InternalCapture = true; - mouse_clicks++; - OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); - return; + // Button-derived controls choose to ignore their Opaque style, give them a chance to draw their background anyways + OnPaintBackgroundInternal (paint_event); + + OnPaintInternal(paint_event); + if (!paint_event.Handled) { + OnPaint (paint_event); + } + + if (current_buffer != null) { + current_buffer.End (paint_event); } - case Msg.WM_RBUTTONUP: { - MouseEventArgs me; - Point pt; - pt = new Point(LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ())); - pt = PointToScreen(pt); + XplatUI.PaintEventEnd (handle, true); + } - XplatUI.SendMessage(m.HWnd, Msg.WM_CONTEXTMENU, m.HWnd, (IntPtr)(pt.X + (pt.Y << 16))); + private void WmEraseBackground (ref Message m) { + // The DefWndProc will never have to handle this, we always paint the background in managed code + // In theory this code would look at ControlStyles.AllPaintingInWmPaint and and call OnPaintBackground + // here but it just makes things more complicated... + m.Result = (IntPtr)1; + } - me = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()) | MouseButtons.Right, - mouse_clicks, - LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0); + private void WmLButtonUp (ref Message m) { + MouseEventArgs me; - HandleClick(mouse_clicks, me); - OnMouseUp (me); + me = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()) | MouseButtons.Left, + mouse_clicks, + LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0); - if (InternalCapture) { - InternalCapture = false; - } + HandleClick(mouse_clicks, me); + OnMouseUp (me); - if (mouse_clicks > 1) { - mouse_clicks = 1; - } - return; + if (InternalCapture) { + InternalCapture = false; } + + if (mouse_clicks > 1) { + mouse_clicks = 1; + } + } - case Msg.WM_RBUTTONDOWN: { - InternalCapture = true; - OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); - return; + private void WmLButtonDown (ref Message m) { + if (CanSelect) { + Select (true, true); } + InternalCapture = true; + OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } - case Msg.WM_RBUTTONDBLCLK: { - InternalCapture = true; - mouse_clicks++; - OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); - return; + private void WmLButtonDblClick (ref Message m) { + InternalCapture = true; + mouse_clicks++; + OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } + + private void WmMButtonUp (ref Message m) { + MouseEventArgs me; + + me = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()) | MouseButtons.Middle, + mouse_clicks, + LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0); + + HandleClick(mouse_clicks, me); + OnMouseUp (me); + if (InternalCapture) { + InternalCapture = false; + } + if (mouse_clicks > 1) { + mouse_clicks = 1; } + } + + private void WmMButtonDown (ref Message m) { + InternalCapture = true; + OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } - case Msg.WM_CONTEXTMENU: { - if (context_menu != null) { - Point pt; + private void WmMButtonDblClick (ref Message m) { + InternalCapture = true; + mouse_clicks++; + OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } - pt = new Point(LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ())); + private void WmRButtonUp (ref Message m) { + MouseEventArgs me; + Point pt; - if (pt.X == -1 || pt.Y == -1) { - pt.X = (this.Width / 2) + this.Left; - pt.Y = (this.Height / 2) + this.Top; - pt = this.PointToScreen (pt); - } + pt = new Point(LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ())); + pt = PointToScreen(pt); + + XplatUI.SendMessage(m.HWnd, Msg.WM_CONTEXTMENU, m.HWnd, (IntPtr)(pt.X + (pt.Y << 16))); + + me = new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()) | MouseButtons.Right, + mouse_clicks, + LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0); + + HandleClick(mouse_clicks, me); + OnMouseUp (me); + + if (InternalCapture) { + InternalCapture = false; + } + + if (mouse_clicks > 1) { + mouse_clicks = 1; + } + } - context_menu.Show (this, PointToClient (pt)); - return; + private void WmRButtonDown (ref Message m) { + InternalCapture = true; + OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } + + private void WmRButtonDblClick (ref Message m) { + InternalCapture = true; + mouse_clicks++; + OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } + + private void WmContextMenu (ref Message m) { + if (context_menu != null) { + Point pt; + + pt = new Point(LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ())); + + if (pt.X == -1 || pt.Y == -1) { + pt.X = (this.Width / 2) + this.Left; + pt.Y = (this.Height / 2) + this.Top; + pt = this.PointToScreen (pt); } + + context_menu.Show (this, PointToClient (pt)); + return; + } #if NET_2_0 // If there isn't a regular context menu, show the Strip version @@ -4603,134 +4837,150 @@ namespace System.Windows.Forms return; } #endif - DefWndProc(ref m); - return; - } - - case Msg.WM_MOUSEWHEEL: { - DefWndProc(ref m); - OnMouseWheel (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - HighOrder(m.WParam.ToInt32()))); - return; - } + DefWndProc(ref m); + } + private void WmCreate (ref Message m) { + OnHandleCreated(EventArgs.Empty); + } - case Msg.WM_MOUSEMOVE: { - OnMouseMove (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), - mouse_clicks, - LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), - 0)); - return; - } + private void WmMouseWheel (ref Message m) { + DefWndProc(ref m); + OnMouseWheel (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + HighOrder(m.WParam.ToInt32()))); + } - case Msg.WM_MOUSE_ENTER: { - if (is_entered) { - return; - } - is_entered = true; - OnMouseEnter(EventArgs.Empty); - return; - } - case Msg.WM_MOUSE_LEAVE: { - is_entered=false; - OnMouseLeave(EventArgs.Empty); - return; - } + private void WmMouseMove (ref Message m) { + OnMouseMove (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), + mouse_clicks, + LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), + 0)); + } - case Msg.WM_MOUSEHOVER: { - OnMouseHover(EventArgs.Empty); + private void WmMouseEnter (ref Message m) { + if (is_entered) { return; } + is_entered = true; + OnMouseEnter(EventArgs.Empty); + } - case Msg.WM_SYSKEYUP: { - if (ProcessKeyMessage(ref m)) { - m.Result = IntPtr.Zero; - return; - } + private void WmMouseLeave (ref Message m) { + is_entered=false; + OnMouseLeave(EventArgs.Empty); + } - if ((m.WParam.ToInt32() & (int)Keys.KeyCode) == (int)Keys.Menu) { - Form form; + private void WmMouseHover (ref Message m) { + OnMouseHover(EventArgs.Empty); + } - form = FindForm(); - if (form != null && form.ActiveMenu != null) { - form.ActiveMenu.ProcessCmdKey(ref m, (Keys)m.WParam.ToInt32()); + private void WmShowWindow (ref Message m) { + if (m.WParam.ToInt32() != 0) { + CreateControl (); + /* if we're being shown, make sure our child controls all have their handles created */ + Control [] controls = child_controls.GetAllControls (); + for (int i=0; i