1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
23 // Jackson Harper (jackson@ximian.com)
30 using System.Runtime.InteropServices;
33 namespace System.Windows.Forms {
35 internal abstract class InternalWindowManager {
36 private TitleButtons title_buttons;
42 protected Point clicked_point;
43 private FormPos sizing_edge;
44 internal Rectangle virtual_position;
46 private Rectangle normal_bounds;
47 private Rectangle iconic_bounds;
68 TopRight = Top | Right,
70 BottomLeft = Bottom | Left,
71 BottomRight = Bottom | Right,
73 AnyEdge = Top | Left | Right | Bottom,
76 public InternalWindowManager (Form form)
80 form.SizeChanged += new EventHandler (FormSizeChangedHandler);
82 title_buttons = new TitleButtons (form);
83 ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
90 public int IconWidth {
91 get { return TitleBarHeight - 5; }
94 public TitleButtons TitleButtons {
99 internal Rectangle NormalBounds {
101 return normal_bounds;
104 normal_bounds = value;
107 internal Size IconicSize {
109 return SystemInformation.MinimizedWindowSize;
113 internal Rectangle IconicBounds {
115 if (iconic_bounds == Rectangle.Empty)
116 return Rectangle.Empty;
117 Rectangle result = iconic_bounds;
118 result.Y = Form.Parent.ClientRectangle.Bottom - iconic_bounds.Y;
122 iconic_bounds = value;
123 iconic_bounds.Y = Form.Parent.ClientRectangle.Bottom - iconic_bounds.Y;
127 internal virtual Rectangle MaximizedBounds {
129 return Form.Parent.ClientRectangle;
133 public virtual void UpdateWindowState (FormWindowState old_window_state, FormWindowState new_window_state, bool force)
135 if (old_window_state == FormWindowState.Normal) {
136 NormalBounds = form.Bounds;
137 } else if (old_window_state == FormWindowState.Minimized) {
138 IconicBounds = form.Bounds;
141 switch (new_window_state) {
142 case FormWindowState.Minimized:
143 if (IconicBounds == Rectangle.Empty) {
144 Size size = IconicSize;
145 Point location = new Point (0, Form.Parent.ClientSize.Height - size.Height);
146 IconicBounds = new Rectangle (location, size);
148 form.Bounds = IconicBounds;
150 case FormWindowState.Maximized:
151 form.Bounds = MaximizedBounds;
153 case FormWindowState.Normal:
154 form.Bounds = NormalBounds;
158 UpdateWindowDecorations (new_window_state);
162 public virtual void UpdateWindowDecorations (FormWindowState window_state)
164 ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
165 if (form.IsHandleCreated)
166 XplatUI.RequestNCRecalc (form.Handle);
169 public virtual bool WndProc (ref Message m)
172 Console.WriteLine(DateTime.Now.ToLongTimeString () + " " + this.GetType () .Name + " (Handle={0},Text={1}) received message {2}", form.IsHandleCreated ? form.Handle : IntPtr.Zero, form.Text, m.ToString ());
175 switch ((Msg)m.Msg) {
178 // The mouse handling messages are actually
179 // not WM_NC* messages except for the first button and NCMOVEs
180 // down because we capture on the form
182 case Msg.WM_MOUSEMOVE:
183 return HandleMouseMove (form, ref m);
185 case Msg.WM_LBUTTONUP:
186 HandleLButtonUp (ref m);
189 case Msg.WM_RBUTTONDOWN:
190 return HandleRButtonDown (ref m);
192 case Msg.WM_LBUTTONDOWN:
193 return HandleLButtonDown (ref m);
195 case Msg.WM_LBUTTONDBLCLK:
196 return HandleLButtonDblClick (ref m);
198 case Msg.WM_PARENTNOTIFY:
199 if (Control.LowOrder(m.WParam.ToInt32()) == (int) Msg.WM_LBUTTONDOWN)
203 case Msg.WM_NCHITTEST:
204 return HandleNCHitTest (ref m);
206 // Return true from these guys, otherwise win32 will mess up z-order
207 case Msg.WM_NCLBUTTONUP:
208 HandleNCLButtonUp (ref m);
211 case Msg.WM_NCLBUTTONDOWN:
212 HandleNCLButtonDown (ref m);
215 case Msg.WM_NCMOUSEMOVE:
216 HandleNCMouseMove (ref m);
219 case Msg.WM_NCLBUTTONDBLCLK:
220 HandleNCLButtonDblClick (ref m);
223 case Msg.WM_NCMOUSELEAVE:
224 HandleNCMouseLeave (ref m);
227 case Msg.WM_MOUSELEAVE:
228 HandleMouseLeave (ref m);
231 case Msg.WM_NCCALCSIZE:
232 return HandleNCCalcSize (ref m);
235 return HandleNCPaint (ref m);
241 protected virtual bool HandleNCPaint (ref Message m)
243 PaintEventArgs pe = XplatUI.PaintEventStart (ref m, form.Handle, false);
247 if (form.ActiveMenu != null) {
250 pnt = GetMenuOrigin ();
252 // The entire menu has to be in the clip rectangle because the
253 // control buttons are right-aligned and otherwise they would
254 // stay painted when the window gets resized.
255 clip = new Rectangle (pnt.X, pnt.Y, form.ClientSize.Width, 0);
256 clip = Rectangle.Union (clip, pe.ClipRectangle);
258 pe.Graphics.SetClip (clip);
260 form.ActiveMenu.Draw (pe, new Rectangle (pnt.X, pnt.Y, form.ClientSize.Width, 0));
262 if (HasBorders || IsMinimized && !(Form.IsMdiChild && IsMaximized)) {
263 // clip region is not correct on win32.
264 // use the entire form's area.
265 clip = new Rectangle (0, 0, form.Width, form.Height);
266 ThemeEngine.Current.DrawManagedWindowDecorations (pe.Graphics, clip, this);
268 XplatUI.PaintEventEnd (ref m, form.Handle, false);
272 protected virtual bool HandleNCCalcSize (ref Message m)
274 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
275 XplatUIWin32.RECT rect;
277 if (m.WParam == (IntPtr)1) {
278 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (m.LParam,
279 typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
281 ncp.rgrc1 = NCCalcSize (ncp.rgrc1);
283 Marshal.StructureToPtr (ncp, m.LParam, true);
285 rect = (XplatUIWin32.RECT) Marshal.PtrToStructure (m.LParam, typeof (XplatUIWin32.RECT));
287 rect = NCCalcSize (rect);
289 Marshal.StructureToPtr (rect, m.LParam, true);
295 protected virtual XplatUIWin32.RECT NCCalcSize (XplatUIWin32.RECT proposed_window_rect)
297 int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
300 proposed_window_rect.top += TitleBarHeight + bw;
301 proposed_window_rect.bottom -= bw;
302 proposed_window_rect.left += bw;
303 proposed_window_rect.right -= bw;
306 if (XplatUI.RequiresPositiveClientAreaSize) {
307 // This is necessary for Linux, can't handle <= 0-sized
308 // client areas correctly.
309 if (proposed_window_rect.right <= proposed_window_rect.left) {
310 proposed_window_rect.right += proposed_window_rect.left - proposed_window_rect.right + 1;
312 if (proposed_window_rect.top >= proposed_window_rect.bottom) {
313 proposed_window_rect.bottom += proposed_window_rect.top - proposed_window_rect.bottom + 1;
317 return proposed_window_rect;
320 protected virtual bool HandleNCHitTest (ref Message m)
323 int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
324 int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
326 NCPointToClient (ref x, ref y);
328 FormPos pos = FormPosForCoords (x, y);
330 if (pos == FormPos.TitleBar) {
331 m.Result = new IntPtr ((int)HitTest.HTCAPTION);
340 m.Result = new IntPtr ((int)HitTest.HTTOP);
343 m.Result = new IntPtr ((int)HitTest.HTLEFT);
346 m.Result = new IntPtr ((int)HitTest.HTRIGHT);
349 m.Result = new IntPtr ((int)HitTest.HTBOTTOM);
351 case FormPos.TopLeft:
352 m.Result = new IntPtr ((int)HitTest.HTTOPLEFT);
354 case FormPos.TopRight:
355 m.Result = new IntPtr ((int)HitTest.HTTOPRIGHT);
357 case FormPos.BottomLeft:
358 m.Result = new IntPtr ((int)HitTest.HTBOTTOMLEFT);
360 case FormPos.BottomRight:
361 m.Result = new IntPtr ((int)HitTest.HTBOTTOMRIGHT);
364 // We return false so that DefWndProc handles things
370 public virtual void UpdateBorderStyle (FormBorderStyle border_style)
372 if (form.IsHandleCreated) {
373 XplatUI.SetBorderStyle (form.Handle, border_style);
376 if (ShouldRemoveWindowManager (border_style)) {
377 form.RemoveWindowManager ();
381 ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
386 public virtual void SetWindowState (FormWindowState old_state, FormWindowState window_state)
388 UpdateWindowState (old_state, window_state, false);
391 public virtual FormWindowState GetWindowState ()
393 return form.window_state;
396 public virtual void PointToClient (ref int x, ref int y)
398 // toolwindows stay in screencoords we just have to make sure
399 // they obey the working area
400 Rectangle working = SystemInformation.WorkingArea;
402 if (x > working.Right)
404 if (x < working.Left)
409 if (y > working.Bottom)
413 public virtual void PointToScreen (ref int x, ref int y)
415 XplatUI.ClientToScreen (form.Handle, ref x, ref y);
418 protected virtual bool ShouldRemoveWindowManager (FormBorderStyle style)
420 return style != FormBorderStyle.FixedToolWindow && style != FormBorderStyle.SizableToolWindow;
423 public bool IconRectangleContains (int x, int y)
428 Rectangle icon = ThemeEngine.Current.ManagedWindowGetTitleBarIconArea (this);
429 return icon.Contains (x, y);
432 public bool ShowIcon {
440 if (IsToolWindow || Form.FormBorderStyle == FormBorderStyle.FixedDialog)
446 protected virtual void Activate ()
448 form.Invalidate (true);
452 public virtual bool IsActive {
459 private void FormSizeChangedHandler (object sender, EventArgs e)
461 if (form.IsHandleCreated) {
462 ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
463 XplatUI.InvalidateNC (form.Handle);
467 protected virtual bool HandleRButtonDown (ref Message m)
473 protected virtual bool HandleLButtonDown (ref Message m)
479 protected virtual bool HandleLButtonDblClick(ref Message m)
484 protected virtual bool HandleNCMouseLeave (ref Message m)
486 int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
487 int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
489 NCPointToClient (ref x, ref y);
490 FormPos pos = FormPosForCoords (x, y);
492 if (pos != FormPos.TitleBar) {
493 HandleTitleBarLeave (x, y);
500 protected virtual bool HandleNCMouseMove (ref Message m)
502 int x = Control.LowOrder((int)m.LParam.ToInt32( ));
503 int y = Control.HighOrder((int)m.LParam.ToInt32( ));
505 NCPointToClient (ref x, ref y);
506 FormPos pos = FormPosForCoords (x, y);
508 if (pos == FormPos.TitleBar) {
509 HandleTitleBarMouseMove (x, y);
513 if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
514 MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y, 0);
515 form.ActiveMenu.OnMouseMove (form, mea);
522 protected virtual bool HandleNCLButtonDown (ref Message m)
526 start = Cursor.Position;
527 virtual_position = form.Bounds;
529 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
530 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
532 // Need to adjust because we are in NC land
533 NCPointToClient (ref x, ref y);
534 FormPos pos = FormPosForCoords (x, y);
536 if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
537 MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y - TitleBarHeight, 0);
538 form.ActiveMenu.OnMouseDown (form, mea);
541 if (pos == FormPos.TitleBar) {
542 HandleTitleBarDown (x, y);
547 if ((pos & FormPos.AnyEdge) == 0)
550 virtual_position = form.Bounds;
551 state = State.Sizing;
560 protected virtual void HandleNCLButtonDblClick (ref Message m)
562 int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
563 int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
565 // Need to adjust because we are in NC land
566 NCPointToClient (ref x, ref y);
568 FormPos pos = FormPosForCoords (x, y);
569 if (pos == FormPos.TitleBar || pos == FormPos.Top)
570 HandleTitleBarDoubleClick (x, y);
574 protected virtual void HandleTitleBarDoubleClick (int x, int y)
579 protected virtual void HandleTitleBarLeave (int x, int y)
581 title_buttons.MouseLeave (x, y);
584 protected virtual void HandleTitleBarMouseMove (int x, int y)
586 if (title_buttons.MouseMove (x, y))
587 XplatUI.InvalidateNC (form.Handle);
590 protected virtual void HandleTitleBarUp (int x, int y)
592 title_buttons.MouseUp (x, y);
597 protected virtual void HandleTitleBarDown (int x, int y)
599 title_buttons.MouseDown (x, y);
601 if (!TitleButtons.AnyPushedTitleButtons && !IsMaximized) {
602 state = State.Moving;
603 clicked_point = new Point (x, y);
604 if (form.Parent != null) {
605 form.CaptureWithConfine (form.Parent);
611 XplatUI.InvalidateNC (form.Handle);
614 private bool HandleMouseMove (Form form, ref Message m)
618 HandleWindowMove (m);
628 private void HandleMouseLeave (ref Message m)
633 protected virtual void HandleWindowMove (Message m)
635 Point move = MouseMove (Cursor.Position);
637 UpdateVP (virtual_position.X + move.X, virtual_position.Y + move.Y,
638 virtual_position.Width, virtual_position.Height);
641 private void HandleSizing (Message m)
643 Rectangle pos = virtual_position;
647 int border_width = BorderWidth;
648 mw = 2 * (border_width + Theme.ManagedWindowSpacingAfterLastTitleButton) + ThemeEngine.Current.ManagedWindowButtonSize (this).Width;
649 mh = 2 * border_width + TitleBarHeight;
651 Size minimum_size = SystemInformation.MinWindowTrackSize;
652 mw = minimum_size.Width;
653 mh = minimum_size.Height;
655 int x = Cursor.Position.X;
656 int y = Cursor.Position.Y;
658 PointToClient (ref x, ref y);
660 if ((sizing_edge & FormPos.Top) != 0) {
661 if (pos.Bottom - y < mh)
663 pos.Height = pos.Bottom - y;
665 } else if ((sizing_edge & FormPos.Bottom) != 0) {
666 int height = y - pos.Top;
672 if ((sizing_edge & FormPos.Left) != 0) {
673 if (pos.Right - x < mw)
675 pos.Width = pos.Right - x;
677 } else if ((sizing_edge & FormPos.Right) != 0) {
678 int width = x - form.Left;
687 public bool IsMaximized {
688 get { return GetWindowState () == FormWindowState.Maximized; }
691 public bool IsMinimized {
692 get { return GetWindowState () == FormWindowState.Minimized; }
695 public bool IsSizable {
697 switch (form.FormBorderStyle) {
698 case FormBorderStyle.Sizable:
699 case FormBorderStyle.SizableToolWindow:
700 return (form.window_state != FormWindowState.Minimized);
707 public bool HasBorders {
709 return form.FormBorderStyle != FormBorderStyle.None;
713 public bool IsToolWindow {
715 if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
716 form.FormBorderStyle == FormBorderStyle.FixedToolWindow ||
717 form.GetCreateParams().IsSet (WindowExStyles.WS_EX_TOOLWINDOW))
723 public int TitleBarHeight {
725 return ThemeEngine.Current.ManagedWindowTitleBarHeight (this);
729 public int BorderWidth {
731 return ThemeEngine.Current.ManagedWindowBorderWidth (this);
735 public virtual int MenuHeight {
737 return (form.Menu != null ? ThemeEngine.Current.MenuHeight : 0);
741 protected void UpdateVP (Rectangle r)
743 UpdateVP (r.X, r.Y, r.Width, r.Height);
746 protected void UpdateVP (Point loc, int w, int h)
748 UpdateVP (loc.X, loc.Y, w, h);
751 protected void UpdateVP (int x, int y, int w, int h)
753 virtual_position.X = x;
754 virtual_position.Y = y;
755 virtual_position.Width = w;
756 virtual_position.Height = h;
758 DrawVirtualPosition (virtual_position);
761 protected virtual void HandleLButtonUp (ref Message m)
763 if (state == State.Idle)
766 ClearVirtualPosition ();
768 form.Capture = false;
769 if (state == State.Moving && form.Location != virtual_position.Location)
770 form.Location = virtual_position.Location;
771 else if (state == State.Sizing && form.Bounds != virtual_position)
772 form.Bounds = virtual_position;
775 OnWindowFinishedMoving ();
778 private bool HandleNCLButtonUp (ref Message m)
781 ClearVirtualPosition ();
783 form.Capture = false;
785 if (form.MdiContainer != null)
786 form.MdiContainer.SizeScrollBars();
789 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
790 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
792 NCPointToClient (ref x, ref y);
793 FormPos pos = FormPosForCoords (x, y);
795 if (pos == FormPos.TitleBar) {
796 HandleTitleBarUp (x, y);
803 protected void DrawTitleButton (Graphics dc, TitleButton button, Rectangle clip)
805 if (!button.Rectangle.IntersectsWith (clip))
808 ThemeEngine.Current.ManagedWindowDrawMenuButton (dc, button, clip, this);
811 public virtual void DrawMaximizedButtons (object sender, PaintEventArgs pe)
815 protected Point MouseMove (Point pos)
817 return new Point (pos.X - start.X, pos.Y - start.Y);
820 protected virtual void DrawVirtualPosition (Rectangle virtual_position)
822 form.Bounds = virtual_position;
823 start = Cursor.Position;
826 protected virtual void ClearVirtualPosition ()
831 protected virtual void OnWindowFinishedMoving ()
835 protected virtual void NCPointToClient(ref int x, ref int y) {
836 form.PointToClient(ref x, ref y);
837 NCClientToNC (ref x, ref y);
840 protected virtual void NCClientToNC (ref int x, ref int y) {
846 internal Point GetMenuOrigin ()
848 return new Point (BorderWidth, BorderWidth + TitleBarHeight);
851 protected FormPos FormPosForCoords (int x, int y)
853 int bw = BorderWidth;
854 if (y < TitleBarHeight + bw) {
855 // Console.WriteLine ("A");
856 if (y > bw && x > bw &&
858 return FormPos.TitleBar;
860 if (x < bw || (x < 20 && y < bw))
861 return FormPos.TopLeft;
863 if (x > form.Width - bw ||
864 (x > form.Width - 20 && y < bw))
865 return FormPos.TopRight;
870 } else if (y > form.Height - 20) {
871 // Console.WriteLine ("B");
873 (x < 20 && y > form.Height - bw))
874 return FormPos.BottomLeft;
876 if (x > form.Width - (bw * 2) ||
877 (x > form.Width - 20 &&
878 y > form.Height - bw))
879 return FormPos.BottomRight;
881 if (y > form.Height - (bw * 2))
882 return FormPos.Bottom;
886 // Console.WriteLine ("C");
888 } else if (x > form.Width - (bw * 2)) {
889 // Console.WriteLine ("D");
890 return FormPos.Right;
892 // Console.WriteLine ("E {0}", form.Width - bw);
898 internal class TitleButton
900 public Rectangle Rectangle;
901 public ButtonState State;
902 public CaptionButton Caption;
903 private EventHandler Clicked;
907 public TitleButton (CaptionButton caption, EventHandler clicked)
913 public void OnClick ()
915 if (Clicked != null) {
916 Clicked (this, EventArgs.Empty);
920 public bool Entered {
921 get { return entered; }
922 set { entered = value; }
926 internal class TitleButtons : System.Collections.IEnumerable
928 public TitleButton MinimizeButton;
929 public TitleButton MaximizeButton;
930 public TitleButton RestoreButton;
931 public TitleButton CloseButton;
932 public TitleButton HelpButton;
934 public TitleButton [] AllButtons;
937 private ToolTip.ToolTipWindow tooltip;
938 private Timer tooltip_timer;
939 private TitleButton tooltip_hovered_button;
940 private TitleButton tooltip_hidden_button;
941 private const int tooltip_hide_interval = 3000;
942 private const int tooltip_show_interval = 1000;
945 public TitleButtons (Form frm)
950 MinimizeButton = new TitleButton (CaptionButton.Minimize, new EventHandler (ClickHandler));
951 MaximizeButton = new TitleButton (CaptionButton.Maximize, new EventHandler (ClickHandler));
952 RestoreButton = new TitleButton (CaptionButton.Restore, new EventHandler (ClickHandler));
953 CloseButton = new TitleButton (CaptionButton.Close, new EventHandler (ClickHandler));
954 HelpButton = new TitleButton (CaptionButton.Help, new EventHandler (ClickHandler));
956 AllButtons = new TitleButton [] { MinimizeButton, MaximizeButton, RestoreButton, CloseButton, HelpButton };
959 private void ClickHandler (object sender, EventArgs e)
965 TitleButton button = (TitleButton) sender;
967 switch (button.Caption) {
968 case CaptionButton.Close:
971 case CaptionButton.Help:
972 Console.WriteLine ("Help not implemented.");
974 case CaptionButton.Maximize:
975 form.WindowState = FormWindowState.Maximized;
977 case CaptionButton.Minimize:
978 form.WindowState = FormWindowState.Minimized;
980 case CaptionButton.Restore:
981 form.WindowState = FormWindowState.Normal;
986 public TitleButton FindButton (int x, int y)
992 foreach (TitleButton button in AllButtons) {
993 if (button.Visible && button.Rectangle.Contains (x, y)) {
1000 public bool AnyPushedTitleButtons {
1006 foreach (TitleButton button in AllButtons) {
1007 if (button.Visible && button.State == ButtonState.Pushed) {
1015 #region IEnumerable Members
1017 public System.Collections.IEnumerator GetEnumerator ()
1019 return AllButtons.GetEnumerator ();
1023 #region ToolTip helpers
1024 // Called from MouseMove if mouse is over a button
1025 public void ToolTipStart (TitleButton button)
1027 tooltip_hovered_button = button;
1029 if (tooltip_hovered_button == tooltip_hidden_button)
1031 tooltip_hidden_button = null;
1033 if (tooltip != null && tooltip.Visible)
1036 if (tooltip_timer == null) {
1038 tooltip_timer = new Timer ();
1039 tooltip_timer.Tick += new EventHandler (ToolTipTimerTick);
1042 tooltip_timer.Interval = tooltip_show_interval;
1043 tooltip_timer.Start ();
1044 tooltip_hovered_button = button;
1047 public void ToolTipTimerTick (object sender, EventArgs e)
1049 if (tooltip_timer.Interval == tooltip_hide_interval) {
1050 tooltip_hidden_button = tooltip_hovered_button;
1051 ToolTipHide (false);
1053 ToolTipShow (false);
1056 // Called from timer (with only_refresh = false)
1057 // Called from ToolTipStart if tooltip is already shown (with only_refresh = true)
1058 public void ToolTipShow (bool only_refresh)
1063 string text = Locale.GetText (tooltip_hovered_button.Caption.ToString ());
1065 tooltip_timer.Interval = tooltip_hide_interval;
1066 tooltip_timer.Enabled = true;
1068 if (only_refresh && (tooltip == null || !tooltip.Visible)) {
1072 if (tooltip == null)
1073 tooltip = new ToolTip.ToolTipWindow ();
1074 else if (tooltip.Text == text && tooltip.Visible)
1076 else if (tooltip.Visible)
1077 tooltip.Visible = false;
1079 if (form.WindowState == FormWindowState.Maximized && form.MdiParent != null)
1080 tooltip.Present (form.MdiParent, text);
1082 tooltip.Present (form, text);
1086 // Called from MouseLeave (with reset_hidden_button = true)
1087 // Called from MouseDown (with reset_hidden_button = false)
1088 // Called from MouseMove if mouse isn't over any button (with reset_hidden_button = false)
1089 // Called from Timer if hiding (with reset_hidden_button = false)
1090 public void ToolTipHide (bool reset_hidden_button)
1092 if (tooltip_timer != null)
1093 tooltip_timer.Enabled = false;
1094 if (tooltip != null && tooltip.Visible)
1095 tooltip.Visible = false;
1096 if (reset_hidden_button)
1097 tooltip_hidden_button = null;
1101 public bool MouseMove (int x, int y)
1107 bool any_change = false;
1108 bool any_pushed_buttons = AnyPushedTitleButtons;
1109 bool any_tooltip = false;
1110 TitleButton over_button = FindButton (x, y);
1112 foreach (TitleButton button in this) {
1116 if (button.State == ButtonState.Inactive)
1119 if (button == over_button) {
1120 if (any_pushed_buttons) {
1121 any_change |= button.State != ButtonState.Pushed;
1122 button.State = ButtonState.Pushed;
1124 ToolTipStart (button);
1126 if (!button.Entered) {
1127 button.Entered = true;
1128 if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
1132 if (any_pushed_buttons) {
1133 any_change |= button.State != ButtonState.Normal;
1134 button.State = ButtonState.Normal;
1136 if (button.Entered) {
1137 button.Entered = false;
1138 if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
1145 ToolTipHide (false);
1150 public void MouseDown (int x, int y)
1156 ToolTipHide (false);
1158 foreach (TitleButton button in this) {
1159 if (button != null && button.State != ButtonState.Inactive) {
1160 button.State = ButtonState.Normal;
1163 TitleButton clicked_button = FindButton (x, y);
1164 if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
1165 clicked_button.State = ButtonState.Pushed;
1169 public void MouseUp (int x, int y)
1175 TitleButton clicked_button = FindButton (x, y);
1176 if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
1177 clicked_button.OnClick ();
1180 foreach (TitleButton button in this) {
1181 if (button == null || button.State == ButtonState.Inactive)
1184 button.State = ButtonState.Normal;
1187 if (clicked_button == CloseButton && !form.closing)
1188 XplatUI.InvalidateNC (form.Handle);
1193 internal void MouseLeave (int x, int y)
1199 foreach (TitleButton button in this) {
1200 if (button == null || button.State == ButtonState.Inactive)
1203 button.State = ButtonState.Normal;