1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //	Jackson Harper (jackson@ximian.com)
24 //
25 //
26 
27 
28 using System;
29 using System.Drawing;
30 using System.Drawing.Drawing2D;
31 using System.Runtime.InteropServices;
32 
33 namespace System.Windows.Forms {
34 
35 	internal class MdiWindowManager : InternalWindowManager {
36 
37 		private MainMenu merged_menu;
38 		private MainMenu maximized_menu;
39 		private MenuItem icon_menu;
40 		private ContextMenu icon_popup_menu;
41 		internal bool was_minimized;
42 
43 		private PaintEventHandler draw_maximized_buttons;
44 		internal EventHandler form_closed_handler;
45 
46 		private MdiClient mdi_container;
47 		private Rectangle prev_virtual_position;
48 
49 		private Point icon_clicked;
50 		private DateTime icon_clicked_time;
51 		private bool icon_dont_show_popup;
52 
53 		private TitleButtons maximized_title_buttons;
54 		private bool is_visible_pending;
55 		private byte last_activation_event; // 0 = none, 1 = activated, 2 = deactivated.
56 
RaiseActivated()57 		public void RaiseActivated ()
58 		{
59 			if (last_activation_event == 1)
60 				return;
61 
62 			last_activation_event = 1;
63 			form.OnActivatedInternal ();
64 			form.SelectActiveControl ();
65 		}
66 
RaiseDeactivate()67 		public void RaiseDeactivate ()
68 		{
69 			if (last_activation_event != 1)
70 				return;
71 			last_activation_event = 2;
72 			form.OnDeactivateInternal ();
73 		}
74 
75 		public override int MenuHeight {
76 			get {
77 				// Mdi children don't get menus on the form, they're shown on the main form.
78 				return 0;
79 			}
80 		}
81 
82 		internal bool IsVisiblePending {
83 			get {
84 				return is_visible_pending;
85 			}
86 			set {
87 				is_visible_pending = value;
88 			}
89 		}
90 
91 		private TitleButtons MaximizedTitleButtons {
92 			get {
93 				if (maximized_title_buttons == null) {
94 					maximized_title_buttons = new TitleButtons (this.Form);
95 					maximized_title_buttons.CloseButton.Visible = true;
96 					maximized_title_buttons.RestoreButton.Visible = true;
97 					maximized_title_buttons.MinimizeButton.Visible = true;
98 				}
99 				return maximized_title_buttons;
100 			}
101 		}
102 
103 		internal override Rectangle MaximizedBounds {
104 			get {
105 				Rectangle pb = mdi_container.ClientRectangle;
106 				int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
107 				int tw = TitleBarHeight;
108 
109 				Rectangle new_bounds = new Rectangle (pb.Left - bw,
110 						pb.Top - tw - bw,
111 						pb.Width + bw * 2,
112 						pb.Height + tw + bw * 2);
113 				return new_bounds;
114 			}
115 		}
116 
117 
118 
MdiWindowManager(Form form, MdiClient mdi_container)119 		public MdiWindowManager (Form form, MdiClient mdi_container) : base (form)
120 		{
121 			this.mdi_container = mdi_container;
122 			if (form.WindowState == FormWindowState.Normal) {
123 				NormalBounds = form.Bounds;
124 			}
125 			form_closed_handler = new EventHandler (FormClosed);
126 			form.Closed += form_closed_handler;
127 			form.TextChanged += new EventHandler (FormTextChangedHandler);
128 			form.SizeChanged += new EventHandler (FormSizeChangedHandler);
129 			form.LocationChanged += new EventHandler (FormLocationChangedHandler);
130 			form.VisibleChanged += new EventHandler (FormVisibleChangedHandler);
131 			draw_maximized_buttons = new PaintEventHandler (DrawMaximizedButtons);
132 			CreateIconMenus ();
133 		}
134 
FormVisibleChangedHandler(object sender, EventArgs e)135 		private void FormVisibleChangedHandler (object sender, EventArgs e)
136 		{
137 			if (mdi_container == null)
138 				return;
139 
140 			if (form.Visible) {
141 				mdi_container.ActivateChild (form);
142 			} else if (mdi_container.Controls.Count > 1) {
143 				mdi_container.ActivateActiveMdiChild ();
144 			}
145 		}
146 
FormTextChangedHandler(object sender, EventArgs e)147 		private void FormTextChangedHandler (object sender, EventArgs e)
148 		{
149 			mdi_container.SetParentText (false);
150 
151 			if (form.MdiParent.MainMenuStrip != null)
152 				form.MdiParent.MainMenuStrip.RefreshMdiItems ();
153 		}
154 
FormLocationChangedHandler(object sender, EventArgs e)155 		private void FormLocationChangedHandler (object sender, EventArgs e)
156 		{
157 			if (form.window_state == FormWindowState.Minimized)
158 				IconicBounds = form.Bounds;
159 			form.MdiParent.MdiContainer.SizeScrollBars ();
160 		}
161 
FormSizeChangedHandler(object sender, EventArgs e)162 		private void FormSizeChangedHandler (object sender, EventArgs e)
163 		{
164 			if (form.window_state == FormWindowState.Maximized && form.Bounds != MaximizedBounds)
165 				form.Bounds = MaximizedBounds;
166 
167 			form.MdiParent.MdiContainer.SizeScrollBars ();
168 		}
169 
170 		public MainMenu MergedMenu {
171 			get {
172 				if (merged_menu == null)
173 					merged_menu = CreateMergedMenu ();
174 				return merged_menu;
175 			}
176 		}
177 
CreateMergedMenu()178 		private MainMenu CreateMergedMenu ()
179 		{
180 			Form parent = (Form) mdi_container.Parent;
181 			MainMenu clone;
182 			if (parent.Menu != null)
183 				clone = (MainMenu) parent.Menu.CloneMenu ();
184 			else
185 				clone = new MainMenu ();
186 
187 			if (form.WindowState == FormWindowState.Maximized) {
188 
189 			}
190 			clone.MergeMenu (form.Menu);
191 			clone.MenuChanged += new EventHandler (MenuChangedHandler);
192 			clone.SetForm (parent);
193 			return clone;
194 		}
195 
196 		public MainMenu MaximizedMenu {
197 			get {
198 				if (maximized_menu == null)
199 					maximized_menu = CreateMaximizedMenu ();
200 				return maximized_menu;
201 			}
202 		}
203 
CreateMaximizedMenu()204 		private MainMenu CreateMaximizedMenu ()
205 		{
206 			Form parent = (Form) mdi_container.Parent;
207 
208 			if (form.MainMenuStrip != null || parent.MainMenuStrip != null)
209 				return null;
210 
211 			MainMenu res = new MainMenu ();
212 
213 			if (parent.Menu != null) {
214 				MainMenu clone = (MainMenu) parent.Menu.CloneMenu ();
215 				res.MergeMenu (clone);
216 			}
217 
218 			if (form.Menu != null) {
219 				MainMenu clone = (MainMenu) form.Menu.CloneMenu ();
220 				res.MergeMenu (clone);
221 			}
222 
223 			if (res.MenuItems.Count == 0)
224 				res.MenuItems.Add (new MenuItem ()); // Dummy item to get the menu height correct
225 
226 			res.MenuItems.Insert (0, icon_menu);
227 
228 			res.SetForm (parent);
229 			return res;
230 		}
231 
CreateIconMenus()232 		private void CreateIconMenus ()
233 		{
234 			icon_menu = new MenuItem ();
235 			icon_popup_menu = new ContextMenu ();
236 
237 			icon_menu.OwnerDraw = true;
238 			icon_menu.MeasureItem += new MeasureItemEventHandler (MeasureIconMenuItem);
239 			icon_menu.DrawItem += new DrawItemEventHandler (DrawIconMenuItem);
240 			icon_menu.Click += new EventHandler (ClickIconMenuItem);
241 
242 			MenuItem restore = new MenuItem ("&Restore", new EventHandler (RestoreItemHandler));
243 			MenuItem move = new MenuItem ("&Move", new EventHandler (MoveItemHandler));
244 			MenuItem size = new MenuItem ("&Size", new EventHandler (SizeItemHandler));
245 			MenuItem minimize = new MenuItem ("Mi&nimize", new EventHandler (MinimizeItemHandler));
246 			MenuItem maximize = new MenuItem ("Ma&ximize", new EventHandler (MaximizeItemHandler));
247 			MenuItem close = new MenuItem ("&Close", new EventHandler (CloseItemHandler));
248 			MenuItem next = new MenuItem ("Nex&t", new EventHandler (NextItemHandler));
249 
250 			icon_menu.MenuItems.AddRange (new MenuItem [] { restore, move, size, minimize,
251 									maximize, close, next });
252 			icon_popup_menu.MenuItems.AddRange (new MenuItem [] { restore, move, size, minimize,
253 									maximize, close, next });
254 		}
255 
ClickIconMenuItem(object sender, EventArgs e)256 		private void ClickIconMenuItem(object sender, EventArgs e)
257 		{
258 			if ((DateTime.Now - icon_clicked_time).TotalMilliseconds <= SystemInformation.DoubleClickTime) {
259 				form.Close ();
260 				return;
261 			}
262 			icon_clicked_time = DateTime.Now;
263 			Point pnt = Point.Empty;
264 			pnt = form.MdiParent.PointToScreen (pnt);
265 			pnt = form.PointToClient (pnt);
266 			ShowPopup (pnt);
267 		}
268 
ShowPopup(Point pnt)269 		internal void ShowPopup (Point pnt)
270 		{
271 			// If we are using MainMenuStrip, display that menu instead
272 			if (form.WindowState == FormWindowState.Maximized && form.MdiParent.MainMenuStrip != null)
273 				if (form.MdiParent.MainMenuStrip.Items.Count > 0) {
274 					ToolStripItem tsi = form.MdiParent.MainMenuStrip.Items[0];
275 
276 					if (tsi is MdiControlStrip.SystemMenuItem) {
277 						(tsi as MdiControlStrip.SystemMenuItem).ShowDropDown ();
278 						return;
279 					}
280 				}
281 
282 			icon_popup_menu.MenuItems[0].Enabled = form.window_state != FormWindowState.Normal;    // restore
283 			icon_popup_menu.MenuItems[1].Enabled = form.window_state != FormWindowState.Maximized; // move
284 			icon_popup_menu.MenuItems[2].Enabled = form.window_state != FormWindowState.Maximized; // size
285 			icon_popup_menu.MenuItems[3].Enabled = form.window_state != FormWindowState.Minimized; // minimize
286 			icon_popup_menu.MenuItems[4].Enabled = form.window_state != FormWindowState.Maximized; // maximize
287 			icon_popup_menu.MenuItems[5].Enabled = true;  // close
288 			icon_popup_menu.MenuItems[6].Enabled = true;  // next
289 
290 			icon_popup_menu.Show(form, pnt);
291 		}
292 
RestoreItemHandler(object sender, EventArgs e)293 		private void RestoreItemHandler (object sender, EventArgs e)
294 		{
295 			form.WindowState = FormWindowState.Normal;
296 		}
297 
MoveItemHandler(object sender, EventArgs e)298 		private void MoveItemHandler (object sender, EventArgs e)
299 		{
300 			int x = 0;
301 			int y = 0;
302 
303 			PointToScreen (ref x, ref y);
304 			Cursor.Position = new Point (x, y);
305 			form.Cursor = Cursors.Cross;
306 			state = State.Moving;
307 			form.Capture = true;
308 		}
309 
SizeItemHandler(object sender, EventArgs e)310 		private void SizeItemHandler (object sender, EventArgs e)
311 		{
312 			int x = 0;
313 			int y = 0;
314 
315 			PointToScreen (ref x, ref y);
316 			Cursor.Position = new Point (x, y);
317 			form.Cursor = Cursors.Cross;
318 			state = State.Sizing;
319 			form.Capture = true;
320 		}
321 
MinimizeItemHandler(object sender, EventArgs e)322 		private void MinimizeItemHandler (object sender, EventArgs e)
323 		{
324 			form.WindowState = FormWindowState.Minimized;
325 		}
326 
MaximizeItemHandler(object sender, EventArgs e)327 		private void MaximizeItemHandler (object sender, EventArgs e)
328 		{
329 			if (form.WindowState != FormWindowState.Maximized)
330 				form.WindowState = FormWindowState.Maximized;
331 		}
332 
CloseItemHandler(object sender, EventArgs e)333 		private void CloseItemHandler (object sender, EventArgs e)
334 		{
335 			form.Close ();
336 		}
337 
NextItemHandler(object sender, EventArgs e)338 		private void NextItemHandler (object sender, EventArgs e)
339 		{
340 			mdi_container.ActivateNextChild ();
341 		}
342 
DrawIconMenuItem(object sender, DrawItemEventArgs de)343 		private void DrawIconMenuItem (object sender, DrawItemEventArgs de)
344 		{
345 			de.Graphics.DrawIcon (form.Icon, new Rectangle (de.Bounds.X + 2, de.Bounds.Y + 2,
346 							      de.Bounds.Height - 4, de.Bounds.Height - 4));
347 		}
348 
MeasureIconMenuItem(object sender, MeasureItemEventArgs me)349 		private void MeasureIconMenuItem (object sender, MeasureItemEventArgs me)
350 		{
351 			int size = SystemInformation.MenuHeight;
352 			me.ItemHeight = size;
353 			me.ItemWidth = size + 2; // some padding
354 		}
355 
MenuChangedHandler(object sender, EventArgs e)356 		private void MenuChangedHandler (object sender, EventArgs e)
357 		{
358 			CreateMergedMenu ();
359 		}
360 
PointToClient(ref int x, ref int y)361 		public override void PointToClient (ref int x, ref int y)
362 		{
363 			XplatUI.ScreenToClient (mdi_container.Handle, ref x, ref y);
364 		}
365 
PointToScreen(ref int x, ref int y)366 		public override void PointToScreen (ref int x, ref int y)
367 		{
368 			XplatUI.ClientToScreen (mdi_container.Handle, ref x, ref y);
369 		}
370 
UpdateWindowDecorations(FormWindowState window_state)371 		public override void UpdateWindowDecorations (FormWindowState window_state)
372 		{
373 			if (MaximizedMenu != null) {
374 				switch (window_state) {
375 				case FormWindowState.Minimized:
376 				case FormWindowState.Normal:
377 					MaximizedMenu.Paint -= draw_maximized_buttons;
378 					MaximizedTitleButtons.Visible = false;
379 					TitleButtons.Visible = true;
380 					break;
381 				case FormWindowState.Maximized:
382 					MaximizedMenu.Paint += draw_maximized_buttons;
383 					MaximizedTitleButtons.Visible = true;
384 					TitleButtons.Visible = false;
385 					break;
386 				}
387 			}
388 
389 			base.UpdateWindowDecorations (window_state);
390 		}
391 
SetWindowState(FormWindowState old_state, FormWindowState window_state)392 		public override void SetWindowState (FormWindowState old_state, FormWindowState window_state)
393 		{
394 			mdi_container.SetWindowState (form, old_state, window_state, false);
395 		}
396 
FormClosed(object sender, EventArgs e)397 		private void FormClosed (object sender, EventArgs e)
398 		{
399 			mdi_container.ChildFormClosed (form);
400 
401 			if (form.MdiParent.MainMenuStrip != null)
402 				form.MdiParent.MainMenuStrip.RefreshMdiItems ();
403 
404 			mdi_container.RemoveControlMenuItems (this);
405 		}
406 
DrawMaximizedButtons(object sender, PaintEventArgs pe)407 		public override void DrawMaximizedButtons (object sender, PaintEventArgs pe)
408 		{
409 			Size bs = ThemeEngine.Current.ManagedWindowGetMenuButtonSize (this);
410 			Point pnt =  XplatUI.GetMenuOrigin (mdi_container.ParentForm.Handle);
411 			int bw = ThemeEngine.Current.ManagedWindowBorderWidth (this);
412 			TitleButtons buttons = MaximizedTitleButtons;
413 
414 			buttons.Visible = true;
415 			TitleButtons.Visible = false;
416 
417 			buttons.CloseButton.Rectangle = new Rectangle (mdi_container.ParentForm.Size.Width - 1 - bw - bs.Width - 2,
418 					pnt.Y + 2, bs.Width, bs.Height);
419 
420 			buttons.RestoreButton.Rectangle = new Rectangle (buttons.CloseButton.Rectangle.Left - 2 - bs.Width,
421 					pnt.Y + 2, bs.Width, bs.Height);
422 
423 			buttons.MinimizeButton.Rectangle = new Rectangle (buttons.RestoreButton.Rectangle.Left - bs.Width,
424 					pnt.Y + 2, bs.Width, bs.Height);
425 
426 			DrawTitleButton (pe.Graphics, buttons.MinimizeButton, pe.ClipRectangle);
427 			DrawTitleButton (pe.Graphics, buttons.RestoreButton, pe.ClipRectangle);
428 			DrawTitleButton (pe.Graphics, buttons.CloseButton, pe.ClipRectangle);
429 
430 			buttons.MinimizeButton.Rectangle.Y -= pnt.Y;
431 			buttons.RestoreButton.Rectangle.Y -= pnt.Y;
432 			buttons.CloseButton.Rectangle.Y -= pnt.Y;
433 		}
434 
HandleMenuMouseDown(MainMenu menu, int x, int y)435 		public bool HandleMenuMouseDown (MainMenu menu, int x, int y)
436 		{
437 			Point pt = MenuTracker.ScreenToMenu (menu, new Point (x, y));
438 
439 			HandleTitleBarDown (pt.X, pt.Y);
440 			return TitleButtons.AnyPushedTitleButtons;
441 		}
442 
HandleMenuMouseUp(MainMenu menu, int x, int y)443 		public void HandleMenuMouseUp (MainMenu menu, int x, int y)
444 		{
445 			Point pt = MenuTracker.ScreenToMenu (menu, new Point (x, y));
446 
447 			HandleTitleBarUp (pt.X, pt.Y);
448 		}
449 
HandleMenuMouseLeave(MainMenu menu, int x, int y)450 		public void HandleMenuMouseLeave (MainMenu menu, int x, int y)
451 		{
452 			Point pt = MenuTracker.ScreenToMenu (menu, new Point (x, y));
453 			HandleTitleBarLeave (pt.X, pt.Y);
454 
455 		}
456 
HandleMenuMouseMove(MainMenu menu, int x, int y)457 		public void HandleMenuMouseMove (MainMenu menu, int x, int y)
458 		{
459 			Point pt = MenuTracker.ScreenToMenu (menu, new Point (x, y));
460 
461 			HandleTitleBarMouseMove (pt.X, pt.Y);
462 
463 		}
464 
HandleTitleBarLeave(int x, int y)465 		protected override void HandleTitleBarLeave (int x, int y)
466 		{
467 			base.HandleTitleBarLeave (x, y);
468 
469 			if (maximized_title_buttons != null) {
470 				maximized_title_buttons.MouseLeave (x, y);
471 			}
472 
473 			if (IsMaximized)
474 				XplatUI.InvalidateNC (form.MdiParent.Handle);
475 		}
476 
HandleTitleBarUp(int x, int y)477 		protected override void HandleTitleBarUp (int x, int y)
478 		{
479 			if (IconRectangleContains (x, y)) {
480 				if (!icon_dont_show_popup) {
481 					if (IsMaximized)
482 						ClickIconMenuItem (null, null);
483 					else
484 						ShowPopup (Point.Empty);
485 				} else {
486 					icon_dont_show_popup = false;
487 				}
488 				return;
489 			}
490 
491 			bool was_maximized = IsMaximized;
492 			base.HandleTitleBarUp (x, y);
493 			if (maximized_title_buttons != null && was_maximized) {
494 				maximized_title_buttons.MouseUp (x, y);
495 			}
496 
497 			if (IsMaximized)
498 				XplatUI.InvalidateNC (mdi_container.Parent.Handle);
499 		}
500 
HandleTitleBarDoubleClick(int x, int y)501 		protected override void HandleTitleBarDoubleClick (int x, int y)
502 		{
503 			if (IconRectangleContains (x, y)) {
504 				form.Close ();
505 			} else if (form.MaximizeBox == true) {
506 				form.WindowState = FormWindowState.Maximized;
507 			}
508 			base.HandleTitleBarDoubleClick (x, y);
509 		}
510 
HandleTitleBarDown(int x, int y)511 		protected override void HandleTitleBarDown (int x, int y)
512 		{
513 			if (IconRectangleContains (x, y)) {
514 				if ((DateTime.Now - icon_clicked_time).TotalMilliseconds <= SystemInformation.DoubleClickTime && icon_clicked.X == x && icon_clicked.Y == y) {
515 					form.Close ();
516 				} else {
517 					icon_clicked_time = DateTime.Now;
518 					icon_clicked.X = x;
519 					icon_clicked.Y = y;
520 				}
521 
522 				return;
523 			}
524 
525 			base.HandleTitleBarDown (x, y);
526 
527 			if (maximized_title_buttons != null) {
528 				maximized_title_buttons.MouseDown (x, y);
529 			}
530 
531 			if (IsMaximized) {
532 				XplatUI.InvalidateNC (mdi_container.Parent.Handle);
533 			}
534 		}
535 
HandleTitleBarMouseMove(int x, int y)536 		protected override void HandleTitleBarMouseMove (int x, int y)
537 		{
538 			base.HandleTitleBarMouseMove (x, y);
539 
540 			if (maximized_title_buttons != null && maximized_title_buttons.MouseMove (x, y))
541 				XplatUI.InvalidateNC (form.MdiParent.Handle);
542 		}
543 
HandleLButtonDblClick(ref Message m)544 		protected override bool HandleLButtonDblClick (ref Message m)
545 		{
546 
547 			int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
548 			int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
549 
550 			// Correct since we are in NC land.
551 			NCClientToNC (ref x, ref y);
552 
553 			if (IconRectangleContains (x, y)) {
554 				icon_popup_menu.Wnd.Hide ();
555 				form.Close ();
556 				return true;
557 			}
558 
559 			return base.HandleLButtonDblClick (ref m);
560 		}
561 
HandleLButtonDown(ref Message m)562 		protected override bool HandleLButtonDown (ref Message m)
563 		{
564 
565 			int x = Control.LowOrder ((int)m.LParam.ToInt32 ());
566 			int y = Control.HighOrder ((int)m.LParam.ToInt32 ());
567 
568 			// Correct y since we are in NC land.
569 			NCClientToNC(ref x, ref y);
570 
571 			if (IconRectangleContains (x, y)){
572 				if ((DateTime.Now - icon_clicked_time).TotalMilliseconds <= SystemInformation.DoubleClickTime) {
573 					if (icon_popup_menu != null && icon_popup_menu.Wnd != null) {
574 						icon_popup_menu.Wnd.Hide ();
575 					}
576 					form.Close ();
577 					return true;
578 				} else if (form.Capture) {
579 					icon_dont_show_popup = true;
580 				}
581 			}
582 			return base.HandleLButtonDown (ref m);
583 		}
584 
ShouldRemoveWindowManager(FormBorderStyle style)585 		protected override bool ShouldRemoveWindowManager (FormBorderStyle style)
586 		{
587 			return false;
588 		}
589 
HandleWindowMove(Message m)590 		protected override void HandleWindowMove (Message m)
591 		{
592 			Point pos = Cursor.Position;
593 			Point move = MouseMove (pos);
594 
595 			if (move.X == 0 && move.Y == 0)
596 				return;
597 
598 			int x = virtual_position.X + move.X;
599 			int y = virtual_position.Y + move.Y;
600 
601 			Rectangle client = mdi_container.ClientRectangle;
602 			if (mdi_container.VerticalScrollbarVisible)
603 				client.Width -= SystemInformation.VerticalScrollBarWidth;
604 			if (mdi_container.HorizontalScrollbarVisible)
605 				client.Height -= SystemInformation.HorizontalScrollBarHeight;
606 
607 			UpdateVP (x, y, form.Width, form.Height);
608 
609 			start = pos;
610 		}
611 
HandleNCMouseMove(ref Message m)612 		protected override bool HandleNCMouseMove (ref Message m)
613 		{
614 			XplatUI.RequestAdditionalWM_NCMessages (form.Handle, true, true);
615 			return base.HandleNCMouseMove (ref m);
616 		}
617 
DrawVirtualPosition(Rectangle virtual_position)618 		protected override void DrawVirtualPosition (Rectangle virtual_position)
619 		{
620 			ClearVirtualPosition ();
621 
622 			if (form.Parent != null)
623 				XplatUI.DrawReversibleRectangle (form.Parent.Handle, virtual_position, 2);
624 			prev_virtual_position = virtual_position;
625 		}
626 
ClearVirtualPosition()627 		protected override void ClearVirtualPosition ()
628 		{
629 			if (prev_virtual_position != Rectangle.Empty && form.Parent != null)
630 				XplatUI.DrawReversibleRectangle (form.Parent.Handle,
631 						prev_virtual_position, 2);
632 			prev_virtual_position = Rectangle.Empty;
633 		}
634 
OnWindowFinishedMoving()635 		protected override void OnWindowFinishedMoving ()
636 		{
637 			form.Refresh ();
638 		}
639 
640 		public override bool IsActive {
641 			get {
642 				if (mdi_container == null)
643 					return false;
644 				return mdi_container.ActiveMdiChild == form;
645 			}
646 		}
647 
Activate()648 		protected override void Activate ()
649 		{
650 			if (mdi_container.ActiveMdiChild != form) {
651 				mdi_container.ActivateChild (form);
652 			}
653 			base.Activate ();
654 		}
655 	}
656 }
657 
658