2 // System.Windows.Forms.Control.cs
5 // stubbed out by Jaak Simm (jaaksimm@firm.ee)
6 // Dennis Hayes (dennish@rayetk.com)
7 // WINELib implementation started by John Sohn (jsohn@columbus.rr.com)
8 // Alexandre Pigolkine (pigolkine@gmx.de)
9 // Aleksey Ryabchuk (ryabchuk@yahoo.com)
11 // (C) Ximian, Inc., 2002
14 using System.ComponentModel;
16 using System.Collections;
17 using System.Threading;
19 using System.Runtime.InteropServices;
20 using System.Collections.Specialized;
22 namespace System.Windows.Forms {
24 public class Control : Component , ISynchronizeInvoke, IWin32Window {
28 // Helper NativeWindow class to dispatch messages back
29 // to the Control class
31 protected class ControlNativeWindow : NativeWindow {
33 private Control control;
35 public ControlNativeWindow (Control control) : base ()
37 this.control = control;
40 protected override void WndProc (ref Message m)
42 //Console.WriteLine ("Control WndProc Message HWnd {0}, Msg {1}", m.HWnd, m.Msg);
43 // Do not call default WndProc here
44 // let the control decide what to do
45 // base.WndProc (ref m);
46 control.WndProc (ref m);
50 // FIXME: not sure if dervied classes should have access
51 protected ControlNativeWindow window;
52 private ControlCollection childControls;
53 private Control parent;
54 static private Hashtable controlsCollection = new Hashtable ();
55 static private NativeWindow parkingWindow = null;
56 private static bool classRegistered = false;
61 // it seems these are stored in case the window is not created,
62 // corresponding properties (below) need to check if window
63 // is created or not and react accordingly
65 string accessibleDefaultActionDescription;
66 string accessibleDescription;
67 string accessibleName;
68 AccessibleRole accessibleRole;
71 protected Color backColor;
72 Image backgroundImage;
73 //BindingContext bindingContext;
77 bool causesValidation;
78 ContextMenu contextMenu;
82 protected Color foreColor;
85 // Point location; // using bounds to store location
88 RightToLeft rightToLeft;
90 protected string text;
91 protected bool visible;
92 protected ControlStyles controlStyles_;
99 private static readonly int LAYOUT_SUSPENDED = BitVector32.CreateMask ();
100 private static readonly int LAYOUT_PENDING = BitVector32.CreateMask (LAYOUT_SUSPENDED);
101 private static readonly int DISPOSED = BitVector32.CreateMask (LAYOUT_PENDING);
102 private static readonly int RECREATING_HANDLE= BitVector32.CreateMask (DISPOSED);
103 private static readonly int CREATED = BitVector32.CreateMask (RECREATING_HANDLE);
104 private static readonly int DISPOSING = BitVector32.CreateMask (CREATED);
105 private static readonly int TOPLEVEL = BitVector32.CreateMask (DISPOSING);
108 protected bool mouseIsInside_;
110 // BeginInvoke () etc. helpers
111 static int InvokeMessage = Win32.RegisterWindowMessage ("mono_control_invoke_helper");
113 // CHECKME: This variable is used to determine whether current thread
114 // was used to create Control Handle. It take some space but saves a call
115 // to unmanaged code in ISynchronizeInvoke.IsInvokeRequired.
116 private int CreatorThreadId_ = 0;
118 private Queue InvokeQueue_ = new Queue ();
120 internal class ControlInvokeHelper : IAsyncResult {
121 private Delegate Method_ = null;
122 private object[] MethodArgs_ = null;
123 private object MethodResult_ = null;
124 private ManualResetEvent AsyncWaitHandle_ = new ManualResetEvent (false);
125 private bool CompletedSynchronously_ = false;
126 private bool IsCompleted_ = false;
128 public ControlInvokeHelper (Delegate method, object[] args) {
133 // IAsyncResult interface
134 object IAsyncResult.AsyncState {
136 if (MethodArgs_ != null && MethodArgs_.Length != 0)
137 return MethodArgs_[MethodArgs_.Length - 1];
143 WaitHandle IAsyncResult.AsyncWaitHandle {
145 return AsyncWaitHandle_;
149 bool IAsyncResult.CompletedSynchronously {
151 return CompletedSynchronously_;
155 bool IAsyncResult.IsCompleted {
161 internal bool CompletedSynchronously {
163 CompletedSynchronously_ = value;
167 internal object MethodResult {
169 return MethodResult_;
173 internal void ExecuteMethod () {
174 object result = Method_.DynamicInvoke (MethodArgs_);
176 MethodResult_ = result;
179 AsyncWaitHandle_.Set ();
183 // --- Constructors ---
185 //Compact Framework //only Control ()
188 childControls = CreateControlsInstance ();
190 statuses = new BitVector32 ();
192 accessibleDefaultActionDescription = null;
193 accessibleDescription = null;
194 accessibleName = null;
195 accessibleRole = AccessibleRole.Default;
197 anchor = AnchorStyles.Top | AnchorStyles.Left;
198 backColor = Control.DefaultBackColor;
199 backgroundImage = null;
200 bounds = new Rectangle ();
201 oldBounds = new Rectangle ();
202 // bindingContext = null;
203 causesValidation = true;
205 dock = DockStyle.None;
207 // font = Control.DefaultFont;
208 foreColor = Control.DefaultForeColor;
209 imeMode = ImeMode.Inherit;
210 isAccessible = false;
211 // location = new Point (0,0); should be from OS
214 rightToLeft = RightToLeft.Inherit;
221 oldBounds.Width = bounds.Width = DefaultSize.Width;
222 oldBounds.Height = bounds.Height= DefaultSize.Height;
223 clientWidth = DefaultSize.Width;
224 clientHeight = DefaultSize.Height;
226 mouseIsInside_ = false;
227 controlStyles_ = ControlStyles.Selectable | ControlStyles.StandardClick | ControlStyles.StandardDoubleClick;
228 // Do not create Handle here, only in CreateHandle
229 // CreateHandle ();//sets window handle. FIXME: No it does not
232 // according to docs, the constructors do not create
234 public Control (string text) : this ()
237 // SetWindowTextA (Handle, text);
240 public Control (Control parent, string text) : this (text)
243 // SetParent (Handle, parent.Handle);
246 public Control (string text, int left, int top,
247 int width, int height) : this (text)
253 //SetWindowPos (Handle, (IntPtr) 0, left, top,
254 // width, height, 0);
257 public Control (Control parent,string text,int left, int top,
258 int width,int height) : this (parent, text)
264 // SetWindowPos (Handle, (IntPtr) 0, left, top,
265 // width, height, 0);
268 // for internal use only, create a control class
269 // for an existing, created HWND
270 private Control (IntPtr existingHandle)
272 window = (ControlNativeWindow) NativeWindow.FromHandle (
276 // --- Properties ---
277 // Properties only supporting .NET framework, not stubbed out:
278 // - protected bool RenderRightToLeft {get;}
279 // - public IWindowTarget WindowTarget {get; set;}
281 //public AccessibleObject AccessibilityObject {
283 // throw new NotImplementedException ();
287 public string AccessibleDefaultActionDescription {
289 return accessibleDefaultActionDescription;
292 accessibleDefaultActionDescription = value;
296 public string AccessibleDescription {
298 return accessibleDescription;
301 accessibleDescription=value;
305 public string AccessibleName {
307 return accessibleName;
310 accessibleName=value;
314 public AccessibleRole AccessibleRole {
316 return accessibleRole;
319 accessibleRole=value;
323 public virtual bool AllowDrop {
332 public virtual AnchorStyles Anchor {
337 if (anchor != value){
339 if (anchor != (AnchorStyles.Left | AnchorStyles.Top))
340 Dock = DockStyle.None;
346 public virtual Color BackColor {
351 if (backColor != value) {
353 OnBackColorChanged (new EventArgs ());
358 public virtual Image BackgroundImage {
360 return backgroundImage;
363 backgroundImage = value;
364 // FIXME: force redraw
369 public virtual BindingContext BindingContext {
371 //return bindingContext;
372 throw new NotImplementedException ();
375 //bindingContext=value;
376 throw new NotImplementedException ();
388 public Rectangle Bounds {
393 SetBounds (value.Left, value.Top, value.Width, value.Height);
397 public bool CanFocus {
399 if (IsHandleCreated && Visible && Enabled)
406 public bool CanSelect {
408 if (!GetStyle (ControlStyles.Selectable))
414 Control parent = Parent;
415 while (parent != null){
416 if (!parent.Visible || !parent.Enabled)
418 parent = parent.Parent;
426 public bool Capture {
428 if (IsHandleCreated) {
429 IntPtr captured = Win32.GetCapture ();
430 if (Handle == captured)
436 if (IsHandleCreated) {
438 Win32.SetCapture (Handle);
440 IntPtr captured = Win32.GetCapture ();
442 // if this window is in capture state
444 if (Handle == captured)
445 Win32.ReleaseCapture ();
451 public bool CausesValidation {
453 return causesValidation;
456 causesValidation=value;
461 public Rectangle ClientRectangle {
463 return new Rectangle (0, 0, ClientSize.Width, ClientSize.Height);
470 public Size ClientSize {
472 return new Size (clientWidth, clientHeight);
475 SetClientSizeCore (value.Width, value.Height);
480 public string CompanyName {
482 //Better than throwing an execption
483 return "Company Name";
487 public bool ContainsFocus {
489 if (IsHandleCreated) {
490 if (Focused) return true;
491 foreach (Control ctr in Controls) {
492 if (ctr.ContainsFocus) return true;
501 public virtual ContextMenu ContextMenu {
506 if (contextMenu != value){
508 OnContextMenuChanged (EventArgs.Empty);
513 public ControlCollection Controls {
514 get { return childControls; }
517 public bool Created {
518 get { return statuses[ CREATED ]; }
521 protected virtual CreateParams CreateParams {
523 CreateParams createParams = new CreateParams ();
524 createParams.Caption = Text;
525 createParams.X = Left;
526 createParams.Y = Top;
527 createParams.Width = Width;
528 createParams.Height = Height;
529 createParams.ClassStyle = 0;
530 createParams.ExStyle = 0;
531 createParams.Param = 0;
534 createParams.Parent = parent.Handle;
536 createParams.Parent = ParkingWindowHandle;
538 createParams.Style = (int) WindowStyles.WS_OVERLAPPED;
540 createParams.Style |= (int) WindowStyles.WS_VISIBLE;
547 internal protected IntPtr ControlRealWndProc = IntPtr.Zero;
548 internal protected bool SubClassWndProc_ = false;
550 // This function lets Windows or/and default Windows control process message
551 // Classes have to call it if they do not handle message in WndProc or
552 // default handling is needed.
553 protected void CallControlWndProc (ref Message msg) {
554 if (ControlRealWndProc != IntPtr.Zero) {
555 msg.Result = (IntPtr)Win32.CallWindowProc (ControlRealWndProc, msg.HWnd, (int)msg.Msg, msg.WParam.ToInt32 (), msg.LParam.ToInt32 ());
558 DefWndProc (ref msg);
562 // Subclass only native Windows controls. Those classes have to set SubClassWndProc_ to true in contructor
563 private void SubclassWindow () {
564 if (IsHandleCreated && SubClassWndProc_) {
565 ControlRealWndProc = Win32.SetWindowLong (Handle, GetWindowLongFlag.GWL_WNDPROC, NativeWindow.GetWindowProc ());
569 private void UnsubclassWindow () {
570 if (IsHandleCreated) {
571 Win32.SetWindowLong (Handle, GetWindowLongFlag.GWL_WNDPROC, ControlRealWndProc.ToInt32 ());
575 protected virtual void OnWmCommand (ref Message m) {
576 if (m.LParam.ToInt32 () != 0) {
577 if (m.LParam != Handle) {
578 // Control notification
579 System.Console.WriteLine ("Control notification Code {0} Id = Hwnd {1}", m.HiWordWParam, m.LParam.ToInt32 ());
580 Control.ReflectMessage (m.LParam, ref m);
583 // Unhandled Control reflection
584 // Derived class didn't handle WM_COMMAND or called base.WndProc in WM_COMMAND handler
585 // CHECKME: Shall we notify user in debug build, throw an exception or just ignore this case ?
591 public virtual Cursor Cursor {
594 return Cursors.Default;
597 set { cursor = value;}
602 // waiting for BindingContext; should be stubbed now
603 public ControlBindingsCollection DataBindings {
605 throw new NotImplementedException ();
609 public static Color DefaultBackColor {
611 // FIXME: use GetSystemMetrics?
612 return SystemColors.Control;
613 //throw new NotImplementedException ();
618 // FIXME: use GetSystemMetrics?
619 public static Font DefaultFont {
620 // FIXME: get current system font from GenericSansSerif
621 // call ArgumentException not called
623 // throw new NotImplementedException ();
624 // return (FontFamily.GenericSansSerif);
625 return Font.FromHfont (Win32.GetStockObject (GSO_.DEFAULT_GUI_FONT));
629 public static Color DefaultForeColor {
631 return SystemColors.ControlText;
635 protected virtual ImeMode DefaultImeMode {
637 return ImeMode.Inherit;
641 protected virtual Size DefaultSize {
643 //Default label size, this should be correct.
644 return new Size (100,23);
648 public virtual Rectangle DisplayRectangle {
650 return ClientRectangle;
654 public bool Disposing {
655 get { return statuses [ DISPOSING ]; }
658 public virtual DockStyle Dock {
665 if (dock != DockStyle.None)
666 Anchor = (AnchorStyles.Left | AnchorStyles.Top);
667 OnDockChanged (EventArgs.Empty);
673 public virtual bool Enabled {
676 //return Win32.IsWindowEnabled (Handle);
679 if (enabled != value) {
680 Win32.EnableWindow (Handle, value);
682 // FIXME: Disable/enable all children here
689 public virtual bool Focused {
691 if (IsHandleCreated) {
692 IntPtr focusedWindow = Win32.GetFocus ();
693 if (focusedWindow == Handle)
701 public virtual Font Font {
704 if (result == null) {
705 if (Parent != null) {
706 result = Parent.Font;
708 if (result == null) {
709 result = Control.DefaultFont;
716 if (IsHandleCreated) {
717 Win32.SendMessage (Handle, Msg.WM_SETFONT, Font.ToHfont ().ToInt32 (), 1);
723 protected int FontHeight {
725 throw new NotImplementedException ();
728 throw new NotImplementedException ();
733 public virtual Color ForeColor {
742 public bool HasChildren {
744 if (childControls.Count >0)
753 return bounds.Height;
756 SetBounds (bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height);
760 public ImeMode ImeMode {
770 public bool IsAccessible {
774 } // default is false
780 public bool IsDisposed {
781 get { return statuses [ DISPOSED ]; }
784 public bool IsHandleCreated {
785 get { return window != null && window.Handle != IntPtr.Zero; }
794 SetBounds (value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X);
799 public Point Location {
802 return new Point (Top, Left);
805 SetBounds (value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location);
809 public static Keys ModifierKeys {
811 Keys keys = Keys.None;
813 if ( (Win32.GetKeyState ( (int) VirtualKeys.VK_SHIFT)& 0x8000)== 0x8000)
815 if ( (Win32.GetKeyState ( (int) VirtualKeys.VK_MENU)& 0x8000) == 0x8000)
817 if ( (Win32.GetKeyState ( (int) VirtualKeys.VK_CONTROL) & 0x8000) == 0x8000)
818 keys |= Keys.Control;
826 public static MouseButtons MouseButtons {
828 // FIXME: use GetAsycKeyState?
829 throw new NotImplementedException ();
834 public static Point MousePosition {
836 POINT point = new POINT ();
837 Win32.GetCursorPos (ref point);
838 return new Point ( (int) point.x, (int) point.y);
853 public Control Parent {
856 //IntPtr parent = GetParent (Handle);
857 //return FromHandle (parent);
860 if (parent != value) {
863 // add ourself to the parents control
864 if (!parent.Controls.Contains (this))
865 parent.Controls.Add (this);
867 // FIXME: Is this logic correct ?
868 if (BackColor == DefaultBackColor) {
869 if (parent.BackColor != BackColor)
870 OnParentBackColorChanged (new EventArgs ());
873 if (IsHandleCreated) {
874 Win32.SetParent (Handle, value.Handle);
877 else if (parent.IsHandleCreated){
878 // CHECKME: Now control is responsible for creating his window
879 // when added to Form, may be things must be reversed.
887 protected static IntPtr ParkingWindowHandle {
889 if (parkingWindow == null)
890 parkingWindow = new NativeWindow ();
892 if (parkingWindow.Handle == IntPtr.Zero){
893 CreateParams pars = new CreateParams ();
894 pars.ClassName = "mono_native_window";
895 pars.Style = (int) WindowStyles.WS_OVERLAPPED;
896 parkingWindow.CreateHandle (pars);
899 return parkingWindow.Handle;
903 protected static void RegisterDefaultWindowClass ()
905 if (!classRegistered){
906 WNDCLASS wndClass = new WNDCLASS ();
908 wndClass.style = (int) (CS_.CS_OWNDC);
909 wndClass.lpfnWndProc = NativeWindow.GetWindowProc ();
910 wndClass.cbClsExtra = 0;
911 wndClass.cbWndExtra = 0;
912 wndClass.hInstance = (IntPtr)0;
913 wndClass.hIcon = (IntPtr)0;
914 wndClass.hCursor = Win32.LoadCursor ( (IntPtr)0, LC_.IDC_ARROW);
915 wndClass.hbrBackground = (IntPtr) ( (int)GetSysColorIndex.COLOR_BTNFACE + 1);
916 wndClass.lpszMenuName = "";
917 wndClass.lpszClassName = Win32.DEFAULT_WINDOW_CLASS;
919 if (Win32.RegisterClass (ref wndClass) != 0)
920 classRegistered = true;
925 public string ProductName {
928 return "Product Name";
933 public string ProductVersion {
936 return "Product Version";
941 public bool RecreatingHandle {
943 return statuses [ RECREATING_HANDLE ] ;
947 public Region Region {
957 protected bool ResizeRedraw {
958 get { return GetStyle (ControlStyles.ResizeRedraw); }
959 set { SetStyle (ControlStyles.ResizeRedraw, value); }
970 public virtual RightToLeft RightToLeft {
981 protected virtual bool ShowFocusCues {
983 throw new NotImplementedException ();
988 protected bool ShowKeyboardCues {
990 throw new NotImplementedException ();
995 public override ISite Site {
997 throw new NotImplementedException ();
1000 throw new NotImplementedException ();
1007 return new Size (Width, Height);
1010 SetBounds (bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size);
1014 internal int tabindex;//for debug/test only. remove
1016 public int TabIndex {
1025 public bool TabStop {
1046 public virtual string Text {
1048 // CHECKME: if we really need to provide back current text of real window
1049 // or just our copy in text member.
1050 if (IsHandleCreated){
1051 int len = Win32.GetWindowTextLengthA (Handle);
1052 // FIXME: len is doubled due to some strange behaviour. (of GetWindowText function ?)
1053 // instead of 10 characters we can get only 9, even if sb.Capacity is 10.
1054 StringBuilder sb = new StringBuilder (len * 2 /*Win32.GetWindowTextLengthA (Handle)*/);
1055 Win32.GetWindowText (Handle, sb, sb.Capacity);
1056 text = sb.ToString ();
1064 if (IsHandleCreated)
1065 Win32.SetWindowTextA (Handle, value);
1067 OnTextChanged (EventArgs.Empty);
1078 SetBounds (bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y);
1083 public Control TopLevelControl {
1085 throw new NotImplementedException ();
1089 public bool Visible {
1090 get { return visible; }
1092 SetVisibleCore (value);
1099 return bounds.Width;
1102 SetBounds (bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width);
1107 /// internal .NET framework supporting methods, not stubbed out:
1108 /// - protected virtual void NotifyInvalidate (Rectangle invalidatedArea)
1109 /// - protected void RaiseDragEvent (object key,DragEventArgs e);
1110 /// - protected void RaiseKeyEvent (object key,KeyEventArgs e);
1111 /// - protected void RaiseMouseEvent (object key,MouseEventArgs e);
1112 /// - protected void RaisePaintEvent (object key,PaintEventArgs e);
1113 /// - protected void ResetMouseEventArgs ();
1116 protected void AccessibilityNotifyClients (
1117 AccessibleEvents accEvent,int childID)
1119 throw new NotImplementedException ();
1123 public void BringToFront ()
1125 if (IsHandleCreated)
1126 Win32.SetWindowPos (Handle, SetWindowPosZOrder.HWND_TOP, 0, 0, 0, 0,
1127 SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE);
1130 public bool Contains (Control ctl)
1132 return childControls.Contains (ctl);
1135 public void CreateControl ()
1140 statuses [ CREATED ] = true;
1145 protected virtual AccessibleObject CreateAccessibilityInstance () {
1146 throw new NotImplementedException ();
1149 protected virtual ControlCollection CreateControlsInstance ()
1151 return new ControlCollection (this);
1156 public Graphics CreateGraphics ()
1158 return Graphics.FromHwnd (Handle);
1161 protected virtual void CreateHandle ()
1164 throw new ObjectDisposedException (Name);
1166 if (IsHandleCreated)
1170 window = new ControlNativeWindow (this);
1172 CreateParams createParams = CreateParams;
1174 createParams.Style |= (int)WindowStyles.WS_DISABLED;
1176 window.CreateHandle (createParams);
1178 if (window.Handle != IntPtr.Zero) {
1179 if (!controlsCollection.Contains (window.Handle))
1180 controlsCollection.Add (window.Handle, this);
1184 CreatorThreadId_ = Win32.GetCurrentThreadId ();
1186 OnHandleCreated (EventArgs.Empty);
1190 protected virtual void DefWndProc (ref Message m)
1192 window.DefWndProc (ref m);
1195 protected virtual void DestroyHandle ()
1197 if (IsHandleCreated){
1198 if (Handle != IntPtr.Zero) {
1199 controlsCollection.Remove (Handle);
1201 if (window != null) {
1202 window.DestroyHandle ();
1207 protected override void Dispose (bool disposing)
1210 statuses [ DISPOSING ] = true;
1215 // close/free unmanaged resources
1218 base.Dispose (disposing);
1220 statuses [ DISPOSED ] = true;
1225 public DragDropEffects DoDragDrop (
1226 object data, DragDropEffects allowedEffects)
1228 throw new NotImplementedException ();
1231 //public object EndInvoke (IAsyncResult asyncResult):
1232 //look under ISynchronizeInvoke methods
1235 public Form FindForm ()
1237 throw new NotImplementedException ();
1241 public bool Focus ()
1243 if (Win32.SetFocus (Handle) != (IntPtr) 0)
1249 public static Control FromChildHandle (IntPtr handle)
1251 Control control = null;
1252 IntPtr controlHwnd = handle;
1253 while (controlHwnd != IntPtr.Zero) {
1254 control = controlsCollection[controlHwnd] as Control;
1255 if (control != null) break;
1256 controlHwnd = Win32.GetParent (controlHwnd);
1261 public static Control FromHandle (IntPtr handle)
1263 // FIXME: Here we have to check, whether control already exists
1264 //Control control = new Control (handle);
1265 Control control = controlsCollection[handle] as Control;
1270 public Control GetChildAtPoint (Point pt)
1272 throw new NotImplementedException ();
1276 //public IContainerControl GetContainerControl ()
1278 // throw new NotImplementedException ();
1281 internal Control getNextFocusedControlCore (Control parent, Control ctl, bool forward)
1283 while (parent.Parent != null)
1284 parent = parent.Parent;
1286 Control next = parent.GetNextControl (ctl, forward);
1287 while (next != null){
1288 if (next.TabStop && next.CanFocus)
1290 next = parent.GetNextControl (next, forward);
1295 internal Control getNextFocusedControl (Control parent, bool forward)
1297 Control next = getNextFocusedControlCore (parent, FocusedControl, forward);
1299 next = getNextFocusedControlCore (parent, null, forward);
1304 public Control GetNextControl (Control ctl, bool forward)
1306 Control next = null;
1309 next = Controls.GetFirstControl (forward);
1312 next = getNextControlForward (ctl);
1314 next = getNextControlBackward (ctl);
1319 private Control getNextControlForward (Control ctl)
1321 if (ctl.Controls.Count != 0)
1322 return ctl.Controls.GetFirstControl (true);
1324 Control parent = ctl.Parent;
1325 if (parent != null){
1326 while (parent != null){
1327 Control next = parent.Controls.GetNextControl (ctl, true);
1331 parent = parent.Parent;
1336 return Controls.GetFirstControl (true);
1339 private Control getNextControlBackward (Control ctl)
1341 Control parent = ctl.Parent;
1342 if (parent != null){
1343 Control next = parent.Controls.GetNextControl (ctl, false);
1345 if (next.Controls.Count > 0)
1346 return next.Controls.GetFirstControl (false);
1353 return Controls.GetFirstControl (false);
1357 protected bool GetStyle (ControlStyles flag)
1359 return (controlStyles_ & flag) != 0;
1363 protected bool GetTopLevel ()
1365 return statuses [ TOPLEVEL ];
1374 protected virtual void InitLayout ()
1380 public void Invalidate ()
1382 if (IsHandleCreated) {
1383 Win32.InvalidateRect (Handle, IntPtr.Zero, 1);
1387 public void Invalidate (bool invalidateChildren)
1390 if (invalidateChildren){
1391 foreach (Control child in Controls)
1392 child.Invalidate (invalidateChildren);
1396 // tries to find appropriate owner for modal form
1397 internal static Control getOwnerWindow (Control skip)
1399 // temporary solution
1400 IEnumerator cw = controlsCollection.GetEnumerator ();
1402 while (cw.MoveNext ()){
1403 Control c = ( (DictionaryEntry) cw.Current).Value as Control;
1404 if (c != null && c != skip){
1405 IntPtr parent = Win32.GetParent (c.Handle);
1406 IntPtr owner = Win32.GetWindow (c.Handle, (uint) GetWindowConstants.GW_OWNER);
1407 if (parent == IntPtr.Zero && owner == IntPtr.Zero)
1415 public void Invalidate (Rectangle rc)
1417 if (IsHandleCreated) {
1418 RECT rect = new RECT ();
1419 rect.left = rc.Left;
1421 rect.right = rc.Right;
1422 rect.bottom = rc.Bottom;
1423 Win32.InvalidateRect (Handle, ref rect, true);
1428 public void Invalidate (Region region)
1434 public void Invalidate (Rectangle rc, bool invalidateChildren)
1440 public void Invalidate (Region region,bool invalidateChildren)
1446 protected void InvokeGotFocus (Control toInvoke, EventArgs e)
1452 protected void InvokeLostFocus (Control toInvoke, EventArgs e)
1458 protected void InvokeOnClick (Control toInvoke, EventArgs e)
1464 protected void InvokePaint (Control c, PaintEventArgs e)
1470 protected void InvokePaintBackground (
1471 Control c,PaintEventArgs e)
1477 protected virtual bool IsInputChar (char charCode)
1483 protected virtual bool IsInputKey (Keys keyData)
1488 public static bool IsMnemonic (char charCode, string text)
1492 return text.IndexOf ("&" + charCode)> 0;
1496 // methods used with events:
1497 protected virtual void OnBackColorChanged (EventArgs e)
1499 if (BackColorChanged != null)
1500 BackColorChanged (this, e);
1502 foreach (Control ctl in Controls) {
1503 ctl.OnParentBackColorChanged (e);
1507 protected virtual void OnBackgroundImageChanged (EventArgs e)
1509 if (BackgroundImageChanged != null)
1510 BackgroundImageChanged (this, e);
1513 protected virtual void OnBindingContextChanged (EventArgs e)
1515 if (BindingContextChanged != null)
1516 BindingContextChanged (this, e);
1519 protected virtual void OnCausesValidationChanged (EventArgs e)
1521 if (CausesValidationChanged != null)
1522 CausesValidationChanged (this, e);
1525 protected virtual void OnChangeUICues (UICuesEventArgs e)
1527 if (ChangeUICues != null)
1528 ChangeUICues (this, e);
1532 protected virtual void OnClick (EventArgs e)
1539 protected virtual void OnContextMenuChanged (EventArgs e)
1541 if (ContextMenuChanged != null)
1542 ContextMenuChanged (this, e);
1545 protected virtual void OnControlAdded (ControlEventArgs e)
1548 e.Control.CreateControl ();
1550 e.Control.Visible = Visible;
1552 if (ControlAdded != null)
1553 ControlAdded (this, e);
1556 protected virtual void OnControlRemoved (ControlEventArgs e)
1558 if (ControlRemoved != null)
1559 ControlRemoved (this, e);
1562 protected virtual void OnCreateControl ()
1565 // create all child windows
1566 IEnumerator cw = childControls.GetEnumerator ();
1568 while (cw.MoveNext ()) {
1569 Control control = (Control) cw.Current;
1570 control.CreateControl ();
1575 protected virtual void OnCursorChanged (EventArgs e)
1577 if (CursorChanged != null)
1578 CursorChanged (this, e);
1581 protected virtual void OnDockChanged (EventArgs e)
1583 // changing this property does not affect the control directly
1584 // so have its parent to calculate new layout
1586 Parent.PerformLayout (this, "Dock");
1587 if (DockChanged != null)
1588 DockChanged (this, e);
1591 protected virtual void OnDoubleClick (EventArgs e)
1593 if (DoubleClick != null)
1594 DoubleClick (this, e);
1597 protected virtual void OnDragDrop (DragEventArgs e)
1599 if (DragDrop != null)
1603 protected virtual void OnDragEnter (DragEventArgs e)
1605 if (DragEnter != null)
1606 DragEnter (this, e);
1609 protected virtual void OnDragLeave (EventArgs e)
1611 if (DragLeave != null)
1612 DragLeave (this, e);
1615 protected virtual void OnDragOver (DragEventArgs e)
1617 if (DragOver != null)
1622 protected virtual void OnEnabledChanged (EventArgs e)
1624 if (EnabledChanged != null)
1625 EnabledChanged (this, e);
1628 protected virtual void OnEnter (EventArgs e)
1634 protected virtual void OnFontChanged (EventArgs e)
1636 if (FontChanged != null)
1637 FontChanged (this, e);
1640 protected virtual void OnForeColorChanged (EventArgs e)
1642 if (ForeColorChanged != null)
1643 ForeColorChanged (this, e);
1646 protected virtual void OnGiveFeedback (GiveFeedbackEventArgs e)
1648 if (GiveFeedback != null)
1649 GiveFeedback (this, e);
1653 protected virtual void OnGotFocus (EventArgs e)
1655 if (GotFocus != null)
1659 protected virtual void OnHandleCreated (EventArgs e)
1661 //if (font != null) {
1662 // Win32.SendMessage (Handle, Msg.WM_SETFONT, font.ToHfont ().ToInt32 (), 0);
1664 Win32.SendMessage (Handle, Msg.WM_SETFONT, Font.ToHfont ().ToInt32 (), 0);
1665 Win32.SetWindowText (Handle, text);
1667 if (HandleCreated != null)
1668 HandleCreated (this, e);
1672 protected virtual void OnHandleDestroyed (EventArgs e)
1674 if (Handle != IntPtr.Zero) {
1675 controlsCollection.Remove (Handle);
1678 if (HandleDestroyed != null) {
1679 HandleDestroyed (this, e);
1683 protected virtual void OnHelpRequested (HelpEventArgs e)
1685 if (HelpRequested != null)
1686 HelpRequested (this, e);
1689 protected virtual void OnImeModeChanged (EventArgs e)
1691 if (ImeModeChanged != null)
1692 ImeModeChanged (this, e);
1695 protected virtual void OnInvalidated (InvalidateEventArgs e)
1697 if (Invalidated != null)
1698 Invalidated (this, e);
1702 protected virtual void OnKeyDown (KeyEventArgs e)
1704 if (KeyDown != null)
1709 protected virtual void OnKeyPress (KeyPressEventArgs e)
1711 if (KeyPress != null)
1716 protected virtual void OnKeyUp (KeyEventArgs e)
1723 protected virtual void OnLayout (LayoutEventArgs e)
1725 DoDockAndAnchorLayout (e);
1730 protected virtual void OnLeave (EventArgs e)
1736 protected virtual void OnLocationChanged (EventArgs e)
1738 if (LocationChanged != null)
1739 LocationChanged (this, e);
1743 protected virtual void OnLostFocus (EventArgs e)
1745 if (LostFocus != null)
1746 LostFocus (this, e);
1750 protected virtual void OnMouseDown (MouseEventArgs e)
1752 if (MouseDown != null)
1753 MouseDown (this, e);
1756 protected virtual void OnMouseEnter (EventArgs e)
1758 //System.Console.WriteLine ("OnMouseEnter");
1759 if (MouseEnter != null)
1760 MouseEnter (this, e);
1763 protected virtual void OnMouseHover (EventArgs e)
1765 if (MouseHover != null)
1766 MouseHover (this, e);
1769 protected virtual void OnMouseLeave (EventArgs e)
1771 //System.Console.WriteLine ("OnMouseLeave");
1773 mouseIsInside_ = false;
1774 if (MouseLeave != null)
1775 MouseLeave (this, e);
1779 protected virtual void OnMouseMove (MouseEventArgs e)
1781 // If enter and mouse pressed - do not process
1782 if ( ( (e.Button & MouseButtons.Left) != 0) && !mouseIsInside_) return;
1784 if (!mouseIsInside_) {
1785 TRACKMOUSEEVENT tme = new TRACKMOUSEEVENT ();
1788 tme.dwFlags = (int)TrackerEventFlags.TME_LEAVE;
1789 tme.dwHoverTime = 0;
1791 bool result = Win32.TrackMouseEvent (ref tme);
1793 System.Console.WriteLine ("{0}",Win32.FormatMessage (Win32.GetLastError ()));
1797 POINT pt = new POINT ();
1800 Win32.ClientToScreen (Handle, ref pt);
1801 IntPtr wndUnderMouse = Win32.WindowFromPoint (pt);
1803 if (wndUnderMouse != Handle) {
1804 // we are outside of the window
1805 if (mouseIsInside_) {
1806 OnMouseLeave (new EventArgs ());
1807 mouseIsInside_ = false;
1811 if (!mouseIsInside_) {
1812 mouseIsInside_ = true;
1813 OnMouseEnter (new EventArgs ());
1816 if (MouseMove != null)
1817 MouseMove (this, e);
1821 protected virtual void OnMouseUp (MouseEventArgs e)
1823 if (MouseUp != null)
1827 protected virtual void OnMouseWheel (MouseEventArgs e)
1829 if (MouseWheel != null)
1830 MouseWheel (this, e);
1833 protected virtual void OnMove (EventArgs e)
1839 protected virtual void OnNotifyMessage (Message m)
1845 protected virtual void OnPaint (PaintEventArgs e)
1852 protected virtual void OnPaintBackground (PaintEventArgs e)
1854 if (GetStyle (ControlStyles.UserPaint)) {
1855 Brush br = new SolidBrush (BackColor);
1856 e.Graphics.FillRectangle (br, e.ClipRectangle);
1861 protected virtual void OnParentBackColorChanged (EventArgs e)
1863 BackColor = Parent.BackColor;
1864 // FIXME: setting BackColor fires the BackColorChanged event,
1865 // so we do not need to call this here
1867 if (BackColorChanged != null)
1868 BackColorChanged (this, e);
1872 protected virtual void OnParentBackgroundImageChanged (
1875 if (BackgroundImageChanged != null)
1876 BackgroundImageChanged (this, e);
1879 protected virtual void OnParentBindingContextChanged (
1882 if (BindingContextChanged != null)
1883 BindingContextChanged (this, e);
1887 protected virtual void OnParentChanged (EventArgs e)
1889 if (ParentChanged != null)
1890 ParentChanged (this, e);
1893 protected virtual void OnParentEnabledChanged (EventArgs e)
1895 if (EnabledChanged != null)
1896 EnabledChanged (this, e);
1899 protected virtual void OnParentFontChanged (EventArgs e)
1901 if (FontChanged != null)
1902 FontChanged (this, e);
1905 protected virtual void OnParentForeColorChanged (EventArgs e)
1907 if (ForeColorChanged != null)
1908 ForeColorChanged (this, e);
1911 protected virtual void OnParentRightToLeftChanged (
1914 if (RightToLeftChanged != null)
1915 RightToLeftChanged (this, e);
1918 protected virtual void OnParentVisibleChanged (EventArgs e)
1920 if (VisibleChanged != null)
1921 VisibleChanged (this, e);
1924 protected virtual void OnQueryContinueDrag (
1925 QueryContinueDragEventArgs e)
1927 if (QueryContinueDrag != null)
1928 QueryContinueDrag (this, e);
1932 protected virtual void OnResize (EventArgs e)
1937 PerformLayout (this, "Bounds");
1940 protected virtual void OnRightToLeftChanged (EventArgs e)
1942 if (RightToLeftChanged != null)
1943 RightToLeftChanged (this, e);
1946 protected virtual void OnSizeChanged (EventArgs e)
1949 if (SizeChanged != null)
1950 SizeChanged (this, e);
1953 protected virtual void OnStyleChanged (EventArgs e)
1955 if (StyleChanged != null)
1956 StyleChanged (this, e);
1959 protected virtual void OnSystemColorsChanged (EventArgs e)
1961 if (SystemColorsChanged != null)
1962 SystemColorsChanged (this, e);
1965 protected virtual void OnTabIndexChanged (EventArgs e)
1967 if (TabIndexChanged != null)
1968 TabIndexChanged (this, e);
1971 protected virtual void OnTabStopChanged (EventArgs e)
1973 if (TabStopChanged != null)
1974 TabStopChanged (this, e);
1978 protected virtual void OnTextChanged (EventArgs e)
1980 if (TextChanged != null)
1981 TextChanged (this, e);
1984 //[MonoTODO] // this doesn't seem to be documented
1985 // protected virtual void OnTextAlignChanged (EventArgs e) {
1986 // TextAlignChanged (this, e);
1989 protected virtual void OnValidated (EventArgs e)
1991 if (Validated != null)
1992 Validated (this, e);
1996 // CancelEventArgs not ready
1997 //protected virtual void OnValidating (CancelEventArgs e)
1999 // throw new NotImplementedException ();
2003 protected virtual void OnVisibleChanged (EventArgs e)
2005 if (VisibleChanged != null)
2006 VisibleChanged (this, e);
2010 // --- end of methods for events ---
2014 public void PerformLayout ()
2016 PerformLayout (null, null);
2020 public void PerformLayout (Control affectedControl,
2021 string affectedProperty)
2023 if (!statuses [ LAYOUT_SUSPENDED ])
2024 OnLayout (new LayoutEventArgs (affectedControl, affectedProperty));
2026 statuses [ LAYOUT_PENDING ] = true;
2031 public Point PointToClient (Point p)
2033 throw new NotImplementedException ();
2038 public Point PointToScreen (Point p)
2040 throw new NotImplementedException ();
2044 public virtual bool PreProcessMessage (ref Message msg)
2046 if (msg.Msg == Msg.WM_KEYDOWN){
2047 Keys keyData = (Keys)msg.WParam.ToInt32 ();
2048 if (!ProcessCmdKey (ref msg, keyData)) {
2049 if (IsInputKey (keyData))
2052 return ProcessDialogKey (keyData);
2056 else if (msg.Msg == Msg.WM_CHAR){
2057 if (IsInputChar ( (char) msg.WParam))
2060 return ProcessDialogChar ( (char) msg.WParam);
2067 protected virtual bool ProcessCmdKey (ref Message msg,
2070 // do something with context menu
2073 return Parent.ProcessCmdKey (ref msg, keyData);
2078 protected virtual bool ProcessDialogChar (char charCode)
2081 return Parent.ProcessDialogChar (charCode);
2086 protected virtual bool ProcessDialogKey (Keys keyData)
2089 return Parent.ProcessDialogKey (keyData);
2094 protected virtual bool ProcessKeyEventArgs (ref Message m)
2096 bool handled = false;
2099 case Msg.WM_KEYDOWN:
2100 KeyEventArgs args_down = new KeyEventArgs ( (Keys)m.WParam.ToInt32 ());
2101 OnKeyDown (args_down);
2102 handled = args_down.Handled;
2105 KeyPressEventArgs args_press = new KeyPressEventArgs ( (char) m.WParam);
2106 OnKeyPress (args_press);
2107 handled = args_press.Handled;
2110 KeyEventArgs args_up = new KeyEventArgs ( (Keys)m.WParam.ToInt32 ());
2112 handled = args_up.Handled;
2120 protected internal virtual bool ProcessKeyMessage (ref Message m)
2122 if (Parent != null){
2123 if (!Parent.ProcessKeyPreview (ref m))
2124 return ProcessKeyEventArgs (ref m);
2130 protected virtual bool ProcessKeyPreview (ref Message m)
2133 return Parent.ProcessKeyPreview (ref m);
2137 // This default implementation of the ProcessMnemonic method simply
2138 // returns false to indicate that the control has no mnemonic.
2139 protected virtual bool ProcessMnemonic (char charCode)
2144 // used when properties/values of Control
2145 // are big enough to warrant recreating the HWND
2146 protected void RecreateHandle ()
2148 statuses [RECREATING_HANDLE] = true;
2149 if (IsHandleCreated) {
2155 IEnumerator cw = childControls.GetEnumerator ();
2156 while (cw.MoveNext ())
2157 ( (Control)cw.Current).RecreateHandle ();
2160 statuses [ RECREATING_HANDLE ] = false;
2165 public Rectangle RectangleToClient (Rectangle r)
2167 // FIXME: What to return if Handle is not created yet ?
2168 RECT rect = new RECT ();
2171 rect.right = r.Right;
2172 rect.bottom = r.Bottom;
2173 Win32.ScreenToClient (Handle,ref rect);
2174 return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
2179 public Rectangle RectangleToScreen (Rectangle r)
2181 // FIXME: What to return if Handle is not created yet ?
2182 RECT rect = new RECT ();
2185 rect.right = r.Right;
2186 rect.bottom = r.Bottom;
2187 Win32.ClientToScreen (Handle,ref rect);
2188 return new Rectangle (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
2192 protected static bool ReflectMessage (IntPtr hWnd, ref Message m) {
2193 bool result = false;
2194 Control cntrl = Control.FromHandle (hWnd);
2195 if (cntrl != null) {
2196 cntrl.WndProc (ref m);
2202 public virtual void Refresh ()
2204 Win32.UpdateWindow (Handle);
2208 public virtual void ResetBackColor ()
2214 public void ResetBindings ()
2220 public virtual void ResetFont ()
2226 public virtual void ResetForeColor ()
2232 public void ResetImeMode ()
2238 public virtual void ResetRightToLeft ()
2244 public virtual void ResetText ()
2250 public void ResumeLayout ()
2252 statuses [ LAYOUT_SUSPENDED ] = false;
2253 if (statuses [ LAYOUT_PENDING ]){
2255 statuses [ LAYOUT_PENDING ] = false;
2260 public void ResumeLayout (bool performLayout)
2262 statuses [ LAYOUT_SUSPENDED ] = false;
2263 if (performLayout && statuses [ LAYOUT_PENDING ]){
2265 statuses [ LAYOUT_PENDING ] = false;
2270 protected ContentAlignment RtlTranslateAlignment (
2271 ContentAlignment align)
2273 throw new NotImplementedException ();
2277 protected HorizontalAlignment RtlTranslateAlignment (
2278 HorizontalAlignment align)
2280 throw new NotImplementedException ();
2284 protected LeftRightAlignment RtlTranslateAlignment (
2285 LeftRightAlignment align)
2287 throw new NotImplementedException ();
2291 protected ContentAlignment RtlTranslateContent (
2292 ContentAlignment align)
2294 throw new NotImplementedException ();
2298 protected HorizontalAlignment RtlTranslateHorizontal (
2299 HorizontalAlignment align)
2301 throw new NotImplementedException ();
2305 protected LeftRightAlignment RtlTranslateLeftRight (
2306 LeftRightAlignment align)
2308 throw new NotImplementedException ();
2312 public void Scale (float ratio)
2314 Scale (ratio, ratio);
2318 public void Scale (float dx,float dy)
2322 IEnumerator cw = childControls.GetEnumerator ();
2323 while (cw.MoveNext ()){
2324 Control control = (Control) cw.Current;
2325 control.Scale (dx, dy);
2331 protected virtual void ScaleCore (float dx, float dy)
2333 Location = new Point ( (int) (Left * dx), (int) (Top * dy));
2334 ClientSize = new Size ( (int) (ClientSize.Width * dx),
2335 (int) (ClientSize.Height * dy));
2339 public void Select ()
2345 protected virtual void Select (bool directed,bool forward)
2351 public bool SelectNextControl (Control ctl, bool forward,
2353 bool nested, bool wrap)
2355 throw new NotImplementedException ();
2360 public void SendToBack ()
2366 public void SetBounds (int x, int y, int width, int height)
2368 SetBounds (x, y, width, height, BoundsSpecified.All);
2372 public void SetBounds (int x, int y, int width, int height, BoundsSpecified specified)
2374 SetBoundsCore (x, y, width, height, specified);
2378 protected virtual void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
2380 if ( (specified & BoundsSpecified.X) == 0) x = Left;
2381 if ( (specified & BoundsSpecified.Y) == 0) y = Top;
2382 if ( (specified & BoundsSpecified.Width) == 0) width = Width;
2383 if ( (specified & BoundsSpecified.Height) == 0) height = Height;
2385 if (IsHandleCreated){
2386 SetWindowPosFlags flags = SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_FRAMECHANGED | SetWindowPosFlags.SWP_DRAWFRAME;
2387 Win32.SetWindowPos (Handle, SetWindowPosZOrder.HWND_NOTOPMOST, x, y, width, height, flags);
2390 UpdateBounds (x, y, width, height);
2393 protected virtual bool MenuPresent {
2394 get { return false; }
2398 protected virtual void SetClientSizeCore (int x, int y)
2400 RECT rc = new RECT ();
2404 CreateParams pars = CreateParams;
2405 Win32.AdjustWindowRectEx (ref rc, pars.Style, MenuPresent ? 1 : 0, pars.ExStyle);
2407 Size = new Size (rc.right - rc.left, rc.bottom - rc.top);
2411 protected void SetStyle (ControlStyles flag, bool value)
2414 controlStyles_ |= flag;
2417 controlStyles_ &= ~flag;
2421 protected void SetTopLevel (bool value)
2424 // FIXME: verify on whether this is supposed
2425 // to activate/deactive the window
2426 Win32.SetWindowPos (Handle,
2427 SetWindowPosZOrder.HWND_NOTOPMOST,
2430 // FIXME: this does not make sense but
2431 // the docs say the window is hidden
2432 Win32.ShowWindow (Handle, ShowWindowStyles.SW_HIDE);
2434 if (GetTopLevel () != value && Parent != null)
2435 throw new ArgumentException ();
2437 statuses [ TOPLEVEL ] = value;
2441 protected virtual void SetVisibleCore (bool value)
2443 bool visibleChanged = (visible != value);
2448 OnVisibleChanged (EventArgs.Empty);
2450 if (IsHandleCreated){
2451 SetWindowPosFlags flags = value ? SetWindowPosFlags.SWP_SHOWWINDOW : SetWindowPosFlags.SWP_HIDEWINDOW;
2452 flags |= SetWindowPosFlags.SWP_NOZORDER | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE;
2453 Win32.SetWindowPos (Handle, 0, 0, 0, 0, 0, flags);
2456 foreach (Control c in Controls)
2465 public void SuspendLayout ()
2467 statuses [ LAYOUT_SUSPENDED ] = true;
2471 public void Update ()
2473 Win32.UpdateWindow (Handle);
2477 protected void UpdateBounds ()
2478 { // update control bounds with current size and position
2480 // currently, this function is called in responce to
2481 // window events, so I assume that all window handles
2483 RECT rect = new RECT ();
2484 Win32.GetWindowRect (Handle, ref rect);
2486 IntPtr parent = Win32.GetParent (Handle);
2487 if (parent != IntPtr.Zero){
2488 Win32.ScreenToClient (parent, ref rect);
2491 UpdateBounds (rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
2495 protected void UpdateBounds (int x, int y, int width, int height)
2497 int clWidth = width;
2498 int clHeight = height;
2500 CreateParams pars = CreateParams;
2501 // this check should be removed when all controls will use base
2502 // implementation of CreateParams
2504 RECT rc = new RECT ();
2508 Win32.AdjustWindowRectEx (ref rc, pars.Style, MenuPresent ? 1 : 0, pars.ExStyle);
2510 clWidth -= ( (rc.right - rc.left)- clWidth);
2511 clHeight -= ( (rc.bottom - rc.top)- clHeight);
2514 UpdateBounds (x , y, width, height, clWidth, clHeight);
2518 protected void UpdateBounds (
2519 int x, int y, int width, int height, int clientWidth,
2522 oldBounds.X = bounds.X;
2523 oldBounds.Y = bounds.Y;
2524 oldBounds.Width = bounds.Width;
2525 oldBounds.Height = bounds.Height;
2527 bool bLocationChanged = (bounds.X != x)|| (bounds.Y != y);
2531 bool bSizeChanged = (bounds.Width != width)|| (bounds.Height != height);
2532 bounds.Width = width;
2533 bounds.Height = height;
2535 this.clientWidth = clientWidth;
2536 this.clientHeight = clientHeight;
2538 if (bLocationChanged)
2539 OnLocationChanged (EventArgs.Empty);
2541 OnSizeChanged (EventArgs.Empty);
2545 protected void UpdateStyles ()
2551 protected void UpdateZOrder ()
2553 if (!IsHandleCreated || Parent == null)
2556 int position = Parent.Controls.GetChildIndex (this , false);
2561 // not in collection for some reason
2565 Control prev = Parent.Controls [ position - 1 ];
2566 if (prev.IsHandleCreated)
2567 Win32.SetWindowPos (Handle, prev.Handle, 0, 0, 0, 0, SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE);
2573 internal MouseEventArgs Msg2MouseEventArgs (ref Message msg) {
2574 MouseButtons mb = MouseButtons.None;
2575 KeyStatusFlags keyIndicator = (KeyStatusFlags)msg.WParam.ToInt32 ();
2576 if ( (keyIndicator & KeyStatusFlags.MK_LBUTTON) != 0) {
2577 mb |= MouseButtons.Left;
2579 if ( (keyIndicator & KeyStatusFlags.MK_RBUTTON) != 0) {
2580 mb |= MouseButtons.Right;
2582 if ( (keyIndicator & KeyStatusFlags.MK_MBUTTON) != 0) {
2583 mb |= MouseButtons.Middle;
2585 if ( (keyIndicator & KeyStatusFlags.MK_XBUTTON1) != 0) {
2586 mb |= MouseButtons.XButton1;
2588 if ( (keyIndicator & KeyStatusFlags.MK_XBUTTON2) != 0) {
2589 mb |= MouseButtons.XButton2;
2592 return new MouseEventArgs (mb, (mb != MouseButtons.None) ? 1: 0, msg.LoWordLParam, msg.HiWordLParam, 0);
2595 // WndProc - calls appriate On... function for the give
2598 // These On... functions do not appear to be called by
2601 // background color/image handled by WinForms
2602 // OnBackColorChanged
2603 // OnBackgroundImageChanged
2604 // OnForeColorChanged
2605 // OnPaintBackground
2607 // controls are added/removed by WinForms
2612 // OnBindingContextChanged
2613 // OnCausesValidationChanged
2615 // OnContextMenuChanged
2616 // OnRightToLeftChanged
2621 // OnTextAlignChanged
2624 // OnTabIndexChanged
2626 // OnLocationChanged
2628 // FIXME: may be one of the WM_IME_ messages
2631 // InvalidateRect is called by no Invalidate message exists
2634 // these messages ARE not called by WNDPROC according to docs
2635 // OnParentBackColorChanged
2636 // OnParentBackgroundImageChanged
2637 // OnParentBindingContextChanged
2639 // OnParentEnabledChanged
2640 // OnParentFontChanged
2641 // OnParentForeColorChanged
2642 // OnParentRightToLeftChanged
2643 // OnParentVisibleChanged
2645 protected virtual void WndProc (ref Message m)
2647 EventArgs eventArgs = new EventArgs ();
2648 // FIXME: paintEventArgs is not being created properly
2649 // FIXME: Graphics does not have a public constructor, you must get one from .NET
2650 //PaintEventArgs paintEventArgs = new PaintEventArgs (
2651 // new Graphics (), new Rectangle ());
2653 if ( (uint)m.Msg == Control.InvokeMessage) {
2654 ControlInvokeHelper helper = null;
2655 lock (InvokeQueue_.SyncRoot) {
2656 if (InvokeQueue_.Count > 0) {
2657 helper = (ControlInvokeHelper)InvokeQueue_.Dequeue ();
2660 if (helper != null) {
2661 helper.ExecuteMethod ();
2665 else if (m.Msg == Msg.WM_COMMAND) {
2667 m.Result = (IntPtr)1;
2668 OnWmCommand (ref m);
2669 if (m.Result != IntPtr.Zero) {
2670 CallControlWndProc (ref m);
2677 Console.WriteLine ("WM_CREATE");
2678 OnHandleCreated (eventArgs);
2680 case Msg.WM_LBUTTONDBLCLK:
2681 OnDoubleClick (eventArgs);
2682 CallControlWndProc (ref m);
2688 // OnQueryContinueDrag
2690 OnEnabledChanged (eventArgs);
2691 CallControlWndProc (ref m);
2693 case Msg.WM_SETFOCUS:
2694 OnEnter (eventArgs);
2695 OnGotFocus (eventArgs);
2696 CallControlWndProc (ref m);
2698 case Msg.WM_FONTCHANGE:
2699 OnFontChanged (eventArgs);
2700 CallControlWndProc (ref m);
2702 case Msg.WM_DESTROY:
2703 OnHandleDestroyed (eventArgs);
2704 CallControlWndProc (ref m);
2708 //OnHelpRequested (eventArgs);
2709 CallControlWndProc (ref m);
2711 case Msg.WM_KEYDOWN:
2712 if (!ProcessKeyMessage (ref m))
2713 CallControlWndProc (ref m);
2716 if (!ProcessKeyMessage (ref m))
2717 CallControlWndProc (ref m);
2720 if (!ProcessKeyMessage (ref m))
2721 CallControlWndProc (ref m);
2723 case Msg.WM_KILLFOCUS:
2724 OnLeave (eventArgs);
2725 OnLostFocus (eventArgs);
2726 CallControlWndProc (ref m);
2728 case Msg.WM_MOUSEACTIVATE:
2729 //OnMouseEnter (eventArgs);
2730 CallControlWndProc (ref m);
2732 case Msg.WM_MOUSEHOVER: // called by TrackMouseEvent
2733 OnMouseHover (eventArgs);
2734 CallControlWndProc (ref m);
2736 case Msg.WM_MOUSELEAVE: // called by TrackMouseEvent
2737 OnMouseLeave (eventArgs);
2738 CallControlWndProc (ref m);
2740 case Msg.WM_MOUSEMOVE:
2742 OnMouseMove (Msg2MouseEventArgs (ref m));
2743 CallControlWndProc (ref m);
2745 case Msg.WM_LBUTTONDOWN:
2747 //OnMouseDown (eventArgs);
2748 CallControlWndProc (ref m);
2750 case Msg.WM_LBUTTONUP:
2752 //OnMouseUp (eventArgs);
2753 CallControlWndProc (ref m);
2755 case Msg.WM_MOUSEWHEEL:
2757 //OnMouseWheel (eventArgs);
2758 CallControlWndProc (ref m);
2763 CallControlWndProc (ref m);
2766 NMHDR nmhdr = (NMHDR)Marshal.PtrToStructure (m.LParam,
2768 if (!Control.ReflectMessage (nmhdr.hwndFrom, ref m))
2769 CallControlWndProc (ref m);
2771 // FIXME: get NM_CLICKED msg from pnmh
2772 // OnClick (eventArgs);
2773 //OnNotifyMessage (eventArgs);
2775 case Msg.WM_ERASEBKGND:
2776 if (GetStyle (ControlStyles.UserPaint)){
2777 if (!GetStyle (ControlStyles.AllPaintingInWmPaint)) {
2778 PaintEventArgs eraseEventArgs = new PaintEventArgs (Graphics.FromHdc (m.WParam), new Rectangle (new Point (0,0),Size));
2779 OnPaintBackground (eraseEventArgs);
2780 eraseEventArgs.Dispose ();
2782 m.Result = (IntPtr)1;
2785 CallControlWndProc (ref m);
2789 if (!GetStyle (ControlStyles.UserPaint)) {
2790 CallControlWndProc (ref m);
2793 PAINTSTRUCT ps = new PAINTSTRUCT ();
2794 IntPtr hdc = Win32.BeginPaint (Handle, ref ps);
2795 Rectangle rc = new Rectangle ();
2796 rc.X = ps.rcPaint.left;
2797 rc.Y = ps.rcPaint.top;
2798 rc.Width = ps.rcPaint.right - ps.rcPaint.left;
2799 rc.Height = ps.rcPaint.bottom - ps.rcPaint.top;
2800 PaintEventArgs paintEventArgs = new PaintEventArgs (Graphics.FromHdc (hdc), rc);
2801 if (GetStyle (ControlStyles.AllPaintingInWmPaint)) {
2802 OnPaintBackground (paintEventArgs);
2804 OnPaint (paintEventArgs);
2805 paintEventArgs.Dispose ();
2806 Win32.EndPaint (Handle, ref ps);
2810 if (GetStyle (ControlStyles.ResizeRedraw)) {
2813 CallControlWndProc (ref m);
2815 case Msg.WM_WINDOWPOSCHANGED:
2817 CallControlWndProc (ref m);
2819 case Msg.WM_STYLECHANGED:
2820 OnStyleChanged (eventArgs);
2821 CallControlWndProc (ref m);
2823 case Msg.WM_SYSCOLORCHANGE:
2824 OnSystemColorsChanged (eventArgs);
2825 CallControlWndProc (ref m);
2827 case Msg.WM_SETTEXT:
2828 //OnTextChanged (eventArgs);
2829 CallControlWndProc (ref m);
2831 case Msg.WM_SETFONT:
2832 //OnTextChanged (eventArgs);
2833 CallControlWndProc (ref m);
2835 case Msg.WM_SHOWWINDOW:
2836 OnVisibleChanged (eventArgs);
2837 CallControlWndProc (ref m);
2839 case Msg.WM_CTLCOLORLISTBOX:
2840 Win32.SetTextColor (m.WParam, Win32.RGB (ForeColor));
2841 //Win32.SetBkColor (m.WParam, 0x00FF00);
2842 //m.Result = Win32.GetStockObject (GSO_.LTGRAY_BRUSH);
2844 case Msg.WM_MEASUREITEM:
2845 ReflectMessage (m.WParam, ref m);
2847 case Msg.WM_DRAWITEM:
2848 Control.ReflectMessage (m.WParam, ref m);
2850 case Msg.WM_HSCROLL:
2851 case Msg.WM_VSCROLL:
2852 if (!Control.ReflectMessage (m.LParam, ref m)) {
2853 CallControlWndProc (ref m);
2856 case Msg.WM_SETCURSOR:
2857 if (cursor != null && cursor.Handle != IntPtr.Zero){
2858 Win32.SetCursor (cursor.Handle);
2859 m.Result = (IntPtr)1;
2861 CallControlWndProc (ref m);
2863 case Msg.WM_RBUTTONDOWN:
2864 if (contextMenu != null){
2865 contextMenu.Show (this,
2866 new Point (Win32.HIGH_ORDER (m.LParam.ToInt32 ()),
2867 Win32.LOW_ORDER (m.LParam.ToInt32 ())));
2869 CallControlWndProc (ref m);
2872 CallControlWndProc (ref m);
2874 if (ControlRealWndProc != IntPtr.Zero) {
2875 CallControlWndProc (ref m);
2885 private void DoAnchor (Control ctrl)
2887 // the default, no actions are needed
2888 if (ctrl.Anchor == (AnchorStyles.Left | AnchorStyles.Top))
2891 int deltaWidth = Bounds.Width - oldBounds.Width;
2892 int deltaHeight = Bounds.Height - oldBounds.Height;
2893 int halfDeltaWidth = deltaWidth / 2;
2894 int halfDeltaHeight = deltaHeight / 2;
2895 Rectangle controlBounds = ctrl.Bounds;
2896 if ( (ctrl.Anchor & AnchorStyles.Left) == 0) {
2897 controlBounds.X += halfDeltaWidth;
2899 if ( (ctrl.Anchor & AnchorStyles.Top) == 0) {
2900 controlBounds.Y += halfDeltaHeight;
2902 if ( (ctrl.Anchor & AnchorStyles.Right) == AnchorStyles.Right) {
2903 if ( (ctrl.Anchor & AnchorStyles.Left) == AnchorStyles.Left) {
2904 controlBounds.Width += deltaWidth;
2907 controlBounds.X += halfDeltaWidth;
2910 if ( (ctrl.Anchor & AnchorStyles.Bottom) == AnchorStyles.Bottom) {
2911 if ( (ctrl.Anchor & AnchorStyles.Top) == AnchorStyles.Top) {
2912 controlBounds.Height += deltaHeight;
2915 controlBounds.Y += halfDeltaHeight;
2918 ctrl.Bounds = controlBounds;
2921 private void DoDockAndAnchorLayout (LayoutEventArgs e)
2923 Rectangle area = DisplayRectangle;
2925 for (int i = childControls.Count - 1; i >= 0; i--){
2926 Control control = childControls[i];
2928 switch (control.Dock){
2929 case DockStyle.Bottom:
2930 control.SetBounds (area.Left, area.Bottom - control.Height,
2931 area.Width, control.Height);
2932 area.Height -= control.Height;
2935 control.SetBounds (area.Left, area.Y, area.Width, control.Height);
2936 area.Y += control.Height;
2937 area.Height -= control.Height;
2939 case DockStyle.Right:
2940 control.SetBounds (area.Right - control.Width, area.Top,
2941 control.Width, area.Height);
2942 area.Width -= control.Width;
2944 case DockStyle.Left:
2945 control.SetBounds (area.Left, area.Y, control.Width, area.Height);
2946 area.X += control.Width;
2947 area.Width -= control.Width;
2949 case DockStyle.None:
2955 for (int i = childControls.Count - 1; i >= 0; i--){
2956 Control control = childControls[i];
2958 if (control.Dock == DockStyle.Fill){
2959 control.SetBounds (area.X, area.Y, area.Width, area.Height);
2964 internal static Control FocusedControl {
2966 IEnumerator cw = controlsCollection.GetEnumerator ();
2968 while (cw.MoveNext ()){
2969 Control c = ( (DictionaryEntry) cw.Current).Value as Control;
2971 if (c.Focused)return c;
2978 internal Control getParentForm ()
2980 Control parent = this.Parent;
2981 while (parent != null){
2984 parent = parent.Parent;
2989 /// --- Control: events ---
2990 public event EventHandler BackColorChanged;
2991 public event EventHandler BackgroundImageChanged;
2992 public event EventHandler BindingContextChanged;
2993 public event EventHandler CausesValidationChanged;
2994 public event UICuesEventHandler ChangeUICues;
2997 public event EventHandler Click;
2999 public event EventHandler ContextMenuChanged;
3000 public event ControlEventHandler ControlAdded;
3001 public event ControlEventHandler ControlRemoved;
3002 public event EventHandler CursorChanged;
3003 public event EventHandler DockChanged;
3004 public event EventHandler DoubleClick;
3005 public event DragEventHandler DragDrop;
3006 public event DragEventHandler DragEnter;
3007 public event EventHandler DragLeave;
3008 public event DragEventHandler DragOver;
3011 public event EventHandler EnabledChanged;
3013 public event EventHandler Enter;
3014 public event EventHandler FontChanged;
3015 public event EventHandler ForeColorChanged;
3016 public event GiveFeedbackEventHandler GiveFeedback;
3019 public event EventHandler GotFocus;
3021 public event EventHandler HandleCreated;
3022 public event EventHandler HandleDestroyed;
3023 public event HelpEventHandler HelpRequested;
3024 public event EventHandler ImeModeChanged;
3025 public event InvalidateEventHandler Invalidated;
3028 public event KeyEventHandler KeyDown;
3031 public event KeyPressEventHandler KeyPress;
3034 public event KeyEventHandler KeyUp;
3036 public event LayoutEventHandler Layout;
3037 public event EventHandler Leave;
3038 public event EventHandler LocationChanged;
3041 public event EventHandler LostFocus;
3044 public event MouseEventHandler MouseDown;
3046 public event EventHandler MouseEnter;
3047 public event EventHandler MouseHover;
3048 public event EventHandler MouseLeave;
3051 public event MouseEventHandler MouseMove;
3054 public event MouseEventHandler MouseUp;
3056 public event MouseEventHandler MouseWheel;
3057 public event EventHandler Move;
3060 public event PaintEventHandler Paint;
3063 public event EventHandler ParentChanged;
3065 public event QueryAccessibilityHelpEventHandler QueryAccessibilityHelp;
3066 public event QueryContinueDragEventHandler QueryContinueDrag;
3069 public event EventHandler Resize;
3071 public event EventHandler RightToLeftChanged;
3072 public event EventHandler SizeChanged;
3073 public event EventHandler StyleChanged;
3074 public event EventHandler SystemColorsChanged;
3075 public event EventHandler TabIndexChanged;
3076 public event EventHandler TabStopChanged;
3079 public event EventHandler TextChanged;
3081 public event EventHandler Validated;
3083 // CancelEventHandler not yet defined
3084 //public event CancelEventHandler Validating {
3086 public event EventHandler VisibleChanged;
3088 /// --- IWin32Window properties
3089 public IntPtr Handle {
3091 // If the handle has not yet been created,
3092 // referencing this property will force the
3093 // handle to be created. (MSDN)
3095 if (!IsHandleCreated)
3098 return window.Handle;
3102 /// --- ISynchronizeInvoke properties ---
3104 public bool InvokeRequired {
3106 return CreatorThreadId_ != Win32.GetCurrentThreadId ();
3110 private IAsyncResult DoInvoke (Delegate method, object[] args) {
3111 IAsyncResult result = null;
3112 ControlInvokeHelper helper = new ControlInvokeHelper (method, args);
3113 if (InvokeRequired) {
3115 lock (InvokeQueue_.SyncRoot) {
3116 InvokeQueue_.Enqueue (helper);
3118 Win32.PostMessage (Handle, Control.InvokeMessage, 0, 0);
3123 helper.CompletedSynchronously = true;
3124 helper.ExecuteMethod ();
3130 /// --- ISynchronizeInvoke methods ---
3132 public IAsyncResult BeginInvoke (Delegate method)
3134 return DoInvoke (method, null);
3138 public IAsyncResult BeginInvoke (Delegate method, object[] args)
3140 return DoInvoke (method, args);
3144 public object EndInvoke (IAsyncResult asyncResult)
3146 object result = null;
3147 ControlInvokeHelper helper = asyncResult as ControlInvokeHelper;
3148 if (helper != null) {
3149 if (!asyncResult.CompletedSynchronously) {
3150 asyncResult.AsyncWaitHandle.WaitOne ();
3152 result = helper.MethodResult;
3159 public object Invoke (Delegate method)
3161 return Invoke (method, null);
3165 public object Invoke (Delegate method, object[] args)
3167 IAsyncResult result = BeginInvoke (method, args);
3168 return EndInvoke (result);
3171 /// sub-class: Control.ControlAccessibleObject
3173 /// Provides information about a control that can be used by an accessibility application.
3175 public class ControlAccessibleObject : AccessibleObject {
3176 // AccessibleObject not ready to be base class
3177 /// --- ControlAccessibleObject.constructor ---
3179 public ControlAccessibleObject (Control ownerControl)
3181 throw new NotImplementedException ();
3185 /// --- ControlAccessibleObject Properties ---
3187 public override string DefaultAction {
3190 return base.DefaultAction;
3195 public override string Description {
3198 return base.Description;
3203 public IntPtr Handle {
3205 throw new NotImplementedException ();
3213 public override string Help {
3221 public override string KeyboardShortcut {
3224 return base.KeyboardShortcut;
3229 public override string Name {
3241 public Control Owner {
3243 throw new NotImplementedException ();
3248 public override AccessibleRole Role {
3255 /// --- ControlAccessibleObject Methods ---
3257 public override int GetHelpTopic (out string fileName)
3260 return base.GetHelpTopic (out fileName);
3264 public void NotifyClients (AccessibleEvents accEvent)
3270 public void NotifyClients (AccessibleEvents accEvent,
3277 public override string ToString ()
3280 return base.ToString ();
3284 /// sub-class: Control.ControlCollection
3286 /// Represents a collection of Control objects
3288 public class ControlCollection : IList, ICollection, IEnumerable, ICloneable {
3290 class ControlComparer : IComparer {
3292 int IComparer.Compare (object x, object y)
3294 int tx = ( (Control)x).TabIndex;
3295 int ty = ( (Control)y).TabIndex;
3306 private ArrayList collection = new ArrayList ();
3307 protected Control owner;
3309 /// --- ControlCollection.constructor ---
3310 public ControlCollection (Control owner)
3315 /// --- ControlCollection Properties ---
3318 return collection.Count;
3322 public bool IsReadOnly {
3324 return collection.IsReadOnly;
3328 public virtual Control this [int index] {
3330 return (Control) collection[index];
3334 public virtual void Add (Control value)
3336 if (!Contains (value)) {
3337 collection.Add (value);
3338 value.Parent = owner;
3339 owner.OnControlAdded (new ControlEventArgs (value));
3343 public virtual void AddRange (Control[] controls)
3345 for (int i = 0; i < controls.Length; i++) {
3350 public virtual void Clear ()
3352 collection.Clear ();
3355 public bool Contains (Control control)
3357 return collection.Contains (control);
3360 public void CopyTo (Array dest,int index)
3362 collection.CopyTo (dest, index);
3366 public override bool Equals (object obj)
3369 return base.Equals (obj);
3372 public int GetChildIndex (Control child)
3374 return GetChildIndex (child, true);
3377 public int GetChildIndex (Control child, bool throwException)
3379 int index = collection.IndexOf (child);
3380 if (index == -1 && throwException)
3381 throw new ArgumentException ("'child' is not a child control of this parent.");
3385 public IEnumerator GetEnumerator ()
3387 return collection.GetEnumerator ();
3391 public override int GetHashCode ()
3394 return base.GetHashCode ();
3397 public int IndexOf (Control control)
3399 return collection.IndexOf (control);
3402 public virtual void Remove (Control value)
3404 collection.Remove (value);
3407 public void RemoveAt (int index)
3409 Remove (this [ index ]);
3410 // have to give a chance to handle this situation in derived class
3411 //collection.RemoveAt (index);
3414 public void SetChildIndex (Control child, int newIndex)
3416 int oldIndex = collection.IndexOf (child);
3418 throw new ArgumentException ("'child' is not a child control of this parent.");
3420 if (oldIndex != newIndex){
3421 collection.Remove (child);
3423 if (newIndex >= collection.Count)
3424 collection.Add (child);
3426 collection.Insert (newIndex, child);
3430 internal Control GetFirstControl (bool direction)
3432 if (collection.Count == 0)
3435 ArrayList copy = collection.Clone () as ArrayList;
3436 copy.Sort (new ControlComparer ());
3439 return copy [0] as Control;
3441 Control last = copy[ collection.Count - 1 ] as Control;
3442 if (last.Controls.Count == 0)
3445 return last.Controls.GetFirstControl (false);
3450 internal Control GetNextControl (Control ctl, bool forward)
3452 if (collection.Count == 0)
3455 ArrayList copy = collection.Clone () as ArrayList;
3456 copy.Sort (new ControlComparer ());
3458 int index = copy.IndexOf (ctl)+ (forward ? 1 : -1);
3460 if ( (forward && index < copy.Count)|| (!forward && index >= 0))
3461 return copy[index] as Control;
3466 /// --- ControlCollection.IClonable methods ---
3468 object ICloneable.Clone ()
3470 throw new NotImplementedException ();
3473 /// --- ControlCollection.IList properties ---
3474 bool IList.IsFixedSize {
3476 return collection.IsFixedSize;
3480 object IList.this [int index] {
3482 return collection[index];
3485 collection[index] = value;
3489 object ICollection.SyncRoot {
3491 return collection.SyncRoot;
3495 bool ICollection.IsSynchronized {
3497 return collection.IsSynchronized;
3501 /// --- ControlCollection.IList methods ---
3502 int IList.Add (object control)
3504 return collection.Add (control);
3507 bool IList.Contains (object control)
3509 return collection.Contains (control);
3512 int IList.IndexOf (object control)
3514 return collection.IndexOf (control);
3517 void IList.Insert (int index,object value)
3519 collection.Insert (index, value);
3522 void IList.Remove (object control)
3524 collection.Remove (control);
3526 } // --- end of Control.ControlCollection ---