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