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 {
442 if (IsToolWindow || Form.FormBorderStyle == FormBorderStyle.FixedDialog)
448 protected virtual void Activate ()
450 form.Invalidate (true);
454 public virtual bool IsActive {
461 private void FormSizeChangedHandler (object sender, EventArgs e)
463 if (form.IsHandleCreated) {
464 ThemeEngine.Current.ManagedWindowSetButtonLocations (this);
465 XplatUI.InvalidateNC (form.Handle);
469 protected virtual bool HandleRButtonDown (ref Message m)
475 protected virtual bool HandleLButtonDown (ref Message m)
481 protected virtual bool HandleLButtonDblClick(ref Message m)
486 protected virtual bool HandleNCMouseLeave (ref Message m)
488 int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
489 int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
491 NCPointToClient (ref x, ref y);
492 FormPos pos = FormPosForCoords (x, y);
494 if (pos != FormPos.TitleBar) {
495 HandleTitleBarLeave (x, y);
502 protected virtual bool HandleNCMouseMove (ref Message m)
504 int x = Control.LowOrder((int)m.LParam.ToInt32( ));
505 int y = Control.HighOrder((int)m.LParam.ToInt32( ));
507 NCPointToClient (ref x, ref y);
508 FormPos pos = FormPosForCoords (x, y);
510 if (pos == FormPos.TitleBar) {
511 HandleTitleBarMouseMove (x, y);
515 if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
516 MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y, 0);
517 form.ActiveMenu.OnMouseMove (form, mea);
524 protected virtual bool HandleNCLButtonDown (ref Message m)
528 start = Cursor.Position;
529 virtual_position = form.Bounds;
531 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
532 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
534 // Need to adjust because we are in NC land
535 NCPointToClient (ref x, ref y);
536 FormPos pos = FormPosForCoords (x, y);
538 if (form.ActiveMenu != null && XplatUI.IsEnabled (form.Handle)) {
539 MouseEventArgs mea = new MouseEventArgs (Form.FromParamToMouseButtons (m.WParam.ToInt32 ()), form.mouse_clicks, x, y - TitleBarHeight, 0);
540 form.ActiveMenu.OnMouseDown (form, mea);
543 if (pos == FormPos.TitleBar) {
544 HandleTitleBarDown (x, y);
549 if ((pos & FormPos.AnyEdge) == 0)
552 virtual_position = form.Bounds;
553 state = State.Sizing;
562 protected virtual void HandleNCLButtonDblClick (ref Message m)
564 int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
565 int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
567 // Need to adjust because we are in NC land
568 NCPointToClient (ref x, ref y);
570 FormPos pos = FormPosForCoords (x, y);
571 if (pos == FormPos.TitleBar || pos == FormPos.Top)
572 HandleTitleBarDoubleClick (x, y);
576 protected virtual void HandleTitleBarDoubleClick (int x, int y)
581 protected virtual void HandleTitleBarLeave (int x, int y)
583 title_buttons.MouseLeave (x, y);
586 protected virtual void HandleTitleBarMouseMove (int x, int y)
588 if (title_buttons.MouseMove (x, y))
589 XplatUI.InvalidateNC (form.Handle);
592 protected virtual void HandleTitleBarUp (int x, int y)
594 title_buttons.MouseUp (x, y);
599 protected virtual void HandleTitleBarDown (int x, int y)
601 title_buttons.MouseDown (x, y);
603 if (!TitleButtons.AnyPushedTitleButtons && !IsMaximized) {
604 state = State.Moving;
605 clicked_point = new Point (x, y);
606 if (form.Parent != null) {
607 form.CaptureWithConfine (form.Parent);
613 XplatUI.InvalidateNC (form.Handle);
616 private bool HandleMouseMove (Form form, ref Message m)
620 HandleWindowMove (m);
630 private void HandleMouseLeave (ref Message m)
635 protected virtual void HandleWindowMove (Message m)
637 Point move = MouseMove (Cursor.Position);
639 UpdateVP (virtual_position.X + move.X, virtual_position.Y + move.Y,
640 virtual_position.Width, virtual_position.Height);
643 private void HandleSizing (Message m)
645 Rectangle pos = virtual_position;
649 int border_width = BorderWidth;
650 mw = 2 * (border_width + Theme.ManagedWindowSpacingAfterLastTitleButton) + ThemeEngine.Current.ManagedWindowButtonSize (this).Width;
651 mh = 2 * border_width + TitleBarHeight;
653 Size minimum_size = SystemInformation.MinWindowTrackSize;
654 mw = minimum_size.Width;
655 mh = minimum_size.Height;
657 int x = Cursor.Position.X;
658 int y = Cursor.Position.Y;
660 PointToClient (ref x, ref y);
662 if ((sizing_edge & FormPos.Top) != 0) {
663 if (pos.Bottom - y < mh)
665 pos.Height = pos.Bottom - y;
667 } else if ((sizing_edge & FormPos.Bottom) != 0) {
668 int height = y - pos.Top;
674 if ((sizing_edge & FormPos.Left) != 0) {
675 if (pos.Right - x < mw)
677 pos.Width = pos.Right - x;
679 } else if ((sizing_edge & FormPos.Right) != 0) {
680 int width = x - form.Left;
689 public bool IsMaximized {
690 get { return GetWindowState () == FormWindowState.Maximized; }
693 public bool IsMinimized {
694 get { return GetWindowState () == FormWindowState.Minimized; }
697 public bool IsSizable {
699 switch (form.FormBorderStyle) {
700 case FormBorderStyle.Sizable:
701 case FormBorderStyle.SizableToolWindow:
702 return (form.window_state != FormWindowState.Minimized);
709 public bool HasBorders {
711 return form.FormBorderStyle != FormBorderStyle.None;
715 public bool IsToolWindow {
717 if (form.FormBorderStyle == FormBorderStyle.SizableToolWindow ||
718 form.FormBorderStyle == FormBorderStyle.FixedToolWindow ||
719 form.GetCreateParams().IsSet (WindowExStyles.WS_EX_TOOLWINDOW))
725 public int TitleBarHeight {
727 return ThemeEngine.Current.ManagedWindowTitleBarHeight (this);
731 public int BorderWidth {
733 return ThemeEngine.Current.ManagedWindowBorderWidth (this);
737 public virtual int MenuHeight {
739 return (form.Menu != null ? ThemeEngine.Current.MenuHeight : 0);
743 protected void UpdateVP (Rectangle r)
745 UpdateVP (r.X, r.Y, r.Width, r.Height);
748 protected void UpdateVP (Point loc, int w, int h)
750 UpdateVP (loc.X, loc.Y, w, h);
753 protected void UpdateVP (int x, int y, int w, int h)
755 virtual_position.X = x;
756 virtual_position.Y = y;
757 virtual_position.Width = w;
758 virtual_position.Height = h;
760 DrawVirtualPosition (virtual_position);
763 protected virtual void HandleLButtonUp (ref Message m)
765 if (state == State.Idle)
768 ClearVirtualPosition ();
770 form.Capture = false;
771 if (state == State.Moving && form.Location != virtual_position.Location)
772 form.Location = virtual_position.Location;
773 else if (state == State.Sizing && form.Bounds != virtual_position)
774 form.Bounds = virtual_position;
777 OnWindowFinishedMoving ();
780 private bool HandleNCLButtonUp (ref Message m)
783 ClearVirtualPosition ();
785 form.Capture = false;
787 if (form.MdiContainer != null)
788 form.MdiContainer.SizeScrollBars();
791 int x = Control.LowOrder ((int) m.LParam.ToInt32 ());
792 int y = Control.HighOrder ((int) m.LParam.ToInt32 ());
794 NCPointToClient (ref x, ref y);
795 FormPos pos = FormPosForCoords (x, y);
797 if (pos == FormPos.TitleBar) {
798 HandleTitleBarUp (x, y);
805 protected void DrawTitleButton (Graphics dc, TitleButton button, Rectangle clip)
807 if (!button.Rectangle.IntersectsWith (clip))
810 ThemeEngine.Current.ManagedWindowDrawMenuButton (dc, button, clip, this);
813 public virtual void DrawMaximizedButtons (object sender, PaintEventArgs pe)
817 protected Point MouseMove (Point pos)
819 return new Point (pos.X - start.X, pos.Y - start.Y);
822 protected virtual void DrawVirtualPosition (Rectangle virtual_position)
824 form.Bounds = virtual_position;
825 start = Cursor.Position;
828 protected virtual void ClearVirtualPosition ()
833 protected virtual void OnWindowFinishedMoving ()
837 protected virtual void NCPointToClient(ref int x, ref int y) {
838 form.PointToClient(ref x, ref y);
839 NCClientToNC (ref x, ref y);
842 protected virtual void NCClientToNC (ref int x, ref int y) {
848 internal Point GetMenuOrigin ()
850 return new Point (BorderWidth, BorderWidth + TitleBarHeight);
853 protected FormPos FormPosForCoords (int x, int y)
855 int bw = BorderWidth;
856 if (y < TitleBarHeight + bw) {
857 // Console.WriteLine ("A");
858 if (y > bw && x > bw &&
860 return FormPos.TitleBar;
862 if (x < bw || (x < 20 && y < bw))
863 return FormPos.TopLeft;
865 if (x > form.Width - bw ||
866 (x > form.Width - 20 && y < bw))
867 return FormPos.TopRight;
872 } else if (y > form.Height - 20) {
873 // Console.WriteLine ("B");
875 (x < 20 && y > form.Height - bw))
876 return FormPos.BottomLeft;
878 if (x > form.Width - (bw * 2) ||
879 (x > form.Width - 20 &&
880 y > form.Height - bw))
881 return FormPos.BottomRight;
883 if (y > form.Height - (bw * 2))
884 return FormPos.Bottom;
888 // Console.WriteLine ("C");
890 } else if (x > form.Width - (bw * 2)) {
891 // Console.WriteLine ("D");
892 return FormPos.Right;
894 // Console.WriteLine ("E {0}", form.Width - bw);
900 internal class TitleButton
902 public Rectangle Rectangle;
903 public ButtonState State;
904 public CaptionButton Caption;
905 private EventHandler Clicked;
909 public TitleButton (CaptionButton caption, EventHandler clicked)
915 public void OnClick ()
917 if (Clicked != null) {
918 Clicked (this, EventArgs.Empty);
922 public bool Entered {
923 get { return entered; }
924 set { entered = value; }
928 internal class TitleButtons : System.Collections.IEnumerable
930 public TitleButton MinimizeButton;
931 public TitleButton MaximizeButton;
932 public TitleButton RestoreButton;
933 public TitleButton CloseButton;
934 public TitleButton HelpButton;
936 public TitleButton [] AllButtons;
939 private ToolTip.ToolTipWindow tooltip;
940 private Timer tooltip_timer;
941 private TitleButton tooltip_hovered_button;
942 private TitleButton tooltip_hidden_button;
943 private const int tooltip_hide_interval = 3000;
944 private const int tooltip_show_interval = 1000;
947 public TitleButtons (Form frm)
952 MinimizeButton = new TitleButton (CaptionButton.Minimize, new EventHandler (ClickHandler));
953 MaximizeButton = new TitleButton (CaptionButton.Maximize, new EventHandler (ClickHandler));
954 RestoreButton = new TitleButton (CaptionButton.Restore, new EventHandler (ClickHandler));
955 CloseButton = new TitleButton (CaptionButton.Close, new EventHandler (ClickHandler));
956 HelpButton = new TitleButton (CaptionButton.Help, new EventHandler (ClickHandler));
958 AllButtons = new TitleButton [] { MinimizeButton, MaximizeButton, RestoreButton, CloseButton, HelpButton };
961 private void ClickHandler (object sender, EventArgs e)
967 TitleButton button = (TitleButton) sender;
969 switch (button.Caption) {
970 case CaptionButton.Close:
973 case CaptionButton.Help:
974 Console.WriteLine ("Help not implemented.");
976 case CaptionButton.Maximize:
977 form.WindowState = FormWindowState.Maximized;
979 case CaptionButton.Minimize:
980 form.WindowState = FormWindowState.Minimized;
982 case CaptionButton.Restore:
983 form.WindowState = FormWindowState.Normal;
988 public TitleButton FindButton (int x, int y)
994 foreach (TitleButton button in AllButtons) {
995 if (button.Visible && button.Rectangle.Contains (x, y)) {
1002 public bool AnyPushedTitleButtons {
1008 foreach (TitleButton button in AllButtons) {
1009 if (button.Visible && button.State == ButtonState.Pushed) {
1017 #region IEnumerable Members
1019 public System.Collections.IEnumerator GetEnumerator ()
1021 return AllButtons.GetEnumerator ();
1025 #region ToolTip helpers
1026 // Called from MouseMove if mouse is over a button
1027 public void ToolTipStart (TitleButton button)
1029 tooltip_hovered_button = button;
1031 if (tooltip_hovered_button == tooltip_hidden_button)
1033 tooltip_hidden_button = null;
1035 if (tooltip != null && tooltip.Visible)
1038 if (tooltip_timer == null) {
1040 tooltip_timer = new Timer ();
1041 tooltip_timer.Tick += new EventHandler (ToolTipTimerTick);
1044 tooltip_timer.Interval = tooltip_show_interval;
1045 tooltip_timer.Start ();
1046 tooltip_hovered_button = button;
1049 public void ToolTipTimerTick (object sender, EventArgs e)
1051 if (tooltip_timer.Interval == tooltip_hide_interval) {
1052 tooltip_hidden_button = tooltip_hovered_button;
1053 ToolTipHide (false);
1055 ToolTipShow (false);
1058 // Called from timer (with only_refresh = false)
1059 // Called from ToolTipStart if tooltip is already shown (with only_refresh = true)
1060 public void ToolTipShow (bool only_refresh)
1065 string text = Locale.GetText (tooltip_hovered_button.Caption.ToString ());
1067 tooltip_timer.Interval = tooltip_hide_interval;
1068 tooltip_timer.Enabled = true;
1070 if (only_refresh && (tooltip == null || !tooltip.Visible)) {
1074 if (tooltip == null)
1075 tooltip = new ToolTip.ToolTipWindow ();
1076 else if (tooltip.Text == text && tooltip.Visible)
1078 else if (tooltip.Visible)
1079 tooltip.Visible = false;
1081 if (form.WindowState == FormWindowState.Maximized && form.MdiParent != null)
1082 tooltip.Present (form.MdiParent, text);
1084 tooltip.Present (form, text);
1088 // Called from MouseLeave (with reset_hidden_button = true)
1089 // Called from MouseDown (with reset_hidden_button = false)
1090 // Called from MouseMove if mouse isn't over any button (with reset_hidden_button = false)
1091 // Called from Timer if hiding (with reset_hidden_button = false)
1092 public void ToolTipHide (bool reset_hidden_button)
1094 if (tooltip_timer != null)
1095 tooltip_timer.Enabled = false;
1096 if (tooltip != null && tooltip.Visible)
1097 tooltip.Visible = false;
1098 if (reset_hidden_button)
1099 tooltip_hidden_button = null;
1103 public bool MouseMove (int x, int y)
1109 bool any_change = false;
1110 bool any_pushed_buttons = AnyPushedTitleButtons;
1111 bool any_tooltip = false;
1112 TitleButton over_button = FindButton (x, y);
1114 foreach (TitleButton button in this) {
1118 if (button.State == ButtonState.Inactive)
1121 if (button == over_button) {
1122 if (any_pushed_buttons) {
1123 any_change |= button.State != ButtonState.Pushed;
1124 button.State = ButtonState.Pushed;
1126 ToolTipStart (button);
1128 if (!button.Entered) {
1129 button.Entered = true;
1130 if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
1134 if (any_pushed_buttons) {
1135 any_change |= button.State != ButtonState.Normal;
1136 button.State = ButtonState.Normal;
1138 if (button.Entered) {
1139 button.Entered = false;
1140 if (ThemeEngine.Current.ManagedWindowTitleButtonHasHotElementStyle (button, form))
1147 ToolTipHide (false);
1152 public void MouseDown (int x, int y)
1158 ToolTipHide (false);
1160 foreach (TitleButton button in this) {
1161 if (button != null && button.State != ButtonState.Inactive) {
1162 button.State = ButtonState.Normal;
1165 TitleButton clicked_button = FindButton (x, y);
1166 if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
1167 clicked_button.State = ButtonState.Pushed;
1171 public void MouseUp (int x, int y)
1177 TitleButton clicked_button = FindButton (x, y);
1178 if (clicked_button != null && clicked_button.State != ButtonState.Inactive) {
1179 clicked_button.OnClick ();
1182 foreach (TitleButton button in this) {
1183 if (button == null || button.State == ButtonState.Inactive)
1186 button.State = ButtonState.Normal;
1189 if (clicked_button == CloseButton && !form.closing)
1190 XplatUI.InvalidateNC (form.Handle);
1195 internal void MouseLeave (int x, int y)
1201 foreach (TitleButton button in this) {
1202 if (button == null || button.State == ButtonState.Inactive)
1205 button.State = ButtonState.Normal;