1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
26 // Aleksey Ryabchuk ryabchuk@yahoo.com
27 // Alexandre Pigolkine pigolkine@gmx.de
28 // Dennis Hayes dennish@raytek.com
29 // Jaak Simm jaaksimm@firm.ee
30 // John Sohn jsohn@columbus.rr.com
34 // $Log: Control.cs,v $
35 // Revision 1.21 2004/08/11 18:59:45 pbartok
36 // - Major cleanup of my SetBounds/SetBoundsCore/UpdateBounds mess
37 // (It seems that SetBounds is just a front for SetBoundsCore and
38 // SetBoundsCore updates the underlying window system and UpdateBounds is
39 // responsible for updating the variables associated with the Control and
40 // sending the events)
41 // - Major cleanup of Size handling; we now have two sizes, client_size and
42 // bounds. Bounds defines the window with decorations, client_size without
45 // Revision 1.20 2004/08/11 15:13:32 pbartok
46 // - Now properly reparents windows
48 // Revision 1.19 2004/08/11 14:37:11 pbartok
51 // Revision 1.18 2004/08/11 13:47:22 pbartok
52 // - Rewrote the collection stuff. Might not be as fast now, not keeping
53 // the number of children around and accessible directly, but it's more
56 // Revision 1.17 2004/08/10 18:32:10 jordi
57 // throw ontextchange event
59 // Revision 1.16 2004/08/10 17:43:04 pbartok
60 // - Added more to the still unfinished Dock/Anchor layout code
62 // Revision 1.15 2004/08/10 15:08:05 jackson
63 // Control will now handle the buffering code, so each control does not have to implement this.
65 // Revision 1.14 2004/08/09 22:11:25 pbartok
66 // - Added incomplete dock layout code
67 // - Added support for mouse wheel
69 // Revision 1.13 2004/08/09 17:25:56 jackson
70 // Use new color names
72 // Revision 1.12 2004/08/09 15:54:51 jackson
73 // Get default properties from the theme.
75 // Revision 1.11 2004/08/06 21:30:56 pbartok
76 // - Fixed recursive loop when resizing
77 // - Improved/fixed redrawing on expose messages
79 // Revision 1.10 2004/08/06 15:53:39 jordi
80 // X11 keyboard navigation
82 // Revision 1.9 2004/08/04 21:14:26 pbartok
83 // - Fixed Invalidation bug (calculated wrong client area)
84 // - Added ClientSize setter
86 // Revision 1.8 2004/08/04 20:11:24 pbartok
87 // - Added Invalidate handling
89 // Revision 1.7 2004/07/27 10:38:17 jordi
90 // changes to be able to run winforms samples
92 // Revision 1.6 2004/07/19 19:09:42 jordi
93 // label control re-written: added missing functionlity, events, and properties
95 // Revision 1.5 2004/07/19 16:49:23 jordi
96 // fixes SetBounds logic
98 // Revision 1.4 2004/07/19 07:29:35 jordi
99 // Call RefreshWindow only if the window has created
101 // Revision 1.3 2004/07/15 17:03:35 jordi
102 // added basic mouse handeling events
104 // Revision 1.2 2004/07/13 15:31:45 jordi
105 // commit: new properties and fixes form size problems
107 // Revision 1.1 2004/07/09 05:21:25 pbartok
108 // - Initial check-in
115 using System.Drawing;
116 using System.ComponentModel;
117 using System.Collections;
118 using System.Diagnostics;
119 using System.Threading;
120 using System.Runtime.InteropServices;
122 namespace System.Windows.Forms
124 public class Control : Component, ISynchronizeInvoke, IWin32Window
126 #region Local Variables
128 internal Rectangle bounds; // bounding rectangle for control (client area + decorations)
129 internal object creator_thread; // thread that created the control
130 internal ControlNativeWindow window; // object for native window handle
131 internal string name; // for object naming
134 internal bool has_focus; // true if control has focus
135 internal bool is_visible; // true if control is visible
136 internal bool is_enabled; // true if control is enabled (usable/not grayed out)
137 internal int tab_index; // position in tab order of siblings
138 internal bool is_disposed; // has the window already been disposed?
139 internal Size client_size; // size of the client area (window excluding decorations)
140 internal ControlStyles control_style; // rather win32-specific, style bits for control
143 internal Color foreground_color; // foreground color for control
144 internal Color background_color; // background color for control
145 internal Image background_image; // background image for control
146 internal Font font; // font for control
147 internal string text; // window/title text for control
150 internal AnchorStyles anchor_style; // anchoring requirements for our control
151 internal DockStyle dock_style; // docking requirements for our control (supercedes anchoring)
152 internal int prev_width; // previous width of the control; required for anchoring
153 internal int prev_height; // previous height of our control; required for anchoring
154 internal Size prev_size;
156 // to be categorized...
157 static internal Hashtable controls; // All of the applications controls, in a flat list
158 internal ControlCollection child_controls; // our children
159 internal Control parent; // our parent control
160 internal AccessibleObject accessibility_object; // object that contains accessibility information about our control
161 internal BindingContext binding_context; // TODO
162 internal RightToLeft right_to_left; // drawing direction for control
163 internal int layout_suspended;
165 private Graphics dc_mem;
166 private Bitmap bmp_mem;
168 #endregion // Local Variables
170 #region Private Classes
171 // This helper class allows us to dispatch messages to Control.WndProc
172 internal class ControlNativeWindow : NativeWindow {
173 private Control control;
175 public ControlNativeWindow(Control control) : base() {
176 this.control=control;
179 protected override void WndProc(ref Message m) {
180 control.WndProc(ref m);
185 #region Public Classes
186 public class ControlCollection : IList, ICollection, ICloneable, IEnumerable {
187 #region ControlCollection Local Variables
188 private ArrayList list;
189 private Control owner;
190 #endregion // ControlCollection Local Variables
192 #region ControlCollection Public Constructor
193 public ControlCollection(Control owner) {
195 this.list=new ArrayList();
199 #region ControlCollection Public Instance Properties
206 public bool IsReadOnly {
208 return list.IsReadOnly;
212 public virtual Control this[int index] {
214 if (index < 0 || index >= list.Count) {
215 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
217 return (Control)list[index];
220 #endregion // ControlCollection Public Instance Properties
222 #region ControlCollection Private Instance Methods
223 public virtual void Add(Control value) {
224 for (int i=0; i<list.Count; i++) {
225 if (list[i]==value) {
226 // Do we need to do anything here?
234 public virtual void AddRange(Control[] controls) {
235 for (int i=0; i<controls.Length; i++) {
240 public virtual void Clear() {
241 owner.SuspendLayout();
243 owner.ResumeLayout();
246 public virtual bool Contains(Control value) {
247 return list.Contains(value);
250 public void CopyTo(Array array, int index) {
251 list.CopyTo(array, index);
254 public override bool Equals(object other) {
255 if (other is ControlCollection && (((ControlCollection)other).owner==this.owner)) {
262 public int GetChildIndex(Control child) {
263 return GetChildIndex(child, false);
266 public int GetChildIndex(Control child, bool throwException) {
269 index=list.IndexOf(child);
271 if (index==-1 && throwException) {
272 throw new ArgumentException("Not a child control", "child");
277 public IEnumerator GetEnumerator() {
278 return list.GetEnumerator();
281 public override int GetHashCode() {
282 return base.GetHashCode();
285 public int IndexOf(Control control) {
286 return list.IndexOf(control);
289 public virtual void Remove(Control value) {
293 public void RemoveAt(int index) {
294 if (index<0 || index>=list.Count) {
295 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
298 list.RemoveAt(index);
301 public void SetChildIndex(Control child, int newIndex) {
304 old_index=list.IndexOf(child);
306 throw new ArgumentException("Not a child control", "child");
309 if (old_index==newIndex) {
315 if (newIndex>list.Count) {
318 list.Insert(newIndex, child);
321 #endregion // ControlCollection Private Instance Methods
323 #region ControlCollection Interface Properties
324 object IList.this[int index] {
326 if (index<0 || index>=list.Count) {
327 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
333 if (!(value is Control)) {
334 throw new ArgumentException("Object of type Control required", "value");
337 list[index]=(Control)value;
341 bool IList.IsFixedSize {
347 bool IList.IsReadOnly {
349 return list.IsReadOnly;
353 bool ICollection.IsSynchronized {
355 return list.IsSynchronized;
359 object ICollection.SyncRoot {
361 return list.SyncRoot;
364 #endregion // ControlCollection Interface Properties
366 #region ControlCollection Interface Methods
367 int IList.Add(object value) {
369 throw new ArgumentNullException("value", "Cannot add null controls");
372 if (!(value is Control)) {
373 throw new ArgumentException("Object of type Control required", "value");
376 return list.Add(value);
379 bool IList.Contains(object value) {
380 if (!(value is Control)) {
381 throw new ArgumentException("Object of type Control required", "value");
384 return this.Contains((Control) value);
387 int IList.IndexOf(object value) {
388 if (!(value is Control)) {
389 throw new ArgumentException("Object of type Control required", "value");
392 return this.IndexOf((Control) value);
395 void IList.Insert(int index, object value) {
396 if (!(value is Control)) {
397 throw new ArgumentException("Object of type Control required", "value");
399 list.Insert(index, value);
402 void IList.Remove(object value) {
403 if (!(value is Control)) {
404 throw new ArgumentException("Object of type Control required", "value");
409 void ICollection.CopyTo(Array array, int index) {
411 list.CopyTo(array, index);
415 Object ICloneable.Clone() {
416 ControlCollection clone = new ControlCollection(this.owner);
417 clone.list=(ArrayList)list.Clone(); // FIXME: Do we need this?
420 #endregion // ControlCollection Interface Methods
422 #endregion // ControlCollection Class
424 #region Public Constructors
426 creator_thread = Thread.CurrentThread;
427 controls = new Hashtable();
428 child_controls = CreateControlsInstance();
429 bounds = new Rectangle(0, 0, DefaultSize.Width, DefaultSize.Height);
430 client_size = new Size(DefaultSize.Width, DefaultSize.Height);
431 prev_size = client_size;
437 layout_suspended = 0;
440 background_image = null;
443 public Control(Control parent, string text) : this() {
448 public Control(Control parent, string text, int left, int top, int width, int height) : this() {
457 public Control(string text) : this() {
461 public Control(string text, int left, int top, int width, int height) : this() {
468 #endregion // Public Constructors
470 #region Public Static Properties
471 public static Color DefaultBackColor {
473 return ThemeEngine.Current.DefaultControlBackColor;
477 public static Font DefaultFont {
479 return ThemeEngine.Current.DefaultFont;
483 public static Color DefaultForeColor {
485 return ThemeEngine.Current.DefaultControlForeColor;
489 public static Keys ModifierKeys {
491 return XplatUI.State.ModifierKeys;
495 public static MouseButtons MouseButtons {
497 return XplatUI.State.MouseButtons;
501 public static Point MousePosition {
503 return XplatUI.State.MousePosition;
506 #endregion // Public Static Properties
508 #region Public Instance Properties
509 public AccessibleObject AccessibilityObject {
511 if (accessibility_object==null) {
512 accessibility_object=CreateAccessibilityInstance();
514 return accessibility_object;
518 public string AccessibleDefaultActionDescription {
520 return AccessibilityObject.default_action;
524 AccessibilityObject.default_action=value;
528 public string AccessibleDescription {
530 return AccessibilityObject.description;
534 AccessibilityObject.description=value;
538 public string AccessibleName {
540 return AccessibilityObject.Name;
544 AccessibilityObject.Name=value;
548 public AccessibleRole AccessibleRole {
550 return AccessibilityObject.role;
554 AccessibilityObject.role=value;
558 public virtual bool AllowDrop {
560 return XplatUI.State.DropTarget;
564 XplatUI.State.DropTarget=value;
568 public virtual AnchorStyles Anchor {
578 public virtual Color BackColor {
580 if (background_color.IsEmpty) {
582 return parent.BackColor;
584 return DefaultBackColor;
586 return background_color;
590 background_color=value;
595 public virtual Image BackgroundImage {
597 return background_image;
601 if (background_image!=value) {
602 background_image=value;
603 OnBackgroundImageChanged(EventArgs.Empty);
608 public virtual BindingContext BindingContext {
610 throw new NotImplementedException();
614 throw new NotImplementedException();
621 return bounds.Y+bounds.Height;
625 public Rectangle Bounds {
631 SetBoundsCore(value.Left, value.Top, value.Width, value.Height, BoundsSpecified.All);
635 public bool CanFocus {
637 throw new NotImplementedException();
641 public bool CanSelect {
643 throw new NotImplementedException();
647 public bool Capture {
649 throw new NotImplementedException();
653 throw new NotImplementedException();
657 public bool CausesValidation {
659 throw new NotImplementedException();
663 throw new NotImplementedException();
667 public Rectangle ClientRectangle {
669 return new Rectangle(0, 0, client_size.Width, client_size.Height);
673 public Size ClientSize {
679 this.SetClientSizeCore(value.Width, value.Height);
683 public String CompanyName {
685 return "Mono Project, Novell, Inc.";
689 public bool ContainsFocus {
691 throw new NotImplementedException();
695 public virtual ContextMenu ContextMenu {
697 throw new NotImplementedException();
701 throw new NotImplementedException();
706 public ControlCollection Controls {
708 return this.child_controls;
712 public bool Created {
714 throw new NotImplementedException();
719 public virtual Cursor Cursor {
721 throw new NotImplementedException();
725 throw new NotImplementedException();
729 public ControlBidingsCollection DataBindings {
731 throw new NotImplementedException();
735 public virtual Rectangle DisplayRectangle {
737 return ClientRectangle;
741 public bool Disposing {
743 throw new NotImplementedException();
747 public virtual DockStyle Dock {
748 get { return dock_style;}
751 if (dock_style == value)
755 OnDockChanged(EventArgs.Empty);
759 public bool Enabled {
769 public virtual bool Focused {
771 return this.has_focus;
775 throw new NotImplementedException();
779 public virtual Font Font {
785 if (Parent != null && Parent.Font != null) {
798 public virtual Color ForeColor {
800 if (foreground_color.IsEmpty) {
802 return parent.ForeColor;
804 return DefaultForeColor;
806 return foreground_color;
810 foreground_color=value;
815 public bool IsDisposed {
817 return this.is_disposed;
821 public bool IsHandleCreated {
823 if ((window!=null) && (window.Handle!=IntPtr.Zero)) {
841 public Control Parent {
849 parent.Controls.Remove(this);
854 if (!parent.Controls.Contains(this)) {
855 parent.Controls.Add(this);
858 XplatUI.SetParent(Handle, value.Handle);
864 public IntPtr Handle { // IWin32Window
867 if (!IsHandleCreated) {
870 return window.Handle;
874 public bool InvokeRequired { // ISynchronizeInvoke
876 if (creator_thread!=Thread.CurrentThread) {
883 public bool Visible {
885 return this.is_visible;
889 if (value!=is_visible) {
891 XplatUI.SetVisible(Handle, value);
896 public virtual string Text {
904 XplatUI.Text(Handle, text);
905 OnTextChanged (EventArgs.Empty);
912 return this.bounds.X;
916 SetBoundsCore(value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X);
922 return this.bounds.Y;
926 SetBoundsCore(bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y);
932 return this.bounds.Width;
936 SetBoundsCore(bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width);
942 return this.bounds.Height;
946 SetBoundsCore(bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height);
950 public Point Location {
952 return new Point(bounds.X, bounds.Y);
956 SetBoundsCore(value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
962 return new Size(Width, Height);
966 SetBoundsCore(bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size);
970 public int TabIndex {
980 #endregion // Public Instance Properties
982 internal Graphics DeviceContext {
983 get { return dc_mem; }
986 internal Bitmap ImageBuffer {
987 get { return bmp_mem; }
990 internal void CreateBuffers (int width, int height)
997 bmp_mem = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
998 dc_mem = Graphics.FromImage (bmp_mem);
1001 #region Protected Instance Properties
1002 protected virtual CreateParams CreateParams {
1004 CreateParams create_params = new CreateParams();
1006 create_params.Caption = Text;
1007 create_params.X = Left;
1008 create_params.Y = Top;
1009 create_params.Width = Width;
1010 create_params.Height = Height;
1012 create_params.ClassName = XplatUI.DefaultClassName;
1013 create_params.ClassStyle = 0;
1014 create_params.ExStyle = 0;
1015 create_params.Param = 0;
1018 create_params.Parent = parent.Handle;
1021 create_params.Style = (int)WindowStyles.WS_OVERLAPPED;
1024 create_params.Style |= (int)WindowStyles.WS_VISIBLE;
1027 return create_params;
1031 protected virtual ImeMode DefaultImeMode {
1033 return ImeMode.Inherit;
1037 protected virtual Size DefaultSize {
1039 return new Size(100, 23);
1043 #endregion // Protected Instance Properties
1045 #region Public Instance Methods
1046 public bool Contains(Control ctl) {
1050 while (current!=null) {
1054 current=current.parent;
1059 public void CreateControl() {
1064 for (int i=0; i<child_controls.Count; i++) {
1065 child_controls[i].CreateControl();
1070 public virtual void Refresh() {
1071 if (IsHandleCreated == true)
1072 XplatUI.RefreshWindow(window.Handle);
1075 public void SetBounds(int x, int y, int width, int height) {
1076 SetBoundsCore(x, y, width, height, BoundsSpecified.All);
1079 public void SetBounds(int x, int y, int width, int height, BoundsSpecified specified) {
1080 SetBoundsCore(x, y, width, height, specified);
1083 public void Show() {
1084 if (!IsHandleCreated) {
1085 this.CreateHandle();
1091 public object Invoke(Delegate method) { // ISynchronizeInvoke
1092 return Invoke(method, null);
1095 public object Invoke(Delegate method, object[] args) { // ISynchronizeInvoke
1096 IAsyncResult result;
1098 result=BeginInvoke(method, args);
1099 return EndInvoke(result);
1102 public IAsyncResult BeginInvoke(Delegate method) { // ISynchronizeInvoke
1103 return BeginInvoke(method, null);
1106 protected virtual AccessibleObject CreateAccessibilityInstance() {
1107 return new AccessibleObject(this);
1110 protected virtual ControlCollection CreateControlsInstance() {
1111 return new ControlCollection(this);
1114 protected void UpdateBounds() {
1120 if (!IsHandleCreated) {
1124 XplatUI.GetWindowPos(this.Handle, out x, out y, out width, out height);
1125 UpdateBounds(x, y, width, height);
1128 protected void UpdateBounds(int x, int y, int width, int height) {
1129 // UpdateBounds only seems to set our sizes and fire events but not update the GUI window to match
1131 bool resized = false;
1132 int client_x_diff = this.bounds.Width-this.client_size.Width;
1133 int client_y_diff = this.bounds.Height-this.client_size.Height;
1135 // Needed to generate required notifications
1136 if ((this.bounds.X!=x) || (this.bounds.Y!=y)) {
1140 if ((this.Bounds.Width!=width) || (this.Bounds.Height!=height)) {
1147 bounds.Height=height;
1149 // Update client rectangle as well
1150 client_size.Width=width-client_x_diff;
1151 client_size.Height=height-client_y_diff;
1154 OnLocationChanged(EventArgs.Empty);
1158 OnSizeChanged(EventArgs.Empty);
1162 protected void UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight) {
1163 this.client_size.Width=clientWidth;
1164 this.client_size.Height=clientHeight;
1166 UpdateBounds(x, y, width, height);
1169 public void Invalidate() {
1170 Invalidate(new Rectangle(0, 0, bounds.Width, bounds.Height), false);
1173 public void Invalidate(bool invalidateChildren) {
1174 Invalidate(new Rectangle(0, 0, bounds.Width, bounds.Height), invalidateChildren);
1177 public void Invalidate(System.Drawing.Rectangle rc) {
1178 Invalidate(rc, false);
1181 public void Invalidate(System.Drawing.Rectangle rc, bool invalidateChildren) {
1182 if (!IsHandleCreated || !is_visible) {
1186 XplatUI.Invalidate(Handle, rc, false);
1188 if (invalidateChildren) {
1189 for (int i=0; i<child_controls.Count; i++) child_controls[i].Invalidate();
1193 public void Invalidate(System.Drawing.Region region) {
1194 Invalidate(region, false);
1198 public void Invalidate(System.Drawing.Region region, bool invalidateChildren) {
1199 throw new NotImplementedException();
1201 // FIXME - should use the GetRegionScans function of the region to invalidate each area
1202 if (invalidateChildren) {
1203 for (int i=0; i<child_controls.Count; i++) child_controls[i].Invalidate();
1207 [MonoTODO("BeginInvoke() : Figure out a cross-platform way to handle this")]
1208 public IAsyncResult BeginInvoke(Delegate method, object[] args) { // ISynchronizeInvoke
1209 IAsyncResult result = null;
1215 public object EndInvoke(IAsyncResult async_result) { // ISynchronizeInvoke
1216 object result = null;
1221 public void PerformLayout() {
1222 PerformLayout(null, null);
1225 public void PerformLayout(Control affectedControl, string affectedProperty) {
1226 LayoutEventArgs levent = new LayoutEventArgs(affectedControl, affectedProperty);
1228 Console.WriteLine("Performing layout on control {0}", this);
1229 if (layout_suspended>0) {
1233 // Prevent us from getting messed up
1236 // Perform all Dock and Anchor calculations
1239 AnchorStyles anchor;
1242 space=this.DisplayRectangle;
1244 // Deal with docking
1245 for (int i=0; i < child_controls.Count; i++) {
1246 child=child_controls[i];
1247 switch (child.Dock) {
1248 case DockStyle.None: {
1253 case DockStyle.Left: {
1254 child.SetBounds(space.Left, space.Y, child.Width, space.Height);
1255 Console.WriteLine("DockStyle.Left: Moving control {0} to {1}:{2} {3}x{4}", this, space.Left, space.Y, child.Width, space.Height);
1256 space.X+=child.Width;
1257 space.Width-=child.Width;
1261 case DockStyle.Top: {
1262 child.SetBounds(space.Left, space.Y, space.Width, child.Height);
1263 Console.WriteLine("DockStyle.Top: Moving control {0} to {1}:{2} {3}x{4}", this, space.Left, space.Y, child.Width, space.Height);
1264 space.Y+=child.Height;
1265 space.Height-=child.Height;
1269 case DockStyle.Right: {
1270 child.SetBounds(space.Right-child.Width, space.Y, child.Width, space.Height);
1271 Console.WriteLine("DockStyle.Right: Moving control {0} to {1}:{2} {3}x{4}", this, space.Left, space.Y, child.Width, space.Height);
1272 space.Width-=child.Width;
1276 case DockStyle.Bottom: {
1277 child.SetBounds(space.Left, space.Bottom-child.Height, space.Width, child.Height);
1278 Console.WriteLine("DockStyle.Bottom: Moving control {0} to {1}:{2} {3}x{4}", this, space.Left, space.Y, child.Width, space.Height);
1279 space.Height-=child.Height;
1283 case DockStyle.Fill: {
1284 Console.WriteLine("DockStyle.Fill: Moving control {0} to {1}:{2} {3}x{4} (prev width/height: {5}x{6}", child, space.Left, space.Y, space.Width, space.Height, child.Width, child.Height);
1285 child.SetBounds(space.Left, space.Top, space.Width, space.Height);
1293 space=this.DisplayRectangle;
1295 // Deal with anchoring
1296 for (int i=0; i < child_controls.Count; i++) {
1304 child=child_controls[i];
1305 anchor=child.Anchor;
1307 left=child.Left-space.Left;
1308 top=child.Top-space.Top;
1309 width=prev_size.Width-child.Width-child.Left;
1310 height=prev_size.Height-child.Height-child.Top;
1312 diff_width=space.Width-prev_size.Width;
1313 diff_height=space.Height-prev_size.Height;
1315 prev_size.Width=space.Width;
1316 prev_size.Height=space.Height;
1318 // If the control is docked we don't need to do anything
1319 if (child.Dock != DockStyle.None) {
1323 if ((anchor & AnchorStyles.Left) !=0 ) {
1324 if ((anchor & AnchorStyles.Right) != 0) {
1325 // Anchoring to left and right
1326 width=width+diff_width;
1330 } else if ((anchor & AnchorStyles.Right) != 0) {
1336 if ((anchor & AnchorStyles.Top) !=0 ) {
1337 if ((anchor & AnchorStyles.Bottom) != 0) {
1338 height+=diff_height;
1342 } else if ((anchor & AnchorStyles.Bottom) != 0) {
1357 child.SetBounds(left, top, width, height);
1360 // Let everyone know
1364 // Need to make sure we decremend layout_suspended
1370 public void ResumeLayout()
1372 ResumeLayout (true);
1375 public void ResumeLayout(bool peformLayout)
1379 if (layout_suspended > 0 || peformLayout == false)
1386 public void SuspendLayout()
1392 protected virtual void WndProc(ref Message m) {
1393 EventArgs e = new EventArgs();
1396 Console.WriteLine("Received message {0}", m);
1399 switch((Msg)m.Msg) {
1402 case Msg.WM_LBUTTONDBLCLK: throw new NotImplementedException(); break;
1404 case Msg.WM_RBUTTONDOWN: throw new NotImplementedException(); break;
1405 case Msg.WM_RBUTTONUP: throw new NotImplementedException(); break;
1406 case Msg.WM_RBUTTONDBLCLK: throw new NotImplementedException(); break;
1408 case Msg.WM_MOUSEHOVER: throw new NotImplementedException(); break;
1409 case Msg.WM_MOUSELEAVE: throw new NotImplementedException(); break;
1412 // Keyboard handling
1413 case Msg.WM_CHAR: throw new NotImplementedException(); break;
1414 case Msg.WM_KEYDOWN: throw new NotImplementedException(); break;
1415 case Msg.WM_KEYUP: throw new NotImplementedException(); break;
1417 // Window management
1418 case Msg.WM_WINDOWPOSCHANGED: {
1424 case Msg.WM_PAINT: {
1426 PaintEventArgs paint_event;
1428 paint_event = XplatUI.PaintEventStart(Handle);
1429 OnPaint(paint_event);
1430 XplatUI.PaintEventEnd(Handle);
1435 case Msg.WM_ERASEBKGND:{
1436 if (GetStyle (ControlStyles.UserPaint)){
1437 PaintEventArgs eraseEventArgs = new PaintEventArgs (Graphics.FromHdc (m.WParam), new Rectangle (new Point (0,0),Size));
1438 OnPaintBackground (eraseEventArgs);
1439 m.Result = (IntPtr)1;
1442 m.Result = (IntPtr)0;
1449 case Msg.WM_LBUTTONUP: {
1452 OnMouseUp (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1454 LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1459 case Msg.WM_LBUTTONDOWN: {
1462 OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1463 clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1469 case Msg.WM_MOUSEWHEEL: {
1472 OnMouseWheel (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1473 clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1474 HighOrder(m.WParam.ToInt32())));
1479 case Msg.WM_MOUSEMOVE: {
1482 OnMouseMove (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1484 LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1490 if (GetStyle(ControlStyles.ResizeRedraw)) {
1494 // Call UpdateBounds, the GUI already has the sizes
1495 UpdateBounds (bounds.X, bounds.Y, LowOrder ((int) m.LParam.ToInt32 ()),
1496 HighOrder ((int) m.LParam.ToInt32 ()));
1502 case Msg.WM_KEYDOWN: {
1504 if (!ProcessKeyEventArgs (ref m))
1510 case Msg.WM_KEYUP: {
1512 if (!ProcessKeyEventArgs (ref m))
1520 case Msg.WM_WINDOWPOSCHANGED: throw new NotImplementedException(); break;
1521 case Msg.WM_SYSCOLORCHANGE: throw new NotImplementedException(); break;
1533 #endregion // Public Instance Methods
1536 #region // Protected Instance Methods
1537 protected virtual void CreateHandle() {
1539 throw new ObjectDisposedException(Name);
1542 if (IsHandleCreated) {
1547 window = new ControlNativeWindow(this);
1548 window.CreateHandle(CreateParams);
1551 if (window.Handle!=IntPtr.Zero) {
1552 if (!controls.Contains(window.Handle)) {
1553 controls.Add(window.Handle, this);
1556 creator_thread = Thread.CurrentThread;
1558 OnHandleCreated(EventArgs.Empty);
1562 protected virtual void DefWndProc(ref Message m) {
1563 window.DefWndProc(ref m);
1566 protected virtual void DestroyHandle() {
1567 if (IsHandleCreated) {
1568 if (Handle != IntPtr.Zero) {
1569 controls.Remove(Handle);
1572 if (window != null) {
1573 window.DestroyHandle();
1578 protected virtual bool ProcessKeyEventArgs (ref Message msg)
1580 KeyEventArgs key_event;
1583 case (int)Msg.WM_KEYDOWN: {
1584 key_event = new KeyEventArgs ((Keys)msg.WParam.ToInt32 ());
1585 OnKeyDown (key_event);
1586 return key_event.Handled;
1588 case (int)Msg.WM_KEYUP: {
1589 key_event = new KeyEventArgs ((Keys)msg.WParam.ToInt32 ());
1590 OnKeyUp (key_event);
1591 return key_event.Handled;
1601 protected virtual bool IsInputKey (Keys keyData)
1606 protected virtual bool ProcessDialogKey (Keys keyData)
1609 return Parent.ProcessDialogKey (keyData);
1614 protected bool GetStyle(ControlStyles flag) {
1615 return (control_style & flag) != 0;
1618 protected virtual bool ProcessDialogChar(char charCode) {
1619 throw new NotImplementedException();
1622 protected virtual bool ProcessMnemonic(char charCode) {
1623 throw new NotImplementedException();
1626 protected void RecreateHandle() {
1627 IEnumerator child = child_controls.GetEnumerator();
1629 if (IsHandleCreated) {
1635 while (child.MoveNext()) {
1636 ((Control)child.Current).RecreateHandle();
1641 protected virtual void ScaleCore(float dx, float dy) {
1642 throw new NotImplementedException();
1645 protected virtual void Select(bool directed, bool forward) {
1646 throw new NotImplementedException();
1649 protected virtual void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
1650 // SetBoundsCore updates the Win32 control itself. UpdateBounds updates the controls variables and fires events, I'm guessing - pdb
1651 if ((specified & BoundsSpecified.X) != BoundsSpecified.X) {
1655 if ((specified & BoundsSpecified.Y) != BoundsSpecified.Y) {
1659 if ((specified & BoundsSpecified.Width)!= BoundsSpecified.Width) {
1663 if ((specified & BoundsSpecified.Height) != BoundsSpecified.Height) {
1667 if (IsHandleCreated) {
1668 XplatUI.MoveWindow(Handle, x, y, width, height);
1671 UpdateBounds(x, y, width, height);
1674 protected virtual void SetClientSizeCore(int x, int y) {
1675 // Calculate the actual window size from the client size (it usually stays the same or grows)
1676 Rectangle ClientRect;
1677 Rectangle WindowRect;
1680 ClientRect = new Rectangle(0, 0, x, y);
1681 cp = this.CreateParams;
1683 if (XplatUI.CalculateWindowRect(Handle, ref ClientRect, cp.Style, false, out WindowRect)==false) {
1687 this.client_size = new Size(x, y);
1688 SetBoundsCore(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
1691 protected void SetStyle(ControlStyles flag, bool value) {
1693 control_style |= flag;
1695 control_style &= ~flag;
1699 #endregion // Public Instance Methods
1701 #region Private Instance Methods
1702 #endregion // Private Instance Methods
1705 #region Private Instance Methods
1706 internal virtual void DoDefaultAction() {
1707 // Only here to be overriden by our actual controls; this is needed by the accessibility class
1709 #endregion // Private Instance Methods
1712 #region OnXXX methods
1713 protected virtual void OnBackColorChanged(EventArgs e) {
1714 if (BackColorChanged!=null) BackColorChanged(this, e);
1715 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentBackColorChanged(e);
1718 protected virtual void OnBackgroundImageChanged(EventArgs e) {
1719 if (BackgroundImageChanged!=null) BackgroundImageChanged(this, e);
1720 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentBackgroundImageChanged(e);
1723 protected virtual void OnBindingContextChanged(EventArgs e) {
1724 if (BindingContextChanged!=null) BindingContextChanged(this, e);
1725 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentBindingContextChanged(e);
1728 protected virtual void OnCausesValidationChanged(EventArgs e) {
1729 if (CausesValidationChanged!=null) CausesValidationChanged(this, e);
1732 protected virtual void OnChangeUICues(UICuesEventArgs e) {
1733 if (CausesValidationChanged!=null) CausesValidationChanged(this, e);
1736 protected virtual void OnClick(EventArgs e) {
1737 if (Click!=null) Click(this, e);
1740 protected virtual void OnContextMenuChanged(EventArgs e) {
1741 if (ContextMenuChanged!=null) ContextMenuChanged(this, e);
1744 protected virtual void OnControlAdded(ControlEventArgs e) {
1745 if (ControlAdded!=null) ControlAdded(this, e);
1748 protected virtual void OnControlRemoved(ControlEventArgs e) {
1749 if (ControlRemoved!=null) ControlRemoved(this, e);
1752 protected virtual void OnCreateControl() {
1755 protected virtual void OnCursorChanged(EventArgs e) {
1756 if (CursorChanged!=null) CursorChanged(this, e);
1759 protected virtual void OnDockChanged(EventArgs e) {
1760 if (DockChanged!=null) DockChanged(this, e);
1763 protected virtual void OnDoubleClick(EventArgs e) {
1764 if (DoubleClick!=null) DoubleClick(this, e);
1767 protected virtual void OnDragDrop(DragEventArgs drgevent) {
1768 if (DragDrop!=null) DragDrop(this, drgevent);
1771 protected virtual void OnDragEnter(DragEventArgs drgevent) {
1772 if (DragEnter!=null) DragEnter(this, drgevent);
1775 protected virtual void OnDragLeave(EventArgs e) {
1776 if (DragLeave!=null) DragLeave(this, e);
1779 protected virtual void OnDragOver(DragEventArgs drgevent) {
1780 if (DragOver!=null) DragOver(this, drgevent);
1783 protected virtual void OnEnabledChanged(EventArgs e) {
1784 if (EnabledChanged!=null) EnabledChanged(this, e);
1785 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentEnabledChanged(e);
1788 protected virtual void OnEnter(EventArgs e) {
1789 if (Enter!=null) Enter(this, e);
1792 protected virtual void OnFontChanged(EventArgs e) {
1793 if (FontChanged!=null) FontChanged(this, e);
1796 protected virtual void OnForeColorChanged(EventArgs e) {
1797 if (ForeColorChanged!=null) ForeColorChanged(this, e);
1798 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentForeColorChanged(e);
1801 protected virtual void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) {
1802 if (GiveFeedback!=null) GiveFeedback(this, gfbevent);
1805 protected virtual void OnGotFocus(EventArgs e) {
1806 if (GotFocus!=null) GotFocus(this, e);
1809 protected virtual void OnHandleCreated(EventArgs e) {
1810 if (HandleCreated!=null) HandleCreated(this, e);
1813 protected virtual void OnHandleDestroyed(EventArgs e) {
1814 if (HandleDestroyed!=null) HandleDestroyed(this, e);
1817 protected virtual void OnHelpRequested(HelpEventArgs hevent) {
1818 if (HelpRequested!=null) HelpRequested(this, hevent);
1821 protected virtual void OnImeModeChanged(EventArgs e) {
1822 if (ImeModeChanged!=null) ImeModeChanged(this, e);
1825 protected virtual void OnInvalidated(InvalidateEventArgs e) {
1826 if (Invalidated!=null) Invalidated(this, e);
1830 protected virtual void OnKeyDown(KeyEventArgs e) {
1831 if (KeyDown!=null) KeyDown(this, e);
1834 protected virtual void OnKeyUp(KeyEventArgs e) {
1835 if (KeyUp!=null) KeyUp(this, e);
1838 protected virtual void OnLayout(LayoutEventArgs levent) {
1839 if (Layout!=null) Layout(this, levent);
1842 protected virtual void OnLeave(EventArgs e) {
1843 if (Leave!=null) Leave(this, e);
1846 protected virtual void OnLocationChanged(EventArgs e) {
1847 if (LocationChanged!=null) LocationChanged(this, e);
1850 protected virtual void OnLostFocus(EventArgs e) {
1851 if (LostFocus!=null) LostFocus(this, e);
1854 protected virtual void OnMouseDown(MouseEventArgs e) {
1855 if (MouseDown!=null) MouseDown(this, e);
1858 protected virtual void OnMouseEnter(EventArgs e) {
1859 if (MouseEnter!=null) MouseEnter(this, e);
1862 protected virtual void OnMouseHover(EventArgs e) {
1863 if (MouseHover!=null) MouseHover(this, e);
1866 protected virtual void OnMouseLeave(EventArgs e) {
1867 if (MouseLeave!=null) MouseLeave(this, e);
1870 protected virtual void OnMouseMove(MouseEventArgs e) {
1871 if (MouseMove!=null) MouseMove(this, e);
1874 protected virtual void OnMouseUp(MouseEventArgs e) {
1875 if (MouseUp!=null) MouseUp(this, e);
1878 protected virtual void OnMouseWheel(MouseEventArgs e) {
1879 if (MouseWheel!=null) MouseWheel(this, e);
1882 protected virtual void OnMove(EventArgs e) {
1883 if (Move!=null) Move(this, e);
1886 protected virtual void OnNotifyMessage(Message m) {
1890 protected virtual void OnPaint(PaintEventArgs e) {
1891 if (Paint!=null) Paint(this, e);
1894 protected virtual void OnPaintBackground(PaintEventArgs pevent) {
1898 protected virtual void OnParentBackColorChanged(EventArgs e) {
1899 if (background_color.IsEmpty && background_image==null) {
1901 OnBackColorChanged(e);
1905 protected virtual void OnParentBackgroundImageChanged(EventArgs e) {
1906 if (background_color.IsEmpty && background_image==null) {
1908 OnBackgroundImageChanged(e);
1912 protected virtual void OnParentBindingContextChanged(EventArgs e) {
1913 if (binding_context==null) {
1914 binding_context=Parent.binding_context;
1915 OnBindingContextChanged(e);
1919 protected virtual void OnParentChanged(EventArgs e) {
1920 if (ParentChanged!=null) ParentChanged(this, e);
1923 protected virtual void OnParentEnabledChanged(EventArgs e) {
1924 if ((is_enabled && !Parent.is_enabled) || (!is_enabled && Parent.is_enabled)) {
1927 EnabledChanged(this, e);
1931 protected virtual void OnParentFontChanged(EventArgs e) {
1938 protected virtual void OnParentForeColorChanged(EventArgs e) {
1939 if (foreground_color.IsEmpty) {
1941 OnForeColorChanged(e);
1945 protected virtual void OnParentRightToLeftChanged(EventArgs e) {
1946 if (right_to_left==RightToLeft.Inherit) {
1948 OnRightToLeftChanged(e);
1952 protected virtual void OnParentVisibleChanged(EventArgs e) {
1953 if (is_visible!=Parent.is_visible) {
1956 OnVisibleChanged(e);
1960 protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e) {
1961 if (QueryContinueDrag!=null) QueryContinueDrag(this, e);
1964 protected virtual void OnResize(EventArgs e) {
1965 if (Resize!=null) Resize(this, e);
1967 PerformLayout(this, "bounds");
1969 // Do we need to let our parent regenerate it's layout thing since we resized?
1972 protected virtual void OnRightToLeftChanged(EventArgs e) {
1973 if (RightToLeftChanged!=null) RightToLeftChanged(this, e);
1974 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentRightToLeftChanged(e);
1977 protected virtual void OnSizeChanged(EventArgs e) {
1979 if (SizeChanged!=null) SizeChanged(this, e);
1982 protected virtual void OnStyleChanged(EventArgs e) {
1983 if (StyleChanged!=null) StyleChanged(this, e);
1986 protected virtual void OnSystemColorsChanged(EventArgs e) {
1987 if (SystemColorsChanged!=null) SystemColorsChanged(this, e);
1990 protected virtual void OnTabIndexChanged(EventArgs e) {
1991 if (TabIndexChanged!=null) TabIndexChanged(this, e);
1994 protected virtual void OnTabStopChanged(EventArgs e) {
1995 if (TabStopChanged!=null) TabStopChanged(this, e);
1998 protected virtual void OnTextChanged(EventArgs e) {
1999 if (TextChanged!=null) TextChanged(this, e);
2002 protected virtual void OnValidated(EventArgs e) {
2003 if (Validated!=null) Validated(this, e);
2006 protected virtual void OnValidating(System.ComponentModel.CancelEventArgs e) {
2007 if (Validating!=null) Validating(this, e);
2010 protected virtual void OnVisibleChanged(EventArgs e) {
2011 if (VisibleChanged!=null) VisibleChanged(this, e);
2013 #endregion // OnXXX methods
2016 public event EventHandler BackColorChanged;
2017 public event EventHandler BackgroundImageChanged;
2018 public event EventHandler BindingContextChanged;
2019 public event EventHandler CausesValidationChanged;
2020 public event UICuesEventHandler ChangeUICues;
2021 public event EventHandler Click;
2022 public event EventHandler ContextMenuChanged;
2023 public event ControlEventHandler ControlAdded;
2024 public event ControlEventHandler ControlRemoved;
2025 public event EventHandler CursorChanged;
2026 public event EventHandler DockChanged;
2027 public event EventHandler DoubleClick;
2028 public event DragEventHandler DragDrop;
2029 public event DragEventHandler DragEnter;
2030 public event EventHandler DragLeave;
2031 public event DragEventHandler DragOver;
2032 public event EventHandler EnabledChanged;
2033 public event EventHandler Enter;
2034 public event EventHandler FontChanged;
2035 public event EventHandler ForeColorChanged;
2036 public event GiveFeedbackEventHandler GiveFeedback;
2037 public event EventHandler GotFocus;
2038 public event EventHandler HandleCreated;
2039 public event EventHandler HandleDestroyed;
2040 public event HelpEventHandler HelpRequested;
2041 public event EventHandler ImeModeChanged;
2042 public event InvalidateEventHandler Invalidated;
2043 public event KeyEventHandler KeyDown;
2044 public event KeyPressEventHandler KeyPress;
2045 public event KeyEventHandler KeyUp;
2046 public event LayoutEventHandler Layout;
2047 public event EventHandler Leave;
2048 public event EventHandler LocationChanged;
2049 public event EventHandler LostFocus;
2050 public event MouseEventHandler MouseDown;
2051 public event EventHandler MouseEnter;
2052 public event EventHandler MouseHover;
2053 public event EventHandler MouseLeave;
2054 public event MouseEventHandler MouseMove;
2055 public event MouseEventHandler MouseUp;
2056 public event MouseEventHandler MouseWheel;
2057 public event EventHandler Move;
2058 public event PaintEventHandler Paint;
2059 public event EventHandler ParentChanged;
2060 public event QueryAccessibilityHelpEventHandler QueryAccessibilityHelp;
2061 public event QueryContinueDragEventHandler QueryContinueDrag;
2062 public event EventHandler Resize;
2063 public event EventHandler RightToLeftChanged;
2064 public event EventHandler SizeChanged;
2065 public event EventHandler StyleChanged;
2066 public event EventHandler SystemColorsChanged;
2067 public event EventHandler TabIndexChanged;
2068 public event EventHandler TabStopChanged;
2069 public event EventHandler TextChanged;
2070 public event EventHandler Validated;
2071 public event CancelEventHandler Validating;
2072 public event EventHandler VisibleChanged;
2073 #endregion // Events
2075 #region Private Methods
2076 internal static int LowOrder (int param)
2078 return (param & 0xffff);
2081 internal static int HighOrder (int param)
2083 return (param >> 16);
2086 internal static MouseButtons FromParamToMouseButtons (int param)
2088 MouseButtons buttons = MouseButtons.None;
2090 if ((param & (int) MsgButtons.MK_LBUTTON) != 0)
2091 buttons |= MouseButtons.Left;
2093 if ((param & (int) MsgButtons.MK_MBUTTON) != 0)
2094 buttons |= MouseButtons.Middle;
2096 if ((param & (int) MsgButtons.MK_RBUTTON) != 0)
2097 buttons |= MouseButtons.Right;