55c63f012e5f1341553a529c1c9874f3b44422e9
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Control.cs
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:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
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.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok            pbartok@novell.com
24 //
25 // Based on work by:
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
31 //
32 // $Revision: 1.27 $
33 // $Modtime: $
34 // $Log: Control.cs,v $
35 // Revision 1.27  2004/08/13 19:00:15  jordi
36 // implements PointToClient (ScreenToClient)
37 //
38 // Revision 1.26  2004/08/13 18:52:07  pbartok
39 // - Added Dispose() and destructor
40 // - Fixed resizing and bounds calculation
41 // - Fixed Layout
42 // - Added memory savings for invisible windows
43 //
44 // Revision 1.25  2004/08/12 19:31:19  pbartok
45 // - Fixed Anchoring bugs
46 //
47 // Revision 1.24  2004/08/12 16:10:42  jackson
48 // Add missing properties
49 //
50 // Revision 1.23  2004/08/11 22:20:59  pbartok
51 // - Signature fixes
52 //
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
58 //
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
67 //   them.
68 //
69 // Revision 1.20  2004/08/11 15:13:32  pbartok
70 // - Now properly reparents windows
71 //
72 // Revision 1.19  2004/08/11 14:37:11  pbartok
73 // - Duh!
74 //
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
78 //   straightforward
79 //
80 // Revision 1.17  2004/08/10 18:32:10  jordi
81 // throw ontextchange event
82 //
83 // Revision 1.16  2004/08/10 17:43:04  pbartok
84 // - Added more to the still unfinished Dock/Anchor layout code
85 //
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.
88 //
89 // Revision 1.14  2004/08/09 22:11:25  pbartok
90 // - Added incomplete dock layout code
91 // - Added support for mouse wheel
92 //
93 // Revision 1.13  2004/08/09 17:25:56  jackson
94 // Use new color names
95 //
96 // Revision 1.12  2004/08/09 15:54:51  jackson
97 // Get default properties from the theme.
98 //
99 // Revision 1.11  2004/08/06 21:30:56  pbartok
100 // - Fixed recursive loop when resizing
101 // - Improved/fixed redrawing on expose messages
102 //
103 // Revision 1.10  2004/08/06 15:53:39  jordi
104 // X11 keyboard navigation
105 //
106 // Revision 1.9  2004/08/04 21:14:26  pbartok
107 // - Fixed Invalidation bug (calculated wrong client area)
108 // - Added ClientSize setter
109 //
110 // Revision 1.8  2004/08/04 20:11:24  pbartok
111 // - Added Invalidate handling
112 //
113 // Revision 1.7  2004/07/27 10:38:17  jordi
114 // changes to be able to run winforms samples
115 //
116 // Revision 1.6  2004/07/19 19:09:42  jordi
117 // label control re-written: added missing functionlity, events, and properties
118 //
119 // Revision 1.5  2004/07/19 16:49:23  jordi
120 // fixes SetBounds logic
121 //
122 // Revision 1.4  2004/07/19 07:29:35  jordi
123 // Call RefreshWindow only if the window has created
124 //
125 // Revision 1.3  2004/07/15 17:03:35  jordi
126 // added basic mouse handeling events
127 //
128 // Revision 1.2  2004/07/13 15:31:45  jordi
129 // commit: new properties and fixes form size problems
130 //
131 // Revision 1.1  2004/07/09 05:21:25  pbartok
132 // - Initial check-in
133 //
134 //
135
136 // NOT COMPLETE 
137
138 using System;
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;
145
146 namespace System.Windows.Forms
147 {
148         public class Control : Component, ISynchronizeInvoke, IWin32Window
149         {
150                 #region Local Variables
151
152                 // Basic
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
157
158                 // State
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;
168
169                 // Visuals
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
175
176                 // Layout
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;
182
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;
191
192                 private Graphics                dc_mem;                 // Graphics context for double buffering
193                 private Bitmap                  bmp_mem;                // Bitmap for double buffering control
194
195                 #endregion      // Local Variables
196
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;
201
202                         public ControlNativeWindow(Control control) : base() {
203                                 this.control=control;
204                         }
205
206                         protected override void WndProc(ref Message m) {
207                                 control.WndProc(ref m);
208                         }
209                 }
210                 #endregion
211                 
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
218
219                         #region ControlCollection Public Constructor
220                         public ControlCollection(Control owner) {
221                                 this.owner=owner;
222                                 this.list=new ArrayList();
223                         }
224                         #endregion
225
226                         #region ControlCollection Public Instance Properties
227                         public int Count {
228                                 get {
229                                         return list.Count;
230                                 }
231                         }
232
233                         public bool IsReadOnly {
234                                 get {
235                                         return list.IsReadOnly;
236                                 }
237                         }
238
239                         public virtual Control this[int index] {
240                                 get {
241                                         if (index < 0 || index >= list.Count) {
242                                                 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
243                                         }
244                                         return (Control)list[index];
245                                 }
246                         }
247                         #endregion // ControlCollection Public Instance Properties
248                         
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?
254                                                 return;
255                                         }
256                                 }
257                                 list.Add(value);
258                                 value.Parent=owner;
259                         }
260                         
261                         public virtual void AddRange(Control[] controls) {
262                                 for (int i=0; i<controls.Length; i++) {
263                                         Add(controls[i]);
264                                 }
265                         }
266
267                         public virtual void Clear() {
268                                 owner.SuspendLayout();
269                                 list.Clear();
270                                 owner.ResumeLayout();
271                         }
272
273                         public virtual bool Contains(Control value) {
274                                 return list.Contains(value);
275                         }
276
277                         public void CopyTo(Array array, int index) {
278                                 list.CopyTo(array, index);
279                         }
280
281                         public override bool Equals(object other) {
282                                 if (other is ControlCollection && (((ControlCollection)other).owner==this.owner)) {
283                                         return(true);
284                                 } else {
285                                         return(false);
286                                 }
287                         }
288
289                         public int GetChildIndex(Control child) {
290                                 return GetChildIndex(child, false);
291                         }
292
293                         public int GetChildIndex(Control child, bool throwException) {
294                                 int index;
295
296                                 index=list.IndexOf(child);
297
298                                 if (index==-1 && throwException) {
299                                         throw new ArgumentException("Not a child control", "child");
300                                 }
301                                 return index;
302                         }
303
304                         public IEnumerator GetEnumerator() {
305                                 return list.GetEnumerator();
306                         }
307
308                         public override int GetHashCode() {
309                                 return base.GetHashCode();
310                         }
311
312                         public int IndexOf(Control control) {
313                                 return list.IndexOf(control);
314                         }
315
316                         public virtual void Remove(Control value) {
317                                 list.Remove(value);
318                         }
319
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");
323                                 }
324
325                                 list.RemoveAt(index);
326                         }
327
328                         public void SetChildIndex(Control child, int newIndex) {
329                                 int     old_index;
330
331                                 old_index=list.IndexOf(child);
332                                 if (old_index==-1) {
333                                         throw new ArgumentException("Not a child control", "child");
334                                 }
335
336                                 if (old_index==newIndex) {
337                                         return;
338                                 }
339
340                                 RemoveAt(old_index);
341
342                                 if (newIndex>list.Count) {
343                                         list.Add(child);
344                                 } else {
345                                         list.Insert(newIndex, child);
346                                 }
347                         }
348                         #endregion // ControlCollection Private Instance Methods
349
350                         #region ControlCollection Interface Properties
351                         object IList.this[int index] {
352                                 get {
353                                         if (index<0 || index>=list.Count) {
354                                                 throw new ArgumentOutOfRangeException("index", index, "ControlCollection does not have that many controls");
355                                         }
356                                         return this[index];
357                                 }
358
359                                 set {
360                                         if (!(value is Control)) {
361                                                 throw new ArgumentException("Object of type Control required", "value");
362                                         }
363
364                                         list[index]=(Control)value;
365                                 }
366                         }
367
368                         bool IList.IsFixedSize {
369                                 get {
370                                         return false;
371                                 }
372                         }
373
374                         bool IList.IsReadOnly {
375                                 get {
376                                         return list.IsReadOnly;
377                                 }
378                         }
379
380                         bool ICollection.IsSynchronized {
381                                 get {
382                                         return list.IsSynchronized;
383                                 }
384                         }
385
386                         object ICollection.SyncRoot {
387                                 get {
388                                         return list.SyncRoot;
389                                 }
390                         }
391                         #endregion // ControlCollection Interface Properties
392
393                         #region ControlCollection Interface Methods
394                         int IList.Add(object value) {
395                                 if (value == null) {
396                                         throw new ArgumentNullException("value", "Cannot add null controls");
397                                 }
398
399                                 if (!(value is Control)) {
400                                         throw new ArgumentException("Object of type Control required", "value");
401                                 }
402
403                                 return list.Add(value);
404                         }
405
406                         bool IList.Contains(object value) {
407                                 if (!(value is Control)) {
408                                         throw new ArgumentException("Object of type Control required", "value");
409                                 }
410
411                                 return this.Contains((Control) value);
412                         }
413
414                         int IList.IndexOf(object value) {
415                                 if (!(value is Control)) {
416                                         throw new ArgumentException("Object of type Control  required", "value");
417                                 }
418
419                                 return this.IndexOf((Control) value);
420                         }
421
422                         void IList.Insert(int index, object value) {
423                                 if (!(value is Control)) {
424                                         throw new ArgumentException("Object of type Control required", "value");
425                                 }
426                                 list.Insert(index, value);
427                         }
428
429                         void IList.Remove(object value) {
430                                 if (!(value is Control)) {
431                                         throw new ArgumentException("Object of type Control required", "value");
432                                 }
433                                 list.Remove(value);
434                         }
435
436                         void ICollection.CopyTo(Array array, int index) {
437                                 if (list.Count>0) {
438                                         list.CopyTo(array, index);
439                                 }
440                         }
441
442                         Object ICloneable.Clone() {
443                                 ControlCollection clone = new ControlCollection(this.owner);
444                                 clone.list=(ArrayList)list.Clone();             // FIXME: Do we need this?
445                                 return clone;
446                         }
447                         #endregion // ControlCollection Interface Methods
448                 }
449                 #endregion      // ControlCollection Class
450                 
451                 #region Public Constructors
452                 public Control() {
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;
459
460                         is_visible = true;
461                         is_disposed = false;
462                         is_enabled = true;
463                         has_focus = false;
464                         layout_suspended = 0;
465
466                         parent = null;
467                         background_image = null;
468                 }
469
470                 public Control(Control parent, string text) : this() {
471                         Text=text;
472                         Parent=parent;
473                 }
474
475                 public Control(Control parent, string text, int left, int top, int width, int height) : this() {
476                         Parent=parent;
477                         bounds.X=left;
478                         bounds.Y=top;
479                         bounds.Width=width;
480                         bounds.Height=height;
481                         SetBoundsCore(left, top, width, height, BoundsSpecified.All);
482                         Text=text;
483                 }
484
485                 public Control(string text) : this() {
486                         Text=text;
487                 }
488
489                 public Control(string text, int left, int top, int width, int height) : this() {
490                         bounds.X=left;
491                         bounds.Y=top;
492                         bounds.Width=width;
493                         bounds.Height=height;
494                         SetBoundsCore(left, top, width, height, BoundsSpecified.All);
495                         Text=text;
496                 }
497
498                 ~Control() {
499                         Dispose(true);
500                 }
501         
502                 public void Dispose() {
503                         Dispose(true);
504                         GC.SuppressFinalize(this);
505                 }
506
507                 protected override void Dispose(bool disposing) {
508                         if (dc_mem!=null) {
509                                 dc_mem.Dispose();
510                                 dc_mem=null;
511                         }
512
513                         if (bmp_mem!=null) {
514                                 bmp_mem.Dispose();
515                                 bmp_mem=null;
516                         }
517
518                         DestroyHandle();
519                         is_disposed=true;
520                 }
521                 #endregion      // Public Constructors
522
523                 #region Public Static Properties
524                 public static Color DefaultBackColor {
525                         get {
526                                 return ThemeEngine.Current.DefaultControlBackColor;
527                         }
528                 }
529
530                 public static Font DefaultFont {
531                         get {
532                                 return ThemeEngine.Current.DefaultFont;
533                         }
534                 }
535
536                 public static Color DefaultForeColor {
537                         get {
538                                 return ThemeEngine.Current.DefaultControlForeColor;
539                         }
540                 }
541
542                 public static Keys ModifierKeys {
543                         get {
544                                 return XplatUI.State.ModifierKeys;
545                         }
546                 }
547
548                 public static MouseButtons MouseButtons {
549                         get {
550                                 return XplatUI.State.MouseButtons;
551                         }
552                 }
553
554                 public static Point MousePosition {
555                         get {                           
556                                 int x = 0, y = 0;
557                                 XplatUI.GetCursorPos (IntPtr.Zero, ref x, ref y);
558                                 return new Point (x, y);
559                         }
560                 }
561                 #endregion      // Public Static Properties
562
563                 #region Public Instance Properties
564                 public AccessibleObject AccessibilityObject {
565                         get {
566                                 if (accessibility_object==null) {
567                                         accessibility_object=CreateAccessibilityInstance();
568                                 }
569                                 return accessibility_object;
570                         }
571                 }
572
573                 public string AccessibleDefaultActionDescription {
574                         get {
575                                 return AccessibilityObject.default_action;
576                         }
577
578                         set {
579                                 AccessibilityObject.default_action=value;
580                         }
581                 }
582
583                 public string AccessibleDescription {
584                         get {
585                                 return AccessibilityObject.description;
586                         }
587
588                         set {
589                                 AccessibilityObject.description=value;
590                         }
591                 }
592
593                 public string AccessibleName {
594                         get {
595                                 return AccessibilityObject.Name;
596                         }
597
598                         set {
599                                 AccessibilityObject.Name=value;
600                         }
601                 }
602
603                 public AccessibleRole AccessibleRole {
604                         get {
605                                 return AccessibilityObject.role;
606                         }
607
608                         set {
609                                 AccessibilityObject.role=value;
610                         }
611                 }
612
613                 public virtual bool AllowDrop {
614                         get {
615                                 return XplatUI.State.DropTarget;
616                         }
617
618                         set {
619                                 XplatUI.State.DropTarget=value;
620                         }
621                 }
622
623                 public virtual AnchorStyles Anchor {
624                         get {
625                                 return anchor_style;
626                         }
627
628                         set {
629                                 anchor_style=value;
630                         }
631                 }
632
633                 public virtual Color BackColor {
634                         get {
635                                 if (background_color.IsEmpty) {
636                                         if (parent!=null) {
637                                                 return parent.BackColor;
638                                         }
639                                         return DefaultBackColor;
640                                 }
641                                 return background_color;
642                         }
643
644                         set {
645                                 background_color=value;
646                                 Refresh();
647                         }
648                 }
649
650                 public virtual Image BackgroundImage {
651                         get {
652                                 return background_image;
653                         }
654
655                         set {
656                                 if (background_image!=value) {
657                                         background_image=value;
658                                         OnBackgroundImageChanged(EventArgs.Empty);
659                                 }
660                         }
661                 }
662
663                 public virtual BindingContext BindingContext {
664                         get {
665                                 throw new NotImplementedException();
666                         }
667
668                         set {
669                                 throw new NotImplementedException();
670                         }
671                 }
672
673
674                 public int Bottom {
675                         get {
676                                 return bounds.Y+bounds.Height;
677                         }
678                 }
679
680                 public Rectangle Bounds {
681                         get {
682                                 return this.bounds;
683                         }
684
685                         set {
686                                 SetBoundsCore(value.Left, value.Top, value.Width, value.Height, BoundsSpecified.All);
687                         }
688                 }
689
690                 public bool CanFocus {
691                         get {
692                                 throw new NotImplementedException();
693                         }
694                 }
695
696                 public bool CanSelect {
697                         get {
698                                 throw new NotImplementedException();
699                         }
700                 }
701
702                 public bool Capture {
703                         get {
704                                 throw new NotImplementedException();
705                         }
706
707                         set {
708                                 throw new NotImplementedException();
709                         }
710                 }
711
712                 public bool CausesValidation {
713                         get {
714                                 throw new NotImplementedException();
715                         }
716
717                         set {
718                                 throw new NotImplementedException();
719                         }
720                 }
721
722                 public Rectangle ClientRectangle {
723                         get {
724                                 return new Rectangle(0, 0, client_size.Width, client_size.Height);
725                         }
726                 }
727
728                 public Size ClientSize {
729                         get {
730                                 return client_size;
731                         }
732
733                         set {
734                                 this.SetClientSizeCore(value.Width, value.Height);
735                         }
736                 }
737
738                 public String CompanyName {
739                         get {
740                                 return "Mono Project, Novell, Inc.";
741                         }
742                 }
743
744                 public bool ContainsFocus {
745                         get {
746                                 throw new NotImplementedException();
747                         }
748                 }
749 #if notdef
750                 public virtual ContextMenu ContextMenu {
751                         get {
752                                 throw new NotImplementedException();
753                         }
754
755                         set {
756                                 throw new NotImplementedException();
757                         }
758                 }
759 #endif
760
761                 public ControlCollection Controls {
762                         get {
763                                 return this.child_controls;
764                         }
765                 }
766
767                 public bool Created {
768                         get {
769                                 throw new NotImplementedException();
770                         }
771                 }
772
773 #if notdef
774                 public virtual Cursor Cursor {
775                         get {
776                                 throw new NotImplementedException();
777                         }
778
779                         set {
780                                 throw new NotImplementedException();
781                         }
782                 }
783
784                 public ControlBidingsCollection DataBindings {
785                         get {
786                                 throw new NotImplementedException();
787                         }
788                 }
789 #endif
790                 public virtual Rectangle DisplayRectangle {
791                         get {
792                                 return ClientRectangle;
793                         }
794                 }
795
796                 public bool Disposing {
797                         get {
798                                 throw new NotImplementedException();
799                         }
800                 }
801
802                 public virtual DockStyle Dock {
803                         get { return dock_style;}
804
805                         set {
806                                 if (dock_style == value)
807                                         return;
808
809                                 dock_style = value;
810                                 OnDockChanged(EventArgs.Empty);
811                         }
812                 }
813
814                 public bool Enabled {
815                         get {
816                                 return is_enabled;
817                         }
818
819                         set {
820                                 is_enabled = value;
821                         }
822                 }
823
824                 public virtual bool Focused {
825                         get {
826                                 return this.has_focus;
827                         }
828                 }
829
830                 public virtual Font Font {
831                         get {
832                                 if (font != null) {
833                                         return font;
834                                 }
835
836                                 if (Parent != null && Parent.Font != null) {
837                                         return Parent.Font;
838                                 }
839
840                                 return DefaultFont;
841                         }
842
843                         set {
844                                 font=value;
845                                 Refresh();
846                         }
847                 }
848
849                 public virtual Color ForeColor {
850                         get {
851                                 if (foreground_color.IsEmpty) {
852                                         if (parent!=null) {
853                                                 return parent.ForeColor;
854                                         }
855                                         return DefaultForeColor;
856                                 }
857                                 return foreground_color;
858                         }
859
860                         set {
861                                 foreground_color=value;
862                                 Refresh();
863                         }
864                 }
865
866                 public bool IsDisposed {
867                         get {
868                                 return this.is_disposed;
869                         }
870                 }
871
872                 public bool IsHandleCreated {
873                         get {
874                                 if ((window!=null) && (window.Handle!=IntPtr.Zero)) {
875                                         return true;
876                                 }
877
878                                 return false;
879                         }
880                 }
881
882                 public string Name {
883                         get {
884                                 return this.name;
885                         }
886
887                         set {
888                                 this.name=value;
889                         }
890                 }
891
892                 public Control Parent {
893                         get {
894                                 return this.parent;
895                         }
896
897                         set {
898                                 if (parent!=value) {
899                                         if (parent!=null) {
900                                                 parent.Controls.Remove(this);
901                                         }
902
903                                         parent=value;
904
905                                         if (!parent.Controls.Contains(this)) {
906                                                 parent.Controls.Add(this);
907                                         }
908
909                                         XplatUI.SetParent(Handle, value.Handle);
910                                 }
911                         }
912                 }
913
914
915                 public IntPtr Handle {                                                  // IWin32Window
916                         get 
917                         {
918                                 if (!IsHandleCreated) {
919                                         CreateHandle();
920                                 }
921                                 return window.Handle;
922                         }
923                 }
924
925                 public bool InvokeRequired {                                            // ISynchronizeInvoke
926                         get {
927                                 if (creator_thread!=Thread.CurrentThread) {
928                                         return true;
929                                 }
930                                 return false;
931                         }
932                 }
933
934                 public bool Visible {
935                         get {
936                                 return this.is_visible;
937                         }
938
939                         set {
940                                 if (value!=is_visible) {
941                                         is_visible=value;
942                                         XplatUI.SetVisible(Handle, value);
943                                 }
944                         }
945                 }
946
947                 public virtual string Text {
948                         get {
949                                 return this.text;
950                         }
951
952                         set {
953                                 if (text!=value) {
954                                         text=value;
955                                         XplatUI.Text(Handle, text);
956                                         OnTextChanged (EventArgs.Empty);
957                                 }
958                         }
959                 }
960
961                 public int Left {
962                         get {
963                                 return this.bounds.X;
964                         }
965
966                         set {
967                                 SetBoundsCore(value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X);
968                         }
969                 }
970
971                 public int Top {
972                         get {
973                                 return this.bounds.Y;
974                         }
975
976                         set {
977                                 SetBoundsCore(bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y);
978                         }
979                 }
980
981                 public int Width {
982                         get {
983                                 return this.bounds.Width;
984                         }
985
986                         set {
987                                 SetBoundsCore(bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width);
988                         }
989                 }
990
991                 public int Height {
992                         get {
993                                 return this.bounds.Height;
994                         }
995
996                         set {
997                                 SetBoundsCore(bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height);
998                         }
999                 }
1000
1001                 public Point Location {
1002                         get {
1003                                 return new Point(bounds.X, bounds.Y);
1004                         }
1005
1006                         set {
1007                                 SetBoundsCore(value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
1008                         }
1009                 }
1010
1011                 public Size Size {
1012                         get {
1013                                 return new Size(Width, Height);
1014                         }
1015
1016                         set {
1017                                 SetBoundsCore(bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size);
1018                         }
1019                 }
1020
1021                 public ImeMode ImeMode {
1022                         get { return ime_mode; }
1023                         set { ime_mode = value; }
1024                 }
1025
1026                 public bool TabStop {
1027                         get { return tab_stop; }
1028                         set { tab_stop = value; }
1029                 }
1030
1031                 public int TabIndex {
1032                         get {
1033                                 return tab_index;
1034                         }
1035
1036                         set {
1037                                 tab_index = value;
1038                         }
1039                 }
1040
1041                 #endregion      // Public Instance Properties
1042
1043                 internal Graphics DeviceContext {
1044                         get { 
1045                                 if (dc_mem==null) {
1046                                         CreateBuffers(this.Width, this.Height);
1047                                 }
1048                                 return dc_mem;
1049                         }
1050                 }
1051
1052                 internal Bitmap ImageBuffer {
1053                         get {
1054                                 if (bmp_mem==null) {
1055                                         CreateBuffers(this.Width, this.Height);
1056                                 }
1057                                 return bmp_mem;
1058                         }
1059                 }
1060
1061                 internal void CreateBuffers (int width, int height)
1062                 {
1063                         if (dc_mem != null)
1064                                 dc_mem.Dispose ();
1065                         if (bmp_mem != null)
1066                                 bmp_mem.Dispose ();
1067
1068                         bmp_mem = new Bitmap (width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
1069                         dc_mem = Graphics.FromImage (bmp_mem);
1070                 }
1071
1072                 #region Protected Instance Properties
1073                 protected virtual CreateParams CreateParams {
1074                         get {
1075                                 CreateParams create_params = new CreateParams();
1076
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;
1082
1083                                 create_params.ClassName = XplatUI.DefaultClassName;
1084                                 create_params.ClassStyle = 0;
1085                                 create_params.ExStyle = 0;
1086                                 create_params.Param = 0;
1087
1088                                 if (parent!=null) {
1089                                         create_params.Parent = parent.Handle;
1090                                 }
1091
1092                                 create_params.Style = (int)WindowStyles.WS_OVERLAPPED;
1093
1094                                 if (is_visible) {
1095                                         create_params.Style |= (int)WindowStyles.WS_VISIBLE;
1096                                 }
1097
1098                                 return create_params;
1099                         }
1100                 }
1101
1102                 protected virtual ImeMode DefaultImeMode {
1103                         get {
1104                                 return ImeMode.Inherit;
1105                         }
1106                 }
1107
1108                 protected virtual Size DefaultSize {
1109                         get {
1110                                 return new Size(100, 23);
1111                         }
1112                 }
1113
1114                 #endregion      // Protected Instance Properties
1115
1116                 #region Public Instance Methods
1117                 public bool Contains(Control ctl) {
1118                         Control current;
1119
1120                         current=ctl;
1121                         while (current!=null) {
1122                                 if (current==ctl) {
1123                                         return true;
1124                                 }
1125                                 current=current.parent;
1126                         }
1127                         return false;
1128                 }
1129
1130                 public void CreateControl() {
1131                         Control child;
1132
1133                         CreateHandle();
1134
1135                         for (int i=0; i<child_controls.Count; i++) {
1136                                 child_controls[i].CreateControl();
1137                         }
1138                         OnCreateControl();
1139                 }
1140
1141                 public virtual void Refresh() {                 
1142                         if (IsHandleCreated == true)
1143                                 XplatUI.RefreshWindow(window.Handle);
1144                 }
1145
1146                 public void SetBounds(int x, int y, int width, int height) {
1147                         SetBoundsCore(x, y, width, height, BoundsSpecified.All);
1148                 }
1149
1150                 public void SetBounds(int x, int y, int width, int height, BoundsSpecified specified) {
1151                         SetBoundsCore(x, y, width, height, specified);
1152                 }
1153
1154                 public void Show() {
1155                         if (!IsHandleCreated) {
1156                                 this.CreateHandle();
1157                         }
1158
1159                         this.Visible=true;                      
1160                 }
1161
1162                 public object Invoke(Delegate method) {                                 // ISynchronizeInvoke
1163                         return Invoke(method, null);
1164                 }
1165
1166                 public object Invoke(Delegate method, object[] args) {                  // ISynchronizeInvoke
1167                         IAsyncResult    result;
1168
1169                         result=BeginInvoke(method, args);
1170                         return EndInvoke(result);
1171                 }
1172
1173                 public IAsyncResult BeginInvoke(Delegate method) {                      // ISynchronizeInvoke
1174                         return BeginInvoke(method, null);
1175                 }
1176
1177                 protected virtual AccessibleObject CreateAccessibilityInstance() {
1178                         return new AccessibleObject(this);
1179                 }
1180
1181                 protected virtual ControlCollection CreateControlsInstance() {
1182                         return new ControlCollection(this);
1183                 }
1184
1185                 protected void UpdateBounds() {
1186                         int     x;
1187                         int     y;
1188                         int     width;
1189                         int     height;
1190                         int     client_width;
1191                         int     client_height;
1192
1193                         if (!IsHandleCreated) {
1194                                 CreateHandle();
1195                         }
1196
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);
1199                 }
1200
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
1203                         bool    moved   = false;
1204                         bool    resized = false;
1205
1206                         int     client_x_diff = this.bounds.Width-this.client_size.Width;
1207                         int     client_y_diff = this.bounds.Height-this.client_size.Height;
1208
1209                         // Needed to generate required notifications
1210                         if ((this.bounds.X!=x) || (this.bounds.Y!=y)) {
1211                                 moved=true;
1212                         }
1213
1214                         if ((this.Bounds.Width!=width) || (this.Bounds.Height!=height)) {
1215                                 resized=true;
1216                         }
1217
1218                         bounds.X=x;
1219                         bounds.Y=y;
1220                         bounds.Width=width;
1221                         bounds.Height=height;
1222
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;
1228
1229                         if (moved) {
1230                                 OnLocationChanged(EventArgs.Empty);
1231                         }
1232
1233                         if (resized) {
1234                                 OnSizeChanged(EventArgs.Empty);
1235                         }
1236                 }
1237
1238                 protected void UpdateBounds(int x, int y, int width, int height, int clientWidth, int clientHeight) {
1239                         UpdateBounds(x, y, width, height);
1240
1241                         this.client_size.Width=clientWidth;
1242                         this.client_size.Height=clientHeight;
1243                 }
1244
1245                 public void Invalidate() {
1246                         Invalidate(ClientRectangle, false);
1247                 }
1248
1249                 public void Invalidate(bool invalidateChildren) {
1250                         Invalidate(ClientRectangle, invalidateChildren);
1251                 }
1252
1253                 public void Invalidate(System.Drawing.Rectangle rc) {
1254                         Invalidate(rc, false);
1255                 }
1256
1257                 public void Invalidate(System.Drawing.Rectangle rc, bool invalidateChildren) {
1258                         if (!IsHandleCreated || !is_visible) {
1259                                 return;
1260                         }
1261
1262                         XplatUI.Invalidate(Handle, rc, false);
1263
1264                         if (invalidateChildren) {
1265                                 for (int i=0; i<child_controls.Count; i++) child_controls[i].Invalidate();
1266                         }
1267                 }
1268
1269                 public void Invalidate(System.Drawing.Region region) {
1270                         Invalidate(region, false);
1271                 }
1272
1273                 [MonoTODO]
1274                 public void Invalidate(System.Drawing.Region region, bool invalidateChildren) {
1275                         throw new NotImplementedException();
1276
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();
1280                         }
1281                 }
1282
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;
1286
1287                         return result;
1288                 }
1289
1290                 [MonoTODO]
1291                 public object EndInvoke(IAsyncResult async_result) {                    // ISynchronizeInvoke
1292                         object result = null;
1293
1294                         return result;
1295                 }
1296
1297                 public void PerformLayout() {
1298                         PerformLayout(null, null);
1299                 }
1300
1301                 public void PerformLayout(Control affectedControl, string affectedProperty) {
1302                         LayoutEventArgs levent = new LayoutEventArgs(affectedControl, affectedProperty);
1303
1304                         if (layout_suspended>0) {
1305                                 return;
1306                         }
1307
1308                         // Prevent recursion
1309                         //in_layout=true;
1310
1311                         // Prevent us from getting messed up
1312                         layout_suspended++;
1313
1314                         // Perform all Dock and Anchor calculations
1315                         try {
1316                                 Control         child;
1317                                 AnchorStyles    anchor;
1318                                 Rectangle       space;
1319                                 int             diff_width;
1320                                 int             diff_height;
1321
1322                                 space=this.DisplayRectangle;
1323                                 diff_width=space.Width-prev_size.Width;
1324                                 diff_height=space.Height-prev_size.Height;
1325
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: {
1331                                                         // Do nothing
1332                                                         break;
1333                                                 }
1334
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;
1339                                                         break;
1340                                                 }
1341
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;
1346                                                         break;
1347                                                 }
1348                                 
1349                                                 case DockStyle.Right: {
1350                                                         child.SetBounds(space.Right-child.Width, space.Y, child.Width, space.Height);
1351                                                         space.Width-=child.Width;
1352                                                         break;
1353                                                 }
1354
1355                                                 case DockStyle.Bottom: {
1356                                                         child.SetBounds(space.Left, space.Bottom-child.Height, space.Width, child.Height);
1357                                                         space.Height-=child.Height;
1358                                                         break;
1359                                                 }
1360
1361                                                 case DockStyle.Fill: {
1362                                                         child.SetBounds(space.Left, space.Top, space.Width, space.Height);
1363                                                         space.Width=0;
1364                                                         space.Height=0;
1365                                                         break;
1366                                                 }
1367                                         }
1368                                 }
1369
1370                                 space=this.DisplayRectangle;
1371
1372                                 // Deal with anchoring
1373                                 for (int i=0; i < child_controls.Count; i++) {
1374                                         int left;
1375                                         int top;
1376                                         int width;
1377                                         int height;
1378
1379                                         child=child_controls[i];
1380                                         anchor=child.Anchor;
1381
1382                                         left=child.Left;
1383                                         top=child.Top;
1384                                         width=child.Width;
1385                                         height=child.Height;
1386
1387                                         // If the control is docked we don't need to do anything
1388                                         if (child.Dock != DockStyle.None) {
1389                                                 continue;
1390                                         }
1391
1392                                         if ((anchor & AnchorStyles.Left) !=0 ) {
1393                                                 if ((anchor & AnchorStyles.Right) != 0) {
1394                                                         // Anchoring to left and right
1395                                                         width=width+diff_width;
1396                                                 } else {
1397                                                         ; // nothing to do
1398                                                 }
1399                                         } else if ((anchor & AnchorStyles.Right) != 0) {
1400                                                 left+=diff_width;
1401                                         } else {
1402                                                 left+=diff_width/2;
1403                                         }
1404
1405                                         if ((anchor & AnchorStyles.Top) !=0 ) {
1406                                                 if ((anchor & AnchorStyles.Bottom) != 0) {
1407                                                         height+=diff_height;
1408                                                 } else {
1409                                                         ; // nothing to do
1410                                                 }
1411                                         } else if ((anchor & AnchorStyles.Bottom) != 0) {
1412                                                 top+=diff_height;
1413                                         } else {
1414                                                 top+=diff_height/2;
1415                                         }
1416
1417                                         // Sanity
1418                                         if (width < 0) {
1419                                                 width=0;
1420                                         }
1421
1422                                         if (height < 0) {
1423                                                 height=0;
1424                                         }
1425
1426                                         child.SetBounds(left, top, width, height);
1427                                 }
1428
1429                                 // Let everyone know
1430                                 OnLayout(levent);
1431                         }
1432
1433                         // Need to make sure we decremend layout_suspended
1434                         finally {
1435                                 layout_suspended--;
1436                         }
1437                 }
1438
1439                 public void ResumeLayout() 
1440                 {
1441                         ResumeLayout (true);
1442                 }
1443
1444                 public void ResumeLayout(bool peformLayout) 
1445                 {
1446                         layout_suspended--;
1447                         
1448                         if (layout_suspended > 0 || peformLayout == false)
1449                                 return;
1450
1451                         PerformLayout();
1452                 }
1453
1454                 
1455                 public void SuspendLayout() 
1456                 {
1457                         layout_suspended++;
1458                 }
1459
1460                 public Point PointToClient (Point p)\r
1461                 {\r
1462                         int x = p.X;\r
1463                         int y = p.Y;\r
1464 \r
1465                         XplatUI.ScreenToClient (Handle, ref x, ref y);\r
1466 \r
1467                         return new Point (x, y);\r
1468                 }\r
1469
1470
1471                 [MonoTODO]
1472                 protected virtual void WndProc(ref Message m) {
1473                         EventArgs       e = new EventArgs();
1474
1475 #if debug
1476                         Console.WriteLine("Received message {0}", m);
1477 #endif
1478
1479                         switch((Msg)m.Msg) {
1480 #if notyet
1481                                 // Mouse handling
1482                                 case Msg.WM_LBUTTONDBLCLK:      throw new NotImplementedException();    break;
1483
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;
1487
1488                                 case Msg.WM_MOUSEHOVER:         throw new NotImplementedException();    break;
1489                                 case Msg.WM_MOUSELEAVE:         throw new NotImplementedException();    break;
1490                                 
1491
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;
1496 #endif
1497                                 // Window management
1498                                 case Msg.WM_WINDOWPOSCHANGED: {
1499                                         UpdateBounds();
1500                                         DefWndProc(ref m);
1501                                         break;
1502                                 }
1503
1504                                 case Msg.WM_PAINT: {
1505                                         Rectangle       rect;
1506                                         PaintEventArgs  paint_event;
1507
1508                                         paint_event = XplatUI.PaintEventStart(Handle);
1509                                         OnPaint(paint_event);
1510                                         XplatUI.PaintEventEnd(Handle);
1511                                         DefWndProc(ref m);      
1512                                         break;
1513                                 }
1514                                 
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;
1520                                         }       
1521                                         else {
1522                                                 m.Result = (IntPtr)0;
1523                                                 DefWndProc (ref m);     
1524                                         }                                       
1525                                         
1526                                         break;
1527                                 }
1528                                 
1529                                 case Msg.WM_LBUTTONUP: {                                        
1530                                         int clicks = 1;
1531                                         
1532                                         OnMouseUp (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), 
1533                                                         clicks, 
1534                                                         LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 
1535                                                         0));
1536                                         break;
1537                                 }
1538                                 
1539                                 case Msg.WM_LBUTTONDOWN: {                                      
1540                                         int clicks = 1;
1541                                         
1542                                         OnMouseDown (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), 
1543                                                         clicks, LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 
1544                                                         0));
1545                                         
1546                                         break;
1547                                 }
1548
1549                                 case Msg.WM_MOUSEWHEEL: {
1550                                         int clicks = 1;
1551
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())));
1555                                         break;
1556                                 }
1557
1558                                 
1559                                 case Msg.WM_MOUSEMOVE: {                                        
1560                                         int clicks = 1;
1561
1562                                         OnMouseMove  (new MouseEventArgs (FromParamToMouseButtons ((int) m.WParam.ToInt32()), 
1563                                                         clicks, 
1564                                                         LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()), 
1565                                                         0));
1566                                         break;
1567                                 }
1568
1569                                 case Msg.WM_SIZE: {                                     
1570                                         if (GetStyle(ControlStyles.ResizeRedraw)) {
1571                                                 Invalidate();
1572                                         }
1573                                         DefWndProc(ref m);      
1574                                         break;                          
1575                                 }
1576
1577                                 case Msg.WM_KEYDOWN: {
1578
1579                                         if (!ProcessKeyEventArgs (ref m))
1580                                                 DefWndProc (ref m);
1581
1582                                         break;                                  
1583                                 }
1584
1585                                 case Msg.WM_KEYUP: {
1586
1587                                         if (!ProcessKeyEventArgs (ref m))
1588                                                 DefWndProc (ref m);
1589
1590                                         break;                                  
1591                                 }               
1592                                 
1593
1594 #if notyet                              
1595                                 case Msg.WM_WINDOWPOSCHANGED:   throw new NotImplementedException();    break;
1596                                 case Msg.WM_SYSCOLORCHANGE:     throw new NotImplementedException();    break;
1597                                 
1598 #endif
1599
1600                                 default:
1601                                         DefWndProc(ref m);      
1602                                         break;
1603                         }
1604                         
1605                         
1606                         
1607                 }
1608                 #endregion      // Public Instance Methods
1609
1610
1611                 #region         // Protected Instance Methods
1612                 protected virtual void CreateHandle() {
1613                         if (IsDisposed) {
1614                                 throw new ObjectDisposedException(Name);
1615                         }
1616
1617                         if (IsHandleCreated) {
1618                                 return;
1619                         }
1620
1621                         if (window==null) {
1622                                 window = new ControlNativeWindow(this);
1623                                 window.CreateHandle(CreateParams);
1624                         }
1625
1626                         if (window.Handle!=IntPtr.Zero) {
1627                                 if (!controls.Contains(window.Handle)) {
1628                                         controls.Add(window.Handle, this);
1629                                 }
1630
1631                                 creator_thread = Thread.CurrentThread;
1632
1633                                 OnHandleCreated(EventArgs.Empty);
1634                         }
1635                 }
1636
1637                 protected virtual void DefWndProc(ref Message m) {
1638                         window.DefWndProc(ref m);
1639                 }
1640
1641                 protected virtual void DestroyHandle() {
1642                         if (IsHandleCreated) {
1643                                 if (Handle != IntPtr.Zero) {
1644                                         controls.Remove(Handle);
1645                                 }
1646
1647                                 if (window != null) {
1648                                         window.DestroyHandle();
1649                                 }
1650                         }
1651                 }
1652
1653                 protected virtual bool ProcessKeyEventArgs (ref Message msg)
1654                 {
1655                         KeyEventArgs key_event;
1656
1657                         switch (msg.Msg) {
1658                         case (int)Msg.WM_KEYDOWN: {
1659                                 key_event = new KeyEventArgs ((Keys)msg.WParam.ToInt32 ());
1660                                 OnKeyDown (key_event);
1661                                 return key_event.Handled;
1662                         }
1663                         case (int)Msg.WM_KEYUP: {
1664                                 key_event = new KeyEventArgs ((Keys)msg.WParam.ToInt32 ());
1665                                 OnKeyUp (key_event);
1666                                 return key_event.Handled;
1667                         }
1668
1669                         default:
1670                                 break;
1671                         }
1672
1673                         return false;
1674                 }
1675
1676                 protected virtual bool IsInputKey (Keys keyData) 
1677                 {
1678                         return false;
1679                 }
1680
1681                 protected virtual bool ProcessDialogKey (Keys keyData)
1682                 {
1683                         if (parent != null)
1684                                 return Parent.ProcessDialogKey (keyData);
1685
1686                         return false;
1687                 }
1688
1689                 protected bool GetStyle(ControlStyles flag) {
1690                         return (control_style & flag) != 0;
1691                 }
1692
1693                 protected virtual bool ProcessDialogChar(char charCode) {
1694                         throw new NotImplementedException();
1695                 }
1696
1697                 protected virtual bool ProcessMnemonic(char charCode) {
1698                         throw new NotImplementedException();
1699                 }
1700
1701                 protected void RecreateHandle() {
1702                         IEnumerator child = child_controls.GetEnumerator();
1703
1704                         if (IsHandleCreated) {
1705                                 DestroyHandle();
1706                                 CreateHandle();
1707
1708                                 // FIXME ZOrder?
1709
1710                                 while (child.MoveNext()) {
1711                                         ((Control)child.Current).RecreateHandle();
1712                                 }
1713                         }
1714                 }
1715
1716                 protected virtual void ScaleCore(float dx, float dy) {
1717                         throw new NotImplementedException();
1718                 }
1719
1720                 protected virtual void Select(bool directed, bool forward) {
1721                         throw new NotImplementedException();
1722                 }
1723
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) {
1727                                 x = Left;
1728                         }
1729
1730                         if ((specified & BoundsSpecified.Y) != BoundsSpecified.Y) {
1731                                 y = Top;
1732                         }
1733
1734                         if ((specified & BoundsSpecified.Width)!= BoundsSpecified.Width) {
1735                                 width = Width;
1736                         }
1737
1738                         if ((specified & BoundsSpecified.Height) != BoundsSpecified.Height) {
1739                                 height = Height;
1740                         }
1741
1742                         if (IsHandleCreated) {
1743                                 XplatUI.SetWindowPos(Handle, x, y, width, height);
1744                         }
1745
1746                         UpdateBounds(x, y, width, height);
1747                 }
1748
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;
1753                         CreateParams    cp;
1754
1755                         ClientRect = new Rectangle(0, 0, x, y);
1756                         cp = this.CreateParams;
1757
1758                         if (XplatUI.CalculateWindowRect(Handle, ref ClientRect, cp.Style, false, out WindowRect)==false) {
1759                                 return;
1760                         }
1761
1762                         this.client_size = new Size(x, y);
1763                         SetBoundsCore(bounds.X, bounds.Y, WindowRect.Width, WindowRect.Height, BoundsSpecified.Size);
1764                 }
1765
1766                 protected void SetStyle(ControlStyles flag, bool value) {
1767                         if (value) {
1768                                 control_style |= flag;
1769                         } else {
1770                                 control_style &= ~flag;
1771                         }
1772                 }
1773
1774                 #endregion      // Public Instance Methods
1775
1776                 #region Private Instance Methods
1777                 #endregion      // Private Instance Methods
1778
1779
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
1783                 }
1784                 #endregion      // Private Instance Methods
1785
1786
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);
1791                 }
1792
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);
1796                 }
1797
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);
1801                 }
1802
1803                 protected virtual void OnCausesValidationChanged(EventArgs e) {
1804                         if (CausesValidationChanged!=null) CausesValidationChanged(this, e);
1805                 }
1806
1807                 protected virtual void OnChangeUICues(UICuesEventArgs e) {
1808                         if (CausesValidationChanged!=null) CausesValidationChanged(this, e);
1809                 }
1810
1811                 protected virtual void OnClick(EventArgs e) {
1812                         if (Click!=null) Click(this, e);
1813                 }
1814
1815                 protected virtual void OnContextMenuChanged(EventArgs e) {
1816                         if (ContextMenuChanged!=null) ContextMenuChanged(this, e);
1817                 }
1818
1819                 protected virtual void OnControlAdded(ControlEventArgs e) {
1820                         if (ControlAdded!=null) ControlAdded(this, e);
1821                 }
1822
1823                 protected virtual void OnControlRemoved(ControlEventArgs e) {
1824                         if (ControlRemoved!=null) ControlRemoved(this, e);
1825                 }
1826
1827                 protected virtual void OnCreateControl() {
1828                 }
1829
1830                 protected virtual void OnCursorChanged(EventArgs e) {
1831                         if (CursorChanged!=null) CursorChanged(this, e);
1832                 }
1833
1834                 protected virtual void OnDockChanged(EventArgs e) {
1835                         if (DockChanged!=null) DockChanged(this, e);
1836                 }
1837
1838                 protected virtual void OnDoubleClick(EventArgs e) {
1839                         if (DoubleClick!=null) DoubleClick(this, e);
1840                 }
1841
1842                 protected virtual void OnDragDrop(DragEventArgs drgevent) {
1843                         if (DragDrop!=null) DragDrop(this, drgevent);
1844                 }
1845
1846                 protected virtual void OnDragEnter(DragEventArgs drgevent) {
1847                         if (DragEnter!=null) DragEnter(this, drgevent);
1848                 }
1849
1850                 protected virtual void OnDragLeave(EventArgs e) {
1851                         if (DragLeave!=null) DragLeave(this, e);
1852                 }
1853
1854                 protected virtual void OnDragOver(DragEventArgs drgevent) {
1855                         if (DragOver!=null) DragOver(this, drgevent);
1856                 }
1857
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);
1861                 }
1862
1863                 protected virtual void OnEnter(EventArgs e) {
1864                         if (Enter!=null) Enter(this, e);
1865                 }
1866
1867                 protected virtual void OnFontChanged(EventArgs e) {
1868                         if (FontChanged!=null) FontChanged(this, e);
1869                 }
1870
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);
1874                 }
1875
1876                 protected virtual void OnGiveFeedback(GiveFeedbackEventArgs gfbevent) {
1877                         if (GiveFeedback!=null) GiveFeedback(this, gfbevent);
1878                 }
1879                 
1880                 protected virtual void OnGotFocus(EventArgs e) {
1881                         if (GotFocus!=null) GotFocus(this, e);
1882                 }
1883
1884                 protected virtual void OnHandleCreated(EventArgs e) {
1885                         if (HandleCreated!=null) HandleCreated(this, e);
1886                 }
1887
1888                 protected virtual void OnHandleDestroyed(EventArgs e) {
1889                         if (HandleDestroyed!=null) HandleDestroyed(this, e);
1890                 }
1891
1892                 protected virtual void OnHelpRequested(HelpEventArgs hevent) {
1893                         if (HelpRequested!=null) HelpRequested(this, hevent);
1894                 }
1895
1896                 protected virtual void OnImeModeChanged(EventArgs e) {
1897                         if (ImeModeChanged!=null) ImeModeChanged(this, e);
1898                 }
1899
1900                 protected virtual void OnInvalidated(InvalidateEventArgs e) {
1901                         if (Invalidated!=null) Invalidated(this, e);
1902                 }
1903
1904
1905                 protected virtual void OnKeyDown(KeyEventArgs e) {                      
1906                         if (KeyDown!=null) KeyDown(this, e);
1907                 }
1908
1909                 protected virtual void OnKeyUp(KeyEventArgs e) {
1910                         if (KeyUp!=null) KeyUp(this, e);
1911                 }
1912
1913                 protected virtual void OnLayout(LayoutEventArgs levent) {
1914                         if (Layout!=null) Layout(this, levent);
1915                 }
1916
1917                 protected virtual void OnLeave(EventArgs e) {
1918                         if (Leave!=null) Leave(this, e);
1919                 }
1920
1921                 protected virtual void OnLocationChanged(EventArgs e) {
1922                         if (LocationChanged!=null) LocationChanged(this, e);
1923                 }
1924
1925                 protected virtual void OnLostFocus(EventArgs e) {
1926                         if (LostFocus!=null) LostFocus(this, e);
1927                 }
1928
1929                 protected virtual void OnMouseDown(MouseEventArgs e) {
1930                         if (MouseDown!=null) MouseDown(this, e);
1931                 }
1932
1933                 protected virtual void OnMouseEnter(EventArgs e) {
1934                         if (MouseEnter!=null) MouseEnter(this, e);
1935                 }
1936
1937                 protected virtual void OnMouseHover(EventArgs e) {
1938                         if (MouseHover!=null) MouseHover(this, e);
1939                 }
1940
1941                 protected virtual void OnMouseLeave(EventArgs e) {
1942                         if (MouseLeave!=null) MouseLeave(this, e);
1943                 }
1944
1945                 protected virtual void OnMouseMove(MouseEventArgs e) {                  
1946                         if (MouseMove!=null) MouseMove(this, e);
1947                 }
1948
1949                 protected virtual void OnMouseUp(MouseEventArgs e) {
1950                         if (MouseUp!=null) MouseUp(this, e);
1951                 }
1952
1953                 protected virtual void OnMouseWheel(MouseEventArgs e) {
1954                         if (MouseWheel!=null) MouseWheel(this, e);
1955                 }
1956
1957                 protected virtual void OnMove(EventArgs e) {
1958                         if (Move!=null) Move(this, e);
1959                 }
1960
1961                 protected virtual void OnNotifyMessage(Message m) {
1962                         // Override me!
1963                 }
1964
1965                 protected virtual void OnPaint(PaintEventArgs e) {
1966                         if (Paint!=null) Paint(this, e);
1967                 }
1968
1969                 protected virtual void OnPaintBackground(PaintEventArgs pevent) {
1970                         // Override me!
1971                 }
1972
1973                 protected virtual void OnParentBackColorChanged(EventArgs e) {
1974                         if (background_color.IsEmpty && background_image==null) {
1975                                 Invalidate();
1976                                 OnBackColorChanged(e);
1977                         }
1978                 }
1979
1980                 protected virtual void OnParentBackgroundImageChanged(EventArgs e) {
1981                         if (background_color.IsEmpty && background_image==null) {
1982                                 Invalidate();
1983                                 OnBackgroundImageChanged(e);
1984                         }
1985                 }
1986
1987                 protected virtual void OnParentBindingContextChanged(EventArgs e) {
1988                         if (binding_context==null) {
1989                                 binding_context=Parent.binding_context;
1990                                 OnBindingContextChanged(e);
1991                         }
1992                 }
1993
1994                 protected virtual void OnParentChanged(EventArgs e) {
1995                         if (ParentChanged!=null) ParentChanged(this, e);
1996                 }
1997
1998                 protected virtual void OnParentEnabledChanged(EventArgs e) {
1999                         if ((is_enabled && !Parent.is_enabled) || (!is_enabled && Parent.is_enabled)) {
2000                                 is_enabled=false;
2001                                 Invalidate();
2002                                 EnabledChanged(this, e);
2003                         }
2004                 }
2005
2006                 protected virtual void OnParentFontChanged(EventArgs e) {
2007                         if (font==null) {
2008                                 Invalidate();
2009                                 OnFontChanged(e);
2010                         }
2011                 }
2012
2013                 protected virtual void OnParentForeColorChanged(EventArgs e) {
2014                         if (foreground_color.IsEmpty) {
2015                                 Invalidate();
2016                                 OnForeColorChanged(e);
2017                         }
2018                 }
2019
2020                 protected virtual void OnParentRightToLeftChanged(EventArgs e) {
2021                         if (right_to_left==RightToLeft.Inherit) {
2022                                 Invalidate();
2023                                 OnRightToLeftChanged(e);
2024                         }
2025                 }
2026
2027                 protected virtual void OnParentVisibleChanged(EventArgs e) {
2028                         if (is_visible!=Parent.is_visible) {
2029                                 is_visible=false;
2030                                 Invalidate();
2031                                 OnVisibleChanged(e);
2032                         }
2033                 }
2034
2035                 protected virtual void OnQueryContinueDrag(QueryContinueDragEventArgs e) {
2036                         if (QueryContinueDrag!=null) QueryContinueDrag(this, e);
2037                 }
2038
2039                 protected virtual void OnResize(EventArgs e) {
2040                         if (Resize!=null) Resize(this, e);
2041
2042                         PerformLayout(this, "bounds");
2043
2044                         // Do we need to let our parent regenerate it's layout thing since we resized?
2045                 }
2046
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);
2050                 }
2051
2052                 protected virtual void OnSizeChanged(EventArgs e) {                     
2053                         OnResize(e);
2054                         if (SizeChanged!=null) SizeChanged(this, e);
2055                 }
2056
2057                 protected virtual void OnStyleChanged(EventArgs e) {
2058                         if (StyleChanged!=null) StyleChanged(this, e);
2059                 }
2060
2061                 protected virtual void OnSystemColorsChanged(EventArgs e) {
2062                         if (SystemColorsChanged!=null) SystemColorsChanged(this, e);
2063                 }
2064
2065                 protected virtual void OnTabIndexChanged(EventArgs e) {
2066                         if (TabIndexChanged!=null) TabIndexChanged(this, e);
2067                 }
2068
2069                 protected virtual void OnTabStopChanged(EventArgs e) {
2070                         if (TabStopChanged!=null) TabStopChanged(this, e);
2071                 }
2072
2073                 protected virtual void OnTextChanged(EventArgs e) {
2074                         if (TextChanged!=null) TextChanged(this, e);
2075                 }
2076
2077                 protected virtual void OnValidated(EventArgs e) {
2078                         if (Validated!=null) Validated(this, e);
2079                 }
2080
2081                 protected virtual void OnValidating(System.ComponentModel.CancelEventArgs e) {
2082                         if (Validating!=null) Validating(this, e);
2083                 }
2084
2085                 protected virtual void OnVisibleChanged(EventArgs e) {
2086                         if (!is_visible) {
2087                                 if (dc_mem!=null) {
2088                                         dc_mem.Dispose ();
2089                                         bmp_mem=null;
2090                                 }
2091
2092                                 if (bmp_mem!=null) {
2093                                         bmp_mem.Dispose();
2094                                         bmp_mem=null;
2095                                 }
2096                         } else {
2097                                 if (!is_disposed) {
2098                                         if (!this.IsHandleCreated) {
2099                                                 this.CreateHandle();
2100                                         }
2101                                         PerformLayout();
2102                                 }
2103                         }
2104                         
2105                         if (VisibleChanged!=null) VisibleChanged(this, e);
2106
2107                         // We need to tell our kids
2108                         for (int i=0; i<child_controls.Count; i++) {
2109                                 child_controls[i].OnParentVisibleChanged(e);
2110                         }
2111                 }
2112                 #endregion      // OnXXX methods
2113
2114                 #region Events
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
2173                 
2174                 #region Private Methods
2175                 internal static int LowOrder (int param) 
2176                 {
2177                         return (param & 0xffff);
2178                 }
2179
2180                 internal static int HighOrder (int param) 
2181                 {
2182                         return (param >> 16);
2183                 }
2184                 
2185                 internal static MouseButtons FromParamToMouseButtons (int param) 
2186                 {               
2187                         MouseButtons buttons = MouseButtons.None;
2188                                         
2189                         if ((param & (int) MsgButtons.MK_LBUTTON) != 0)
2190                                 buttons |= MouseButtons.Left;
2191                         
2192                         if ((param & (int) MsgButtons.MK_MBUTTON) != 0)
2193                                 buttons |= MouseButtons.Middle;
2194                                 
2195                         if ((param & (int) MsgButtons.MK_RBUTTON) != 0)
2196                                 buttons |= MouseButtons.Right;          
2197                                 
2198                         return buttons;
2199
2200                 }
2201                 #endregion      
2202         }
2203 }