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.27 2004/08/13 19:00:15 jordi
36 // implements PointToClient (ScreenToClient)
38 // Revision 1.26 2004/08/13 18:52:07 pbartok
39 // - Added Dispose() and destructor
40 // - Fixed resizing and bounds calculation
42 // - Added memory savings for invisible windows
44 // Revision 1.25 2004/08/12 19:31:19 pbartok
45 // - Fixed Anchoring bugs
47 // Revision 1.24 2004/08/12 16:10:42 jackson
48 // Add missing properties
50 // Revision 1.23 2004/08/11 22:20:59 pbartok
53 // Revision 1.22 2004/08/11 19:19:44 pbartok
54 // - We had SetWindowPos and MoveWindow to set window positions and size,
55 // removed MoveWindow. We have GetWindowPos, so it made sense to keep
56 // SetWindowPos as matching counterpart
57 // - Added some X11 sanity checking
59 // Revision 1.21 2004/08/11 18:59:45 pbartok
60 // - Major cleanup of my SetBounds/SetBoundsCore/UpdateBounds mess
61 // (It seems that SetBounds is just a front for SetBoundsCore and
62 // SetBoundsCore updates the underlying window system and UpdateBounds is
63 // responsible for updating the variables associated with the Control and
64 // sending the events)
65 // - Major cleanup of Size handling; we now have two sizes, client_size and
66 // bounds. Bounds defines the window with decorations, client_size without
69 // Revision 1.20 2004/08/11 15:13:32 pbartok
70 // - Now properly reparents windows
72 // Revision 1.19 2004/08/11 14:37:11 pbartok
75 // Revision 1.18 2004/08/11 13:47:22 pbartok
76 // - Rewrote the collection stuff. Might not be as fast now, not keeping
77 // the number of children around and accessible directly, but it's more
80 // Revision 1.17 2004/08/10 18:32:10 jordi
81 // throw ontextchange event
83 // Revision 1.16 2004/08/10 17:43:04 pbartok
84 // - Added more to the still unfinished Dock/Anchor layout code
86 // Revision 1.15 2004/08/10 15:08:05 jackson
87 // Control will now handle the buffering code, so each control does not have to implement this.
89 // Revision 1.14 2004/08/09 22:11:25 pbartok
90 // - Added incomplete dock layout code
91 // - Added support for mouse wheel
93 // Revision 1.13 2004/08/09 17:25:56 jackson
94 // Use new color names
96 // Revision 1.12 2004/08/09 15:54:51 jackson
97 // Get default properties from the theme.
99 // Revision 1.11 2004/08/06 21:30:56 pbartok
100 // - Fixed recursive loop when resizing
101 // - Improved/fixed redrawing on expose messages
103 // Revision 1.10 2004/08/06 15:53:39 jordi
104 // X11 keyboard navigation
106 // Revision 1.9 2004/08/04 21:14:26 pbartok
107 // - Fixed Invalidation bug (calculated wrong client area)
108 // - Added ClientSize setter
110 // Revision 1.8 2004/08/04 20:11:24 pbartok
111 // - Added Invalidate handling
113 // Revision 1.7 2004/07/27 10:38:17 jordi
114 // changes to be able to run winforms samples
116 // Revision 1.6 2004/07/19 19:09:42 jordi
117 // label control re-written: added missing functionlity, events, and properties
119 // Revision 1.5 2004/07/19 16:49:23 jordi
120 // fixes SetBounds logic
122 // Revision 1.4 2004/07/19 07:29:35 jordi
123 // Call RefreshWindow only if the window has created
125 // Revision 1.3 2004/07/15 17:03:35 jordi
126 // added basic mouse handeling events
128 // Revision 1.2 2004/07/13 15:31:45 jordi
129 // commit: new properties and fixes form size problems
131 // Revision 1.1 2004/07/09 05:21:25 pbartok
132 // - Initial check-in
139 using System.Drawing;
140 using System.ComponentModel;
141 using System.Collections;
142 using System.Diagnostics;
143 using System.Threading;
144 using System.Runtime.InteropServices;
146 namespace System.Windows.Forms
148 public class Control : Component, ISynchronizeInvoke, IWin32Window
150 #region Local Variables
153 internal Rectangle bounds; // bounding rectangle for control (client area + decorations)
154 internal object creator_thread; // thread that created the control
155 internal ControlNativeWindow window; // object for native window handle
156 internal string name; // for object naming
159 internal bool has_focus; // true if control has focus
160 internal bool is_visible; // true if control is visible
161 internal bool is_enabled; // true if control is enabled (usable/not grayed out)
162 internal int tab_index; // position in tab order of siblings
163 internal bool tab_stop = true;
164 internal bool is_disposed; // has the window already been disposed?
165 internal Size client_size; // size of the client area (window excluding decorations)
166 internal ControlStyles control_style; // rather win32-specific, style bits for control
167 internal ImeMode ime_mode = ImeMode.Inherit;
170 internal Color foreground_color; // foreground color for control
171 internal Color background_color; // background color for control
172 internal Image background_image; // background image for control
173 internal Font font; // font for control
174 internal string text; // window/title text for control
177 internal AnchorStyles anchor_style; // anchoring requirements for our control
178 internal DockStyle dock_style; // docking requirements for our control (supercedes anchoring)
179 internal int prev_width; // previous width of the control; required for anchoring
180 internal int prev_height; // previous height of our control; required for anchoring
181 internal Size prev_size;
183 // to be categorized...
184 static internal Hashtable controls; // All of the applications controls, in a flat list
185 internal ControlCollection child_controls; // our children
186 internal Control parent; // our parent control
187 internal AccessibleObject accessibility_object; // object that contains accessibility information about our control
188 internal BindingContext binding_context; // TODO
189 internal RightToLeft right_to_left; // drawing direction for control
190 internal int layout_suspended;
192 private Graphics dc_mem; // Graphics context for double buffering
193 private Bitmap bmp_mem; // Bitmap for double buffering control
195 #endregion // Local Variables
197 #region Private Classes
198 // This helper class allows us to dispatch messages to Control.WndProc
199 internal class ControlNativeWindow : NativeWindow {
200 private Control control;
202 public ControlNativeWindow(Control control) : base() {
203 this.control=control;
206 protected override void WndProc(ref Message m) {
207 control.WndProc(ref m);
212 #region Public Classes
213 public class ControlCollection : IList, ICollection, ICloneable, IEnumerable {
214 #region ControlCollection Local Variables
215 private ArrayList list;
216 private Control owner;
217 #endregion // ControlCollection Local Variables
219 #region ControlCollection Public Constructor
220 public ControlCollection(Control owner) {
222 this.list=new ArrayList();
226 #region ControlCollection Public Instance Properties
233 public bool IsReadOnly {
235 return list.IsReadOnly;
239 public virtual Control this[int index] {
241 if (index < 0 || index >= list.Count) {
242 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
244 return (Control)list[index];
247 #endregion // ControlCollection Public Instance Properties
249 #region ControlCollection Private Instance Methods
250 public virtual void Add(Control value) {
251 for (int i=0; i<list.Count; i++) {
252 if (list[i]==value) {
253 // Do we need to do anything here?
261 public virtual void AddRange(Control[] controls) {
262 for (int i=0; i<controls.Length; i++) {
267 public virtual void Clear() {
268 owner.SuspendLayout();
270 owner.ResumeLayout();
273 public virtual bool Contains(Control value) {
274 return list.Contains(value);
277 public void CopyTo(Array array, int index) {
278 list.CopyTo(array, index);
281 public override bool Equals(object other) {
282 if (other is ControlCollection && (((ControlCollection)other).owner==this.owner)) {
289 public int GetChildIndex(Control child) {
290 return GetChildIndex(child, false);
293 public int GetChildIndex(Control child, bool throwException) {
296 index=list.IndexOf(child);
298 if (index==-1 && throwException) {
299 throw new ArgumentException("Not a child control", "child");
304 public IEnumerator GetEnumerator() {
305 return list.GetEnumerator();
308 public override int GetHashCode() {
309 return base.GetHashCode();
312 public int IndexOf(Control control) {
313 return list.IndexOf(control);
316 public virtual void Remove(Control value) {
320 public void RemoveAt(int index) {
321 if (index<0 || index>=list.Count) {
322 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
325 list.RemoveAt(index);
328 public void SetChildIndex(Control child, int newIndex) {
331 old_index=list.IndexOf(child);
333 throw new ArgumentException("Not a child control", "child");
336 if (old_index==newIndex) {
342 if (newIndex>list.Count) {
345 list.Insert(newIndex, child);
348 #endregion // ControlCollection Private Instance Methods
350 #region ControlCollection Interface Properties
351 object IList.this[int index] {
353 if (index<0 || index>=list.Count) {
354 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
360 if (!(value is Control)) {
361 throw new ArgumentException("Object of type Control required", "value");
364 list[index]=(Control)value;
368 bool IList.IsFixedSize {
374 bool IList.IsReadOnly {
376 return list.IsReadOnly;
380 bool ICollection.IsSynchronized {
382 return list.IsSynchronized;
386 object ICollection.SyncRoot {
388 return list.SyncRoot;
391 #endregion // ControlCollection Interface Properties
393 #region ControlCollection Interface Methods
394 int IList.Add(object value) {
396 throw new ArgumentNullException("value", "Cannot add null controls");
399 if (!(value is Control)) {
400 throw new ArgumentException("Object of type Control required", "value");
403 return list.Add(value);
406 bool IList.Contains(object value) {
407 if (!(value is Control)) {
408 throw new ArgumentException("Object of type Control required", "value");
411 return this.Contains((Control) value);
414 int IList.IndexOf(object value) {
415 if (!(value is Control)) {
416 throw new ArgumentException("Object of type Control required", "value");
419 return this.IndexOf((Control) value);
422 void IList.Insert(int index, object value) {
423 if (!(value is Control)) {
424 throw new ArgumentException("Object of type Control required", "value");
426 list.Insert(index, value);
429 void IList.Remove(object value) {
430 if (!(value is Control)) {
431 throw new ArgumentException("Object of type Control required", "value");
436 void ICollection.CopyTo(Array array, int index) {
438 list.CopyTo(array, index);
442 Object ICloneable.Clone() {
443 ControlCollection clone = new ControlCollection(this.owner);
444 clone.list=(ArrayList)list.Clone(); // FIXME: Do we need this?
447 #endregion // ControlCollection Interface Methods
449 #endregion // ControlCollection Class
451 #region Public Constructors
453 creator_thread = Thread.CurrentThread;
454 controls = new Hashtable();
455 child_controls = CreateControlsInstance();
456 bounds = new Rectangle(0, 0, DefaultSize.Width, DefaultSize.Height);
457 client_size = new Size(DefaultSize.Width, DefaultSize.Height);
458 prev_size = Size.Empty;
464 layout_suspended = 0;
467 background_image = null;
470 public Control(Control parent, string text) : this() {
475 public Control(Control parent, string text, int left, int top, int width, int height) : this() {
480 bounds.Height=height;
481 SetBoundsCore(left, top, width, height, BoundsSpecified.All);
485 public Control(string text) : this() {
489 public Control(string text, int left, int top, int width, int height) : this() {
493 bounds.Height=height;
494 SetBoundsCore(left, top, width, height, BoundsSpecified.All);
502 public void Dispose() {
504 GC.SuppressFinalize(this);
507 protected override void Dispose(bool disposing) {
521 #endregion // Public Constructors
523 #region Public Static Properties
524 public static Color DefaultBackColor {
526 return ThemeEngine.Current.DefaultControlBackColor;
530 public static Font DefaultFont {
532 return ThemeEngine.Current.DefaultFont;
536 public static Color DefaultForeColor {
538 return ThemeEngine.Current.DefaultControlForeColor;
542 public static Keys ModifierKeys {
544 return XplatUI.State.ModifierKeys;
548 public static MouseButtons MouseButtons {
550 return XplatUI.State.MouseButtons;
554 public static Point MousePosition {
557 XplatUI.GetCursorPos (IntPtr.Zero, ref x, ref y);
558 return new Point (x, y);
561 #endregion // Public Static Properties
563 #region Public Instance Properties
564 public AccessibleObject AccessibilityObject {
566 if (accessibility_object==null) {
567 accessibility_object=CreateAccessibilityInstance();
569 return accessibility_object;
573 public string AccessibleDefaultActionDescription {
575 return AccessibilityObject.default_action;
579 AccessibilityObject.default_action=value;
583 public string AccessibleDescription {
585 return AccessibilityObject.description;
589 AccessibilityObject.description=value;
593 public string AccessibleName {
595 return AccessibilityObject.Name;
599 AccessibilityObject.Name=value;
603 public AccessibleRole AccessibleRole {
605 return AccessibilityObject.role;
609 AccessibilityObject.role=value;
613 public virtual bool AllowDrop {
615 return XplatUI.State.DropTarget;
619 XplatUI.State.DropTarget=value;
623 public virtual AnchorStyles Anchor {
633 public virtual Color BackColor {
635 if (background_color.IsEmpty) {
637 return parent.BackColor;
639 return DefaultBackColor;
641 return background_color;
645 background_color=value;
650 public virtual Image BackgroundImage {
652 return background_image;
656 if (background_image!=value) {
657 background_image=value;
658 OnBackgroundImageChanged(EventArgs.Empty);
663 public virtual BindingContext BindingContext {
665 throw new NotImplementedException();
669 throw new NotImplementedException();
676 return bounds.Y+bounds.Height;
680 public Rectangle Bounds {
686 SetBoundsCore(value.Left, value.Top, value.Width, value.Height, BoundsSpecified.All);
690 public bool CanFocus {
692 throw new NotImplementedException();
696 public bool CanSelect {
698 throw new NotImplementedException();
702 public bool Capture {
704 throw new NotImplementedException();
708 throw new NotImplementedException();
712 public bool CausesValidation {
714 throw new NotImplementedException();
718 throw new NotImplementedException();
722 public Rectangle ClientRectangle {
724 return new Rectangle(0, 0, client_size.Width, client_size.Height);
728 public Size ClientSize {
734 this.SetClientSizeCore(value.Width, value.Height);
738 public String CompanyName {
740 return "Mono Project, Novell, Inc.";
744 public bool ContainsFocus {
746 throw new NotImplementedException();
750 public virtual ContextMenu ContextMenu {
752 throw new NotImplementedException();
756 throw new NotImplementedException();
761 public ControlCollection Controls {
763 return this.child_controls;
767 public bool Created {
769 throw new NotImplementedException();
774 public virtual Cursor Cursor {
776 throw new NotImplementedException();
780 throw new NotImplementedException();
784 public ControlBidingsCollection DataBindings {
786 throw new NotImplementedException();
790 public virtual Rectangle DisplayRectangle {
792 return ClientRectangle;
796 public bool Disposing {
798 throw new NotImplementedException();
802 public virtual DockStyle Dock {
803 get { return dock_style;}
806 if (dock_style == value)
810 OnDockChanged(EventArgs.Empty);
814 public bool Enabled {
824 public virtual bool Focused {
826 return this.has_focus;
830 public virtual Font Font {
836 if (Parent != null && Parent.Font != null) {
849 public virtual Color ForeColor {
851 if (foreground_color.IsEmpty) {
853 return parent.ForeColor;
855 return DefaultForeColor;
857 return foreground_color;
861 foreground_color=value;
866 public bool IsDisposed {
868 return this.is_disposed;
872 public bool IsHandleCreated {
874 if ((window!=null) && (window.Handle!=IntPtr.Zero)) {
892 public Control Parent {
900 parent.Controls.Remove(this);
905 if (!parent.Controls.Contains(this)) {
906 parent.Controls.Add(this);
909 XplatUI.SetParent(Handle, value.Handle);
915 public IntPtr Handle { // IWin32Window
918 if (!IsHandleCreated) {
921 return window.Handle;
925 public bool InvokeRequired { // ISynchronizeInvoke
927 if (creator_thread!=Thread.CurrentThread) {
934 public bool Visible {
936 return this.is_visible;
940 if (value!=is_visible) {
942 XplatUI.SetVisible(Handle, value);
947 public virtual string Text {
955 XplatUI.Text(Handle, text);
956 OnTextChanged (EventArgs.Empty);
963 return this.bounds.X;
967 SetBoundsCore(value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X);
973 return this.bounds.Y;
977 SetBoundsCore(bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y);
983 return this.bounds.Width;
987 SetBoundsCore(bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width);
993 return this.bounds.Height;
997 SetBoundsCore(bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height);
1001 public Point Location {
1003 return new Point(bounds.X, bounds.Y);
1007 SetBoundsCore(value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
1013 return new Size(Width, Height);
1017 SetBoundsCore(bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size);
1021 public ImeMode ImeMode {
1022 get { return ime_mode; }
1023 set { ime_mode = value; }
1026 public bool TabStop {
1027 get { return tab_stop; }
1028 set { tab_stop = value; }
1031 public int TabIndex {
1041 #endregion // Public Instance Properties
1043 internal Graphics DeviceContext {
1046 CreateBuffers(this.Width, this.Height);
1052 internal Bitmap ImageBuffer {
1054 if (bmp_mem==null) {
1055 CreateBuffers(this.Width, this.Height);
1061 internal void CreateBuffers (int width, int height)
1065 if (bmp_mem != null)
1068 bmp_mem = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
1069 dc_mem = Graphics.FromImage (bmp_mem);
1072 #region Protected Instance Properties
1073 protected virtual CreateParams CreateParams {
1075 CreateParams create_params = new CreateParams();
1077 create_params.Caption = Text;
1078 create_params.X = Left;
1079 create_params.Y = Top;
1080 create_params.Width = Width;
1081 create_params.Height = Height;
1083 create_params.ClassName = XplatUI.DefaultClassName;
1084 create_params.ClassStyle = 0;
1085 create_params.ExStyle = 0;
1086 create_params.Param = 0;
1089 create_params.Parent = parent.Handle;
1092 create_params.Style = (int)WindowStyles.WS_OVERLAPPED;
1095 create_params.Style |= (int)WindowStyles.WS_VISIBLE;
1098 return create_params;
1102 protected virtual ImeMode DefaultImeMode {
1104 return ImeMode.Inherit;
1108 protected virtual Size DefaultSize {
1110 return new Size(100, 23);
1114 #endregion // Protected Instance Properties
1116 #region Public Instance Methods
1117 public bool Contains(Control ctl) {
1121 while (current!=null) {
1125 current=current.parent;
1130 public void CreateControl() {
1135 for (int i=0; i<child_controls.Count; i++) {
1136 child_controls[i].CreateControl();
1141 public virtual void Refresh() {
1142 if (IsHandleCreated == true)
1143 XplatUI.RefreshWindow(window.Handle);
1146 public void SetBounds(int x, int y, int width, int height) {
1147 SetBoundsCore(x, y, width, height, BoundsSpecified.All);
1150 public void SetBounds(int x, int y, int width, int height, BoundsSpecified specified) {
1151 SetBoundsCore(x, y, width, height, specified);
1154 public void Show() {
1155 if (!IsHandleCreated) {
1156 this.CreateHandle();
1162 public object Invoke(Delegate method) { // ISynchronizeInvoke
1163 return Invoke(method, null);
1166 public object Invoke(Delegate method, object[] args) { // ISynchronizeInvoke
1167 IAsyncResult result;
1169 result=BeginInvoke(method, args);
1170 return EndInvoke(result);
1173 public IAsyncResult BeginInvoke(Delegate method) { // ISynchronizeInvoke
1174 return BeginInvoke(method, null);
1177 protected virtual AccessibleObject CreateAccessibilityInstance() {
1178 return new AccessibleObject(this);
1181 protected virtual ControlCollection CreateControlsInstance() {
1182 return new ControlCollection(this);
1185 protected void UpdateBounds() {
1193 if (!IsHandleCreated) {
1197 XplatUI.GetWindowPos(this.Handle, out x, out y, out width, out height, out client_width, out client_height);
1198 UpdateBounds(x, y, width, height, client_width, client_height);
1201 protected void UpdateBounds(int x, int y, int width, int height) {
1202 // UpdateBounds only seems to set our sizes and fire events but not update the GUI window to match
1204 bool resized = false;
1206 int client_x_diff = this.bounds.Width-this.client_size.Width;
1207 int client_y_diff = this.bounds.Height-this.client_size.Height;
1209 // Needed to generate required notifications
1210 if ((this.bounds.X!=x) || (this.bounds.Y!=y)) {
1214 if ((this.Bounds.Width!=width) || (this.Bounds.Height!=height)) {
1221 bounds.Height=height;
1223 // Update client rectangle as well
1224 prev_size.Width=client_size.Width;
1225 prev_size.Height=client_size.Height;
1226 client_size.Width=width-client_x_diff;
1227 client_size.Height=height-client_y_diff;
1230 OnLocationChanged(EventArgs.Empty);
1234 OnSizeChanged(EventArgs.Empty);
1238 protected void UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight) {
1239 UpdateBounds(x, y, width, height);
1241 this.client_size.Width=clientWidth;
1242 this.client_size.Height=clientHeight;
1245 public void Invalidate() {
1246 Invalidate(ClientRectangle, false);
1249 public void Invalidate(bool invalidateChildren) {
1250 Invalidate(ClientRectangle, invalidateChildren);
1253 public void Invalidate(System.Drawing.Rectangle rc) {
1254 Invalidate(rc, false);
1257 public void Invalidate(System.Drawing.Rectangle rc, bool invalidateChildren) {
1258 if (!IsHandleCreated || !is_visible) {
1262 XplatUI.Invalidate(Handle, rc, false);
1264 if (invalidateChildren) {
1265 for (int i=0; i<child_controls.Count; i++) child_controls[i].Invalidate();
1269 public void Invalidate(System.Drawing.Region region) {
1270 Invalidate(region, false);
1274 public void Invalidate(System.Drawing.Region region, bool invalidateChildren) {
1275 throw new NotImplementedException();
1277 // FIXME - should use the GetRegionScans function of the region to invalidate each area
1278 if (invalidateChildren) {
1279 for (int i=0; i<child_controls.Count; i++) child_controls[i].Invalidate();
1283 [MonoTODO("BeginInvoke() : Figure out a cross-platform way to handle this")]
1284 public IAsyncResult BeginInvoke(Delegate method, object[] args) { // ISynchronizeInvoke
1285 IAsyncResult result = null;
1291 public object EndInvoke(IAsyncResult async_result) { // ISynchronizeInvoke
1292 object result = null;
1297 public void PerformLayout() {
1298 PerformLayout(null, null);
1301 public void PerformLayout(Control affectedControl, string affectedProperty) {
1302 LayoutEventArgs levent = new LayoutEventArgs(affectedControl, affectedProperty);
1304 if (layout_suspended>0) {
1308 // Prevent recursion
1311 // Prevent us from getting messed up
1314 // Perform all Dock and Anchor calculations
1317 AnchorStyles anchor;
1322 space=this.DisplayRectangle;
1323 diff_width=space.Width-prev_size.Width;
1324 diff_height=space.Height-prev_size.Height;
1326 // Deal with docking
1327 for (int i=0; i < child_controls.Count; i++) {
1328 child=child_controls[i];
1329 switch (child.Dock) {
1330 case DockStyle.None: {
1335 case DockStyle.Left: {
1336 child.SetBounds(space.Left, space.Y, child.Width, space.Height);
1337 space.X+=child.Width;
1338 space.Width-=child.Width;
1342 case DockStyle.Top: {
1343 child.SetBounds(space.Left, space.Y, space.Width, child.Height);
1344 space.Y+=child.Height;
1345 space.Height-=child.Height;
1349 case DockStyle.Right: {
1350 child.SetBounds(space.Right-child.Width, space.Y, child.Width, space.Height);
1351 space.Width-=child.Width;
1355 case DockStyle.Bottom: {
1356 child.SetBounds(space.Left, space.Bottom-child.Height, space.Width, child.Height);
1357 space.Height-=child.Height;
1361 case DockStyle.Fill: {
1362 child.SetBounds(space.Left, space.Top, space.Width, space.Height);
1370 space=this.DisplayRectangle;
1372 // Deal with anchoring
1373 for (int i=0; i < child_controls.Count; i++) {
1379 child=child_controls[i];
1380 anchor=child.Anchor;
1385 height=child.Height;
1387 // If the control is docked we don't need to do anything
1388 if (child.Dock != DockStyle.None) {
1392 if ((anchor & AnchorStyles.Left) !=0 ) {
1393 if ((anchor & AnchorStyles.Right) != 0) {
1394 // Anchoring to left and right
1395 width=width+diff_width;
1399 } else if ((anchor & AnchorStyles.Right) != 0) {
1405 if ((anchor & AnchorStyles.Top) !=0 ) {
1406 if ((anchor & AnchorStyles.Bottom) != 0) {
1407 height+=diff_height;
1411 } else if ((anchor & AnchorStyles.Bottom) != 0) {
1426 child.SetBounds(left, top, width, height);
1429 // Let everyone know
1433 // Need to make sure we decremend layout_suspended
1439 public void ResumeLayout()
1441 ResumeLayout (true);
1444 public void ResumeLayout(bool peformLayout)
1448 if (layout_suspended > 0 || peformLayout == false)
1455 public void SuspendLayout()
1460 public Point PointToClient (Point p)
\r
1465 XplatUI.ScreenToClient (Handle, ref x, ref y);
\r
1467 return new Point (x, y);
\r
1472 protected virtual void WndProc(ref Message m) {
1473 EventArgs e = new EventArgs();
1476 Console.WriteLine("Received message {0}", m);
1479 switch((Msg)m.Msg) {
1482 case Msg.WM_LBUTTONDBLCLK: throw new NotImplementedException(); break;
1484 case Msg.WM_RBUTTONDOWN: throw new NotImplementedException(); break;
1485 case Msg.WM_RBUTTONUP: throw new NotImplementedException(); break;
1486 case Msg.WM_RBUTTONDBLCLK: throw new NotImplementedException(); break;
1488 case Msg.WM_MOUSEHOVER: throw new NotImplementedException(); break;
1489 case Msg.WM_MOUSELEAVE: throw new NotImplementedException(); break;
1492 // Keyboard handling
1493 case Msg.WM_CHAR: throw new NotImplementedException(); break;
1494 case Msg.WM_KEYDOWN: throw new NotImplementedException(); break;
1495 case Msg.WM_KEYUP: throw new NotImplementedException(); break;
1497 // Window management
1498 case Msg.WM_WINDOWPOSCHANGED: {
1504 case Msg.WM_PAINT: {
1506 PaintEventArgs paint_event;
1508 paint_event = XplatUI.PaintEventStart(Handle);
1509 OnPaint(paint_event);
1510 XplatUI.PaintEventEnd(Handle);
1515 case Msg.WM_ERASEBKGND:{
1516 if (GetStyle (ControlStyles.UserPaint)){
1517 PaintEventArgs eraseEventArgs = new PaintEventArgs (Graphics.FromHdc (m.WParam), new Rectangle (new Point (0,0),Size));
1518 OnPaintBackground (eraseEventArgs);
1519 m.Result = (IntPtr)1;
1522 m.Result = (IntPtr)0;
1529 case Msg.WM_LBUTTONUP: {
1532 OnMouseUp (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1534 LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1539 case Msg.WM_LBUTTONDOWN: {
1542 OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1543 clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1549 case Msg.WM_MOUSEWHEEL: {
1552 OnMouseWheel (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1553 clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1554 HighOrder(m.WParam.ToInt32())));
1559 case Msg.WM_MOUSEMOVE: {
1562 OnMouseMove (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()),
1564 LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()),
1570 if (GetStyle(ControlStyles.ResizeRedraw)) {
1577 case Msg.WM_KEYDOWN: {
1579 if (!ProcessKeyEventArgs (ref m))
1585 case Msg.WM_KEYUP: {
1587 if (!ProcessKeyEventArgs (ref m))
1595 case Msg.WM_WINDOWPOSCHANGED: throw new NotImplementedException(); break;
1596 case Msg.WM_SYSCOLORCHANGE: throw new NotImplementedException(); break;
1608 #endregion // Public Instance Methods
1611 #region // Protected Instance Methods
1612 protected virtual void CreateHandle() {
1614 throw new ObjectDisposedException(Name);
1617 if (IsHandleCreated) {
1622 window = new ControlNativeWindow(this);
1623 window.CreateHandle(CreateParams);
1626 if (window.Handle!=IntPtr.Zero) {
1627 if (!controls.Contains(window.Handle)) {
1628 controls.Add(window.Handle, this);
1631 creator_thread = Thread.CurrentThread;
1633 OnHandleCreated(EventArgs.Empty);
1637 protected virtual void DefWndProc(ref Message m) {
1638 window.DefWndProc(ref m);
1641 protected virtual void DestroyHandle() {
1642 if (IsHandleCreated) {
1643 if (Handle != IntPtr.Zero) {
1644 controls.Remove(Handle);
1647 if (window != null) {
1648 window.DestroyHandle();
1653 protected virtual bool ProcessKeyEventArgs (ref Message msg)
1655 KeyEventArgs key_event;
1658 case (int)Msg.WM_KEYDOWN: {
1659 key_event = new KeyEventArgs ((Keys)msg.WParam.ToInt32 ());
1660 OnKeyDown (key_event);
1661 return key_event.Handled;
1663 case (int)Msg.WM_KEYUP: {
1664 key_event = new KeyEventArgs ((Keys)msg.WParam.ToInt32 ());
1665 OnKeyUp (key_event);
1666 return key_event.Handled;
1676 protected virtual bool IsInputKey (Keys keyData)
1681 protected virtual bool ProcessDialogKey (Keys keyData)
1684 return Parent.ProcessDialogKey (keyData);
1689 protected bool GetStyle(ControlStyles flag) {
1690 return (control_style & flag) != 0;
1693 protected virtual bool ProcessDialogChar(char charCode) {
1694 throw new NotImplementedException();
1697 protected virtual bool ProcessMnemonic(char charCode) {
1698 throw new NotImplementedException();
1701 protected void RecreateHandle() {
1702 IEnumerator child = child_controls.GetEnumerator();
1704 if (IsHandleCreated) {
1710 while (child.MoveNext()) {
1711 ((Control)child.Current).RecreateHandle();
1716 protected virtual void ScaleCore(float dx, float dy) {
1717 throw new NotImplementedException();
1720 protected virtual void Select(bool directed, bool forward) {
1721 throw new NotImplementedException();
1724 protected virtual void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified) {
1725 // SetBoundsCore updates the Win32 control itself. UpdateBounds updates the controls variables and fires events, I'm guessing - pdb
1726 if ((specified & BoundsSpecified.X) != BoundsSpecified.X) {
1730 if ((specified & BoundsSpecified.Y) != BoundsSpecified.Y) {
1734 if ((specified & BoundsSpecified.Width)!= BoundsSpecified.Width) {
1738 if ((specified & BoundsSpecified.Height) != BoundsSpecified.Height) {
1742 if (IsHandleCreated) {
1743 XplatUI.SetWindowPos(Handle, x, y, width, height);
1746 UpdateBounds(x, y, width, height);
1749 protected virtual void SetClientSizeCore(int x, int y) {
1750 // Calculate the actual window size from the client size (it usually stays the same or grows)
1751 Rectangle ClientRect;
1752 Rectangle WindowRect;
1755 ClientRect = new Rectangle(0, 0, x, y);
1756 cp = this.CreateParams;
1758 if (XplatUI.CalculateWindowRect(Handle, ref ClientRect, cp.Style, false, out WindowRect)==false) {
1762 this.client_size = new Size(x, y);
1763 SetBoundsCore(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
1766 protected void SetStyle(ControlStyles flag, bool value) {
1768 control_style |= flag;
1770 control_style &= ~flag;
1774 #endregion // Public Instance Methods
1776 #region Private Instance Methods
1777 #endregion // Private Instance Methods
1780 #region Private Instance Methods
1781 internal virtual void DoDefaultAction() {
1782 // Only here to be overriden by our actual controls; this is needed by the accessibility class
1784 #endregion // Private Instance Methods
1787 #region OnXXX methods
1788 protected virtual void OnBackColorChanged(EventArgs e) {
1789 if (BackColorChanged!=null) BackColorChanged(this, e);
1790 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentBackColorChanged(e);
1793 protected virtual void OnBackgroundImageChanged(EventArgs e) {
1794 if (BackgroundImageChanged!=null) BackgroundImageChanged(this, e);
1795 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentBackgroundImageChanged(e);
1798 protected virtual void OnBindingContextChanged(EventArgs e) {
1799 if (BindingContextChanged!=null) BindingContextChanged(this, e);
1800 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentBindingContextChanged(e);
1803 protected virtual void OnCausesValidationChanged(EventArgs e) {
1804 if (CausesValidationChanged!=null) CausesValidationChanged(this, e);
1807 protected virtual void OnChangeUICues(UICuesEventArgs e) {
1808 if (CausesValidationChanged!=null) CausesValidationChanged(this, e);
1811 protected virtual void OnClick(EventArgs e) {
1812 if (Click!=null) Click(this, e);
1815 protected virtual void OnContextMenuChanged(EventArgs e) {
1816 if (ContextMenuChanged!=null) ContextMenuChanged(this, e);
1819 protected virtual void OnControlAdded(ControlEventArgs e) {
1820 if (ControlAdded!=null) ControlAdded(this, e);
1823 protected virtual void OnControlRemoved(ControlEventArgs e) {
1824 if (ControlRemoved!=null) ControlRemoved(this, e);
1827 protected virtual void OnCreateControl() {
1830 protected virtual void OnCursorChanged(EventArgs e) {
1831 if (CursorChanged!=null) CursorChanged(this, e);
1834 protected virtual void OnDockChanged(EventArgs e) {
1835 if (DockChanged!=null) DockChanged(this, e);
1838 protected virtual void OnDoubleClick(EventArgs e) {
1839 if (DoubleClick!=null) DoubleClick(this, e);
1842 protected virtual void OnDragDrop(DragEventArgs drgevent) {
1843 if (DragDrop!=null) DragDrop(this, drgevent);
1846 protected virtual void OnDragEnter(DragEventArgs drgevent) {
1847 if (DragEnter!=null) DragEnter(this, drgevent);
1850 protected virtual void OnDragLeave(EventArgs e) {
1851 if (DragLeave!=null) DragLeave(this, e);
1854 protected virtual void OnDragOver(DragEventArgs drgevent) {
1855 if (DragOver!=null) DragOver(this, drgevent);
1858 protected virtual void OnEnabledChanged(EventArgs e) {
1859 if (EnabledChanged!=null) EnabledChanged(this, e);
1860 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentEnabledChanged(e);
1863 protected virtual void OnEnter(EventArgs e) {
1864 if (Enter!=null) Enter(this, e);
1867 protected virtual void OnFontChanged(EventArgs e) {
1868 if (FontChanged!=null) FontChanged(this, e);
1871 protected virtual void OnForeColorChanged(EventArgs e) {
1872 if (ForeColorChanged!=null) ForeColorChanged(this, e);
1873 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentForeColorChanged(e);
1876 protected virtual void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) {
1877 if (GiveFeedback!=null) GiveFeedback(this, gfbevent);
1880 protected virtual void OnGotFocus(EventArgs e) {
1881 if (GotFocus!=null) GotFocus(this, e);
1884 protected virtual void OnHandleCreated(EventArgs e) {
1885 if (HandleCreated!=null) HandleCreated(this, e);
1888 protected virtual void OnHandleDestroyed(EventArgs e) {
1889 if (HandleDestroyed!=null) HandleDestroyed(this, e);
1892 protected virtual void OnHelpRequested(HelpEventArgs hevent) {
1893 if (HelpRequested!=null) HelpRequested(this, hevent);
1896 protected virtual void OnImeModeChanged(EventArgs e) {
1897 if (ImeModeChanged!=null) ImeModeChanged(this, e);
1900 protected virtual void OnInvalidated(InvalidateEventArgs e) {
1901 if (Invalidated!=null) Invalidated(this, e);
1905 protected virtual void OnKeyDown(KeyEventArgs e) {
1906 if (KeyDown!=null) KeyDown(this, e);
1909 protected virtual void OnKeyUp(KeyEventArgs e) {
1910 if (KeyUp!=null) KeyUp(this, e);
1913 protected virtual void OnLayout(LayoutEventArgs levent) {
1914 if (Layout!=null) Layout(this, levent);
1917 protected virtual void OnLeave(EventArgs e) {
1918 if (Leave!=null) Leave(this, e);
1921 protected virtual void OnLocationChanged(EventArgs e) {
1922 if (LocationChanged!=null) LocationChanged(this, e);
1925 protected virtual void OnLostFocus(EventArgs e) {
1926 if (LostFocus!=null) LostFocus(this, e);
1929 protected virtual void OnMouseDown(MouseEventArgs e) {
1930 if (MouseDown!=null) MouseDown(this, e);
1933 protected virtual void OnMouseEnter(EventArgs e) {
1934 if (MouseEnter!=null) MouseEnter(this, e);
1937 protected virtual void OnMouseHover(EventArgs e) {
1938 if (MouseHover!=null) MouseHover(this, e);
1941 protected virtual void OnMouseLeave(EventArgs e) {
1942 if (MouseLeave!=null) MouseLeave(this, e);
1945 protected virtual void OnMouseMove(MouseEventArgs e) {
1946 if (MouseMove!=null) MouseMove(this, e);
1949 protected virtual void OnMouseUp(MouseEventArgs e) {
1950 if (MouseUp!=null) MouseUp(this, e);
1953 protected virtual void OnMouseWheel(MouseEventArgs e) {
1954 if (MouseWheel!=null) MouseWheel(this, e);
1957 protected virtual void OnMove(EventArgs e) {
1958 if (Move!=null) Move(this, e);
1961 protected virtual void OnNotifyMessage(Message m) {
1965 protected virtual void OnPaint(PaintEventArgs e) {
1966 if (Paint!=null) Paint(this, e);
1969 protected virtual void OnPaintBackground(PaintEventArgs pevent) {
1973 protected virtual void OnParentBackColorChanged(EventArgs e) {
1974 if (background_color.IsEmpty && background_image==null) {
1976 OnBackColorChanged(e);
1980 protected virtual void OnParentBackgroundImageChanged(EventArgs e) {
1981 if (background_color.IsEmpty && background_image==null) {
1983 OnBackgroundImageChanged(e);
1987 protected virtual void OnParentBindingContextChanged(EventArgs e) {
1988 if (binding_context==null) {
1989 binding_context=Parent.binding_context;
1990 OnBindingContextChanged(e);
1994 protected virtual void OnParentChanged(EventArgs e) {
1995 if (ParentChanged!=null) ParentChanged(this, e);
1998 protected virtual void OnParentEnabledChanged(EventArgs e) {
1999 if ((is_enabled && !Parent.is_enabled) || (!is_enabled && Parent.is_enabled)) {
2002 EnabledChanged(this, e);
2006 protected virtual void OnParentFontChanged(EventArgs e) {
2013 protected virtual void OnParentForeColorChanged(EventArgs e) {
2014 if (foreground_color.IsEmpty) {
2016 OnForeColorChanged(e);
2020 protected virtual void OnParentRightToLeftChanged(EventArgs e) {
2021 if (right_to_left==RightToLeft.Inherit) {
2023 OnRightToLeftChanged(e);
2027 protected virtual void OnParentVisibleChanged(EventArgs e) {
2028 if (is_visible!=Parent.is_visible) {
2031 OnVisibleChanged(e);
2035 protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e) {
2036 if (QueryContinueDrag!=null) QueryContinueDrag(this, e);
2039 protected virtual void OnResize(EventArgs e) {
2040 if (Resize!=null) Resize(this, e);
2042 PerformLayout(this, "bounds");
2044 // Do we need to let our parent regenerate it's layout thing since we resized?
2047 protected virtual void OnRightToLeftChanged(EventArgs e) {
2048 if (RightToLeftChanged!=null) RightToLeftChanged(this, e);
2049 for (int i=0; i<child_controls.Count; i++) child_controls[i].OnParentRightToLeftChanged(e);
2052 protected virtual void OnSizeChanged(EventArgs e) {
2054 if (SizeChanged!=null) SizeChanged(this, e);
2057 protected virtual void OnStyleChanged(EventArgs e) {
2058 if (StyleChanged!=null) StyleChanged(this, e);
2061 protected virtual void OnSystemColorsChanged(EventArgs e) {
2062 if (SystemColorsChanged!=null) SystemColorsChanged(this, e);
2065 protected virtual void OnTabIndexChanged(EventArgs e) {
2066 if (TabIndexChanged!=null) TabIndexChanged(this, e);
2069 protected virtual void OnTabStopChanged(EventArgs e) {
2070 if (TabStopChanged!=null) TabStopChanged(this, e);
2073 protected virtual void OnTextChanged(EventArgs e) {
2074 if (TextChanged!=null) TextChanged(this, e);
2077 protected virtual void OnValidated(EventArgs e) {
2078 if (Validated!=null) Validated(this, e);
2081 protected virtual void OnValidating(System.ComponentModel.CancelEventArgs e) {
2082 if (Validating!=null) Validating(this, e);
2085 protected virtual void OnVisibleChanged(EventArgs e) {
2092 if (bmp_mem!=null) {
2098 if (!this.IsHandleCreated) {
2099 this.CreateHandle();
2105 if (VisibleChanged!=null) VisibleChanged(this, e);
2107 // We need to tell our kids
2108 for (int i=0; i<child_controls.Count; i++) {
2109 child_controls[i].OnParentVisibleChanged(e);
2112 #endregion // OnXXX methods
2115 public event EventHandler BackColorChanged;
2116 public event EventHandler BackgroundImageChanged;
2117 public event EventHandler BindingContextChanged;
2118 public event EventHandler CausesValidationChanged;
2119 public event UICuesEventHandler ChangeUICues;
2120 public event EventHandler Click;
2121 public event EventHandler ContextMenuChanged;
2122 public event ControlEventHandler ControlAdded;
2123 public event ControlEventHandler ControlRemoved;
2124 public event EventHandler CursorChanged;
2125 public event EventHandler DockChanged;
2126 public event EventHandler DoubleClick;
2127 public event DragEventHandler DragDrop;
2128 public event DragEventHandler DragEnter;
2129 public event EventHandler DragLeave;
2130 public event DragEventHandler DragOver;
2131 public event EventHandler EnabledChanged;
2132 public event EventHandler Enter;
2133 public event EventHandler FontChanged;
2134 public event EventHandler ForeColorChanged;
2135 public event GiveFeedbackEventHandler GiveFeedback;
2136 public event EventHandler GotFocus;
2137 public event EventHandler HandleCreated;
2138 public event EventHandler HandleDestroyed;
2139 public event HelpEventHandler HelpRequested;
2140 public event EventHandler ImeModeChanged;
2141 public event InvalidateEventHandler Invalidated;
2142 public event KeyEventHandler KeyDown;
2143 public event KeyPressEventHandler KeyPress;
2144 public event KeyEventHandler KeyUp;
2145 public event LayoutEventHandler Layout;
2146 public event EventHandler Leave;
2147 public event EventHandler LocationChanged;
2148 public event EventHandler LostFocus;
2149 public event MouseEventHandler MouseDown;
2150 public event EventHandler MouseEnter;
2151 public event EventHandler MouseHover;
2152 public event EventHandler MouseLeave;
2153 public event MouseEventHandler MouseMove;
2154 public event MouseEventHandler MouseUp;
2155 public event MouseEventHandler MouseWheel;
2156 public event EventHandler Move;
2157 public event PaintEventHandler Paint;
2158 public event EventHandler ParentChanged;
2159 public event QueryAccessibilityHelpEventHandler QueryAccessibilityHelp;
2160 public event QueryContinueDragEventHandler QueryContinueDrag;
2161 public event EventHandler Resize;
2162 public event EventHandler RightToLeftChanged;
2163 public event EventHandler SizeChanged;
2164 public event EventHandler StyleChanged;
2165 public event EventHandler SystemColorsChanged;
2166 public event EventHandler TabIndexChanged;
2167 public event EventHandler TabStopChanged;
2168 public event EventHandler TextChanged;
2169 public event EventHandler Validated;
2170 public event CancelEventHandler Validating;
2171 public event EventHandler VisibleChanged;
2172 #endregion // Events
2174 #region Private Methods
2175 internal static int LowOrder (int param)
2177 return (param & 0xffff);
2180 internal static int HighOrder (int param)
2182 return (param >> 16);
2185 internal static MouseButtons FromParamToMouseButtons (int param)
2187 MouseButtons buttons = MouseButtons.None;
2189 if ((param & (int) MsgButtons.MK_LBUTTON) != 0)
2190 buttons |= MouseButtons.Left;
2192 if ((param & (int) MsgButtons.MK_MBUTTON) != 0)
2193 buttons |= MouseButtons.Middle;
2195 if ((param & (int) MsgButtons.MK_RBUTTON) != 0)
2196 buttons |= MouseButtons.Right;