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 // Peter Bartok pbartok@novell.com 24 // 25 // 26 27 // NOT COMPLETE 28 29 using System.Collections; 30 using System.ComponentModel; 31 using System.Drawing; 32 using System.Runtime.InteropServices; 33 34 namespace System.Windows.Forms { 35 [ComVisible (true)] 36 [ClassInterface(ClassInterfaceType.AutoDispatch)] 37 [DesignTimeVisible(false)] 38 [ToolboxItem(false)] 39 public sealed class MdiClient : Control { 40 #region Local Variables 41 private int mdi_created; 42 private ImplicitHScrollBar hbar; 43 private ImplicitVScrollBar vbar; 44 private SizeGrip sizegrip; 45 private int hbar_value; 46 private int vbar_value; 47 private bool lock_sizing; 48 private bool initializing_scrollbars; 49 private int prev_bottom; 50 private bool setting_windowstates = false; 51 internal ArrayList mdi_child_list; 52 private string form_text; 53 private bool setting_form_text; 54 private Form active_child; 55 56 #endregion // Local Variables 57 58 #region Public Classes 59 [ComVisible (false)] 60 public new class ControlCollection : Control.ControlCollection { 61 62 private MdiClient owner; 63 ControlCollection(MdiClient owner)64 public ControlCollection(MdiClient owner) : base(owner) { 65 this.owner = owner; 66 } 67 Add(Control value)68 public override void Add(Control value) { 69 if ((value is Form) == false || !(((Form)value).IsMdiChild)) { 70 throw new ArgumentException("Form must be MdiChild"); 71 } 72 owner.mdi_child_list.Add (value); 73 base.Add (value); 74 75 // newest member is the active one 76 Form form = (Form) value; 77 owner.ActiveMdiChild = form; 78 } 79 Remove(Control value)80 public override void Remove(Control value) 81 { 82 Form form = value as Form; 83 if (form != null) { 84 MdiWindowManager wm = form.WindowManager as MdiWindowManager; 85 if (wm != null) { 86 form.Closed -= wm.form_closed_handler; 87 } 88 } 89 90 owner.mdi_child_list.Remove (value); 91 base.Remove (value); 92 } 93 } 94 #endregion // Public Classes 95 96 #region Public Constructors MdiClient()97 public MdiClient() 98 { 99 mdi_child_list = new ArrayList (); 100 BackColor = SystemColors.AppWorkspace; 101 Dock = DockStyle.Fill; 102 SetStyle (ControlStyles.Selectable, false); 103 } 104 #endregion // Public Constructors 105 SendFocusToActiveChild()106 internal void SendFocusToActiveChild () 107 { 108 Form active = this.ActiveMdiChild; 109 if (active == null) { 110 ParentForm.SendControlFocus (this); 111 } else { 112 active.SendControlFocus (active); 113 ParentForm.ActiveControl = active; 114 } 115 } 116 117 internal bool HorizontalScrollbarVisible { 118 get { return hbar != null && hbar.Visible; } 119 } 120 internal bool VerticalScrollbarVisible { 121 get { return vbar != null && vbar.Visible; } 122 } 123 SetParentText(bool text_changed)124 internal void SetParentText(bool text_changed) 125 { 126 if (setting_form_text) 127 return; 128 129 setting_form_text = true; 130 131 if (text_changed) 132 form_text = ParentForm.Text; 133 134 if (ParentForm.ActiveMaximizedMdiChild == null) { 135 ParentForm.Text = form_text; 136 } else { 137 string childText = ParentForm.ActiveMaximizedMdiChild.form.Text; 138 if (childText.Length > 0) { 139 ParentForm.Text = form_text + " - [" + ParentForm.ActiveMaximizedMdiChild.form.Text + "]"; 140 } else { 141 ParentForm.Text = form_text; 142 } 143 } 144 145 setting_form_text = false; 146 } 147 OnPaintBackgroundInternal(PaintEventArgs pe)148 internal override void OnPaintBackgroundInternal (PaintEventArgs pe) 149 { 150 if (BackgroundImage != null) 151 return; 152 153 if (Parent == null || Parent.BackgroundImage == null) 154 return; 155 Parent.PaintControlBackground (pe); 156 } 157 158 internal Form ParentForm { 159 get { return (Form) Parent; } 160 } 161 CreateControlsInstance()162 protected override Control.ControlCollection CreateControlsInstance () 163 { 164 return new MdiClient.ControlCollection (this); 165 } 166 WndProc(ref Message m)167 protected override void WndProc(ref Message m) { 168 switch ((Msg)m.Msg) { 169 case Msg.WM_NCPAINT: 170 PaintEventArgs pe = XplatUI.PaintEventStart (ref m, Handle, false); 171 172 Rectangle clip; 173 clip = new Rectangle (0, 0, Width, Height); 174 175 ControlPaint.DrawBorder3D (pe.Graphics, clip, Border3DStyle.Sunken); 176 XplatUI.PaintEventEnd (ref m, Handle, false); 177 m.Result = IntPtr.Zero; 178 return ; 179 } 180 181 base.WndProc (ref m); 182 } 183 OnResize(EventArgs e)184 protected override void OnResize (EventArgs e) 185 { 186 base.OnResize (e); 187 188 if (Parent != null && Parent.IsHandleCreated) 189 XplatUI.InvalidateNC (Parent.Handle); 190 // Should probably make this into one loop 191 SizeScrollBars (); 192 ArrangeWindows (); 193 } 194 ScaleControl(SizeF factor, BoundsSpecified specified)195 protected override void ScaleControl (SizeF factor, BoundsSpecified specified) 196 { 197 // Never change the MdiClient's location 198 specified &= ~BoundsSpecified.Location; 199 200 base.ScaleControl (factor, specified); 201 } 202 203 [System.ComponentModel.EditorBrowsable (EditorBrowsableState.Never)] ScaleCore(float dx, float dy)204 protected override void ScaleCore (float dx, float dy) 205 { 206 base.ScaleCore (dx, dy); 207 } 208 SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)209 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified) 210 { 211 base.SetBoundsCore (x, y, width, height, specified); 212 } 213 214 #region Public Instance Properties 215 [Localizable(true)] 216 public override System.Drawing.Image BackgroundImage { 217 get { 218 return base.BackgroundImage; 219 } 220 set { 221 base.BackgroundImage = value; 222 } 223 } 224 225 [EditorBrowsable (EditorBrowsableState.Never)] 226 [Browsable (false)] 227 public override ImageLayout BackgroundImageLayout { 228 get { 229 return base.BackgroundImageLayout; 230 } 231 set { 232 base.BackgroundImageLayout = value; 233 } 234 } 235 236 public Form [] MdiChildren { 237 get { 238 if (mdi_child_list == null) 239 return new Form [0]; 240 return (Form []) mdi_child_list.ToArray (typeof (Form)); 241 } 242 } 243 #endregion // Public Instance Properties 244 245 #region Protected Instance Properties 246 protected override CreateParams CreateParams { 247 get { 248 CreateParams result = base.CreateParams; 249 result.ExStyle |= (int) WindowExStyles.WS_EX_CLIENTEDGE; 250 return result; 251 } 252 } 253 #endregion // Protected Instance Properties 254 255 #region Public Instance Methods LayoutMdi(MdiLayout value)256 public void LayoutMdi (MdiLayout value) { 257 258 // Don't forget to always call ArrangeIconicWindows 259 ArrangeIconicWindows (true); 260 261 switch (value) { 262 case MdiLayout.Cascade: { 263 int i = 0; 264 for (int c = Controls.Count - 1; c >= 0; c--) { 265 Form form = (Form) Controls [c]; 266 267 if (form.WindowState == FormWindowState.Minimized) 268 continue; 269 270 if (form.WindowState == FormWindowState.Maximized) 271 form.WindowState = FormWindowState.Normal; 272 273 form.Width = System.Convert.ToInt32 (ClientSize.Width * 0.8); 274 form.Height = Math.Max ( 275 System.Convert.ToInt32 (ClientSize.Height * 0.8), 276 SystemInformation.MinimumWindowSize.Height + 2); 277 278 int l = 22 * i; 279 int t = 22 * i; 280 281 if (i != 0 && (l + form.Width > ClientSize.Width || t + form.Height > ClientSize.Height)) { 282 i = 0; 283 l = 22 * i; 284 t = 22 * i; 285 } 286 287 form.Left = l; 288 form.Top = t; 289 290 i++; 291 } 292 break; 293 } 294 case MdiLayout.TileHorizontal: 295 case MdiLayout.TileVertical: { 296 // First count number of windows to tile 297 int total = 0; 298 299 // And space used by iconic windows 300 int clientHeight = ClientSize.Height; 301 302 for (int i = 0; i < Controls.Count; i++) { 303 Form form = Controls [i] as Form; 304 305 if (form == null) 306 continue; 307 308 if (!form.Visible) 309 continue; 310 311 if (form.WindowState == FormWindowState.Maximized) 312 form.WindowState = FormWindowState.Normal; 313 else if (form.WindowState == FormWindowState.Minimized) { 314 if (form.Bounds.Top < clientHeight) 315 clientHeight = form.Bounds.Top; 316 continue; 317 } 318 319 total++; 320 } 321 if (total <= 0) 322 return; 323 324 // Calculate desired height and width 325 Size newSize; 326 Size offset; 327 328 if (value == MdiLayout.TileHorizontal) { 329 newSize = new Size(ClientSize.Width, clientHeight / total); 330 offset = new Size (0, newSize.Height); 331 } else { 332 newSize = new Size(ClientSize.Width / total, clientHeight); 333 offset = new Size (newSize.Width, 0); 334 } 335 336 // Loop again and set the size and location. 337 Point nextLocation = Point.Empty; 338 339 for (int i = 0; i < Controls.Count; i++) { 340 Form form = Controls [i] as Form; 341 342 if (form == null) 343 continue; 344 345 if (!form.Visible) 346 continue; 347 348 if (form.WindowState == FormWindowState.Minimized) 349 continue; 350 351 form.Size = newSize; 352 form.Location = nextLocation; 353 nextLocation += offset; 354 } 355 356 break; 357 } 358 } 359 } 360 #endregion // Public Instance Methods 361 362 #region Protected Instance Methods 363 #endregion // Protected Instance Methods 364 SizeScrollBars()365 internal void SizeScrollBars () 366 { 367 if (lock_sizing) 368 return; 369 370 if (!IsHandleCreated) 371 return; 372 373 if (Controls.Count == 0 || ((Form) Controls [0]).WindowState == FormWindowState.Maximized) { 374 if (hbar != null) 375 hbar.Visible = false; 376 if (vbar != null) 377 vbar.Visible = false; 378 if (sizegrip != null) 379 sizegrip.Visible = false; 380 return; 381 } 382 383 int right = 0; 384 int left = 0; 385 int top = 0; 386 int bottom = 0; 387 388 foreach (Form child in Controls) { 389 if (!child.Visible) 390 continue; 391 if (child.Right > right) 392 right = child.Right; 393 if (child.Left < left) { 394 left = child.Left; 395 } 396 397 if (child.Bottom > bottom) 398 bottom = child.Bottom; 399 if (child.Top < 0) { 400 top = child.Top; 401 } 402 } 403 404 int available_width = ClientSize.Width; 405 int available_height = ClientSize.Height; 406 407 bool need_hbar = false; 408 bool need_vbar = false; 409 410 if (right - left > available_width || left < 0) { 411 need_hbar = true; 412 available_height -= SystemInformation.HorizontalScrollBarHeight; 413 } 414 if (bottom - top > available_height || top < 0) { 415 need_vbar = true; 416 available_width -= SystemInformation.VerticalScrollBarWidth; 417 418 if (!need_hbar && (right - left > available_width || left < 0)) { 419 need_hbar = true; 420 available_height -= SystemInformation.HorizontalScrollBarHeight; 421 } 422 } 423 424 if (need_hbar) { 425 if (hbar == null) { 426 hbar = new ImplicitHScrollBar (); 427 Controls.AddImplicit (hbar); 428 } 429 hbar.Visible = true; 430 CalcHBar (left, right, need_vbar); 431 } else if (hbar != null) 432 hbar.Visible = false; 433 434 if (need_vbar) { 435 if (vbar == null) { 436 vbar = new ImplicitVScrollBar (); 437 Controls.AddImplicit (vbar); 438 } 439 vbar.Visible = true; 440 CalcVBar (top, bottom, need_hbar); 441 } else if (vbar != null) 442 vbar.Visible = false; 443 444 if (need_hbar && need_vbar) { 445 if (sizegrip == null) { 446 sizegrip = new SizeGrip (this.ParentForm); 447 Controls.AddImplicit (sizegrip); 448 } 449 sizegrip.Location = new Point (hbar.Right, vbar.Bottom); 450 sizegrip.Visible = true; 451 XplatUI.SetZOrder (sizegrip.Handle, vbar.Handle, false, false); 452 } else if (sizegrip != null) { 453 sizegrip.Visible = false; 454 } 455 456 XplatUI.InvalidateNC (Handle); 457 } 458 CalcHBar(int left, int right, bool vert_vis)459 private void CalcHBar (int left, int right, bool vert_vis) 460 { 461 initializing_scrollbars = true; 462 463 hbar.Left = 0; 464 hbar.Top = ClientRectangle.Bottom - hbar.Height; 465 hbar.Width = ClientRectangle.Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0); 466 hbar.LargeChange = 50; 467 hbar.Minimum = Math.Min (left, 0); 468 hbar.Maximum = Math.Max (right - ClientSize.Width + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0), 0); 469 hbar.Value = 0; 470 hbar_value = 0; 471 hbar.ValueChanged += new EventHandler (HBarValueChanged); 472 XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false); 473 474 initializing_scrollbars = false; 475 } 476 CalcVBar(int top, int bottom, bool horz_vis)477 private void CalcVBar (int top, int bottom, bool horz_vis) 478 { 479 initializing_scrollbars = true; 480 481 vbar.Top = 0; 482 vbar.Left = ClientRectangle.Right - vbar.Width; 483 vbar.Height = ClientRectangle.Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0); 484 vbar.LargeChange = 50; 485 vbar.Minimum = Math.Min (top, 0); 486 vbar.Maximum = Math.Max (bottom - ClientSize.Height + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0), 0); 487 vbar.Value = 0; 488 vbar_value = 0; 489 vbar.ValueChanged += new EventHandler (VBarValueChanged); 490 XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false); 491 492 initializing_scrollbars = false; 493 } 494 HBarValueChanged(object sender, EventArgs e)495 private void HBarValueChanged (object sender, EventArgs e) 496 { 497 if (initializing_scrollbars) 498 return; 499 500 if (hbar.Value == hbar_value) 501 return; 502 503 lock_sizing = true; 504 505 try { 506 int diff = hbar_value - hbar.Value; 507 foreach (Form child in Controls) { 508 child.Left += diff; 509 } 510 } finally { 511 lock_sizing = false; 512 } 513 514 hbar_value = hbar.Value; 515 } 516 VBarValueChanged(object sender, EventArgs e)517 private void VBarValueChanged (object sender, EventArgs e) 518 { 519 if (initializing_scrollbars) 520 return; 521 522 if (vbar.Value == vbar_value) 523 return; 524 525 lock_sizing = true; 526 527 try { 528 int diff = vbar_value - vbar.Value; 529 foreach (Form child in Controls) { 530 child.Top += diff; 531 } 532 } finally { 533 lock_sizing = false; 534 } 535 536 vbar_value = vbar.Value; 537 } 538 ArrangeWindows()539 private void ArrangeWindows () 540 { 541 if (!IsHandleCreated) 542 return; 543 544 int change = 0; 545 if (prev_bottom != -1) 546 change = Bottom - prev_bottom; 547 548 foreach (Control c in Controls) { 549 Form child = c as Form; 550 551 if (c == null || !child.Visible) 552 continue; 553 554 MdiWindowManager wm = child.WindowManager as MdiWindowManager; 555 if (wm.GetWindowState () == FormWindowState.Maximized) 556 child.Bounds = wm.MaximizedBounds; 557 558 if (wm.GetWindowState () == FormWindowState.Minimized) { 559 child.Top += change; 560 } 561 562 } 563 564 prev_bottom = Bottom; 565 } 566 ArrangeIconicWindows(bool rearrange_all)567 internal void ArrangeIconicWindows (bool rearrange_all) 568 { 569 Rectangle rect = Rectangle.Empty; 570 571 lock_sizing = true; 572 foreach (Form form in Controls) { 573 if (form.WindowState != FormWindowState.Minimized) 574 continue; 575 576 MdiWindowManager wm = (MdiWindowManager) form.WindowManager; 577 578 if (wm.IconicBounds != Rectangle.Empty && !rearrange_all) { 579 if (form.Bounds != wm.IconicBounds) 580 form.Bounds = wm.IconicBounds; 581 continue; 582 } 583 584 bool success = true; 585 int startx, starty, currentx, currenty; 586 587 rect.Size = wm.IconicSize; 588 589 startx = 0; 590 starty = ClientSize.Height - rect.Height; 591 currentx = startx; 592 currenty = starty; 593 594 do { 595 rect.X = currentx; 596 rect.Y = currenty; 597 success = true; 598 foreach (Form form2 in Controls) { 599 if (form2 == form || form2.window_state != FormWindowState.Minimized) 600 continue; 601 602 if (form2.Bounds.IntersectsWith(rect)) { 603 success = false; 604 break; 605 } 606 } 607 if (!success) { 608 currentx += rect.Width; 609 if (currentx + rect.Width > Right) { 610 currentx = startx; 611 currenty -= rect.Height; 612 } 613 } 614 } while (!success); 615 wm.IconicBounds = rect; 616 form.Bounds = wm.IconicBounds; 617 } 618 lock_sizing = false; 619 } 620 ChildFormClosed(Form form)621 internal void ChildFormClosed (Form form) 622 { 623 FormWindowState closed_form_windowstate = form.WindowState; 624 625 form.Visible = false; 626 Controls.Remove (form); 627 628 if (Controls.Count == 0) { 629 ((MdiWindowManager) form.window_manager).RaiseDeactivate (); 630 } else if (closed_form_windowstate == FormWindowState.Maximized) { 631 Form current = (Form) Controls [0]; 632 current.WindowState = FormWindowState.Maximized; 633 ActivateChild(current); 634 } 635 636 if (Controls.Count == 0) { 637 XplatUI.RequestNCRecalc (Parent.Handle); 638 ParentForm.PerformLayout (); 639 640 // If we closed the last child, unmerge the menus. 641 // If it's not the last child, the menu will be unmerged 642 // when another child takes focus. 643 MenuStrip parent_menu = form.MdiParent.MainMenuStrip; 644 645 if (parent_menu != null) 646 if (parent_menu.IsCurrentlyMerged) 647 ToolStripManager.RevertMerge (parent_menu); 648 } 649 SizeScrollBars (); 650 SetParentText (false); 651 form.Dispose(); 652 } 653 ActivateNextChild()654 internal void ActivateNextChild () 655 { 656 if (Controls.Count < 1) 657 return; 658 if (Controls.Count == 1 && Controls[0] == ActiveMdiChild) 659 return; 660 661 Form front = (Form) Controls [0]; 662 Form form = (Form) Controls [1]; 663 664 ActivateChild (form); 665 front.SendToBack (); 666 } 667 ActivatePreviousChild()668 internal void ActivatePreviousChild () 669 { 670 if (Controls.Count <= 1) 671 return; 672 673 Form back = (Form) Controls [Controls.Count - 1]; 674 675 ActivateChild (back); 676 } 677 ActivateChild(Form form)678 internal void ActivateChild (Form form) 679 { 680 if (Controls.Count < 1) 681 return; 682 683 if (ParentForm.is_changing_visible_state > 0) 684 return; 685 686 Form current = (Form) Controls [0]; 687 bool raise_deactivate = ParentForm.ActiveControl == current; 688 689 // We want to resize the new active form before it is 690 // made active to avoid flickering. Can't do it in the 691 // normal way (form.WindowState = Maximized) since it's not 692 // active yet and everything would just return to before. 693 // We also won't suspend layout, this way the layout will 694 // happen before the form is made active (and in many cases 695 // before it is visible, which avoids flickering as well). 696 MdiWindowManager wm = (MdiWindowManager)form.WindowManager; 697 698 if (current.WindowState == FormWindowState.Maximized && form.WindowState != FormWindowState.Maximized && form.Visible) { 699 FormWindowState old_state = form.window_state; 700 SetWindowState (form, old_state, FormWindowState.Maximized, true); 701 wm.was_minimized = form.window_state == FormWindowState.Minimized; 702 form.window_state = FormWindowState.Maximized; 703 SetParentText (false); 704 } 705 706 form.BringToFront (); 707 form.SendControlFocus (form); 708 SetWindowStates (wm); 709 if (current != form) { 710 form.has_focus = false; 711 if (current.IsHandleCreated) 712 XplatUI.InvalidateNC (current.Handle); 713 if (form.IsHandleCreated) 714 XplatUI.InvalidateNC (form.Handle); 715 if (raise_deactivate) { 716 MdiWindowManager current_wm = (MdiWindowManager) current.window_manager; 717 current_wm.RaiseDeactivate (); 718 719 } 720 } 721 active_child = (Form) Controls [0]; 722 723 if (active_child.Visible) { 724 bool raise_activated = ParentForm.ActiveControl != active_child; 725 ParentForm.ActiveControl = active_child; 726 if (raise_activated) { 727 MdiWindowManager active_wm = (MdiWindowManager) active_child.window_manager; 728 active_wm.RaiseActivated (); 729 } 730 } 731 } 732 AfterTopMostControl()733 internal override IntPtr AfterTopMostControl () 734 { 735 // order of scrollbars: 736 // top = vertical 737 // sizegrid 738 // bottom = horizontal 739 if (hbar != null && hbar.Visible) 740 return hbar.Handle; 741 // no need to check for sizegrip since it will only 742 // be visible if hbar is visible. 743 if (vbar != null && vbar.Visible) 744 return vbar.Handle; 745 746 return base.AfterTopMostControl (); 747 } 748 SetWindowStates(MdiWindowManager wm)749 internal bool SetWindowStates (MdiWindowManager wm) 750 { 751 /* 752 MDI WindowState behaviour: 753 - If the active window is maximized, all other maximized windows are normalized. 754 - If a normal window gets focus and the original active window was maximized, 755 the normal window gets maximized and the original window gets normalized. 756 - If a minimized window gets focus and the original window was maximized, 757 the minimzed window gets maximized and the original window gets normalized. 758 If the ex-minimized window gets deactivated, it will be normalized. 759 */ 760 Form form = wm.form; 761 762 if (setting_windowstates) { 763 return false; 764 } 765 766 if (!form.Visible) 767 return false; 768 769 bool is_active = wm.IsActive; 770 bool maximize_this = false; 771 772 if (!is_active){ 773 return false; 774 } 775 776 ArrayList minimize_these = new ArrayList (); 777 ArrayList normalize_these = new ArrayList (); 778 779 setting_windowstates = true; 780 foreach (Form frm in mdi_child_list) { 781 if (frm == form) { 782 continue; 783 } else if (!frm.Visible){ 784 continue; 785 } 786 if (frm.WindowState == FormWindowState.Maximized && is_active) { 787 maximize_this = true; 788 if (((MdiWindowManager) frm.window_manager).was_minimized) { 789 minimize_these.Add (frm); 790 } else { 791 normalize_these.Add (frm); 792 } 793 } 794 } 795 796 if (maximize_this && form.WindowState != FormWindowState.Maximized) { 797 wm.was_minimized = form.window_state == FormWindowState.Minimized; 798 form.WindowState = FormWindowState.Maximized; 799 } 800 801 foreach (Form frm in minimize_these) 802 frm.WindowState = FormWindowState.Minimized; 803 804 foreach (Form frm in normalize_these) 805 frm.WindowState = FormWindowState.Normal; 806 807 808 SetParentText (false); 809 810 XplatUI.RequestNCRecalc (ParentForm.Handle); 811 XplatUI.RequestNCRecalc (Handle); 812 813 SizeScrollBars (); 814 815 setting_windowstates = false; 816 817 if (form.MdiParent.MainMenuStrip != null) 818 form.MdiParent.MainMenuStrip.RefreshMdiItems (); 819 820 // Implicit menu strip merging 821 // - When child is activated 822 // - Parent form must have a MainMenuStrip 823 // - Find the first menustrip on the child 824 // - Merge 825 MenuStrip parent_menu = form.MdiParent.MainMenuStrip; 826 827 if (parent_menu != null) { 828 if (parent_menu.IsCurrentlyMerged) 829 ToolStripManager.RevertMerge (parent_menu); 830 831 MenuStrip child_menu = LookForChildMenu (form); 832 833 if (form.WindowState != FormWindowState.Maximized) 834 RemoveControlMenuItems (wm); 835 836 if (form.WindowState == FormWindowState.Maximized) { 837 bool found = false; 838 839 foreach (ToolStripItem tsi in parent_menu.Items) { 840 if (tsi is MdiControlStrip.SystemMenuItem) { 841 (tsi as MdiControlStrip.SystemMenuItem).MdiForm = form; 842 found = true; 843 } else if (tsi is MdiControlStrip.ControlBoxMenuItem) { 844 (tsi as MdiControlStrip.ControlBoxMenuItem).MdiForm = form; 845 found = true; 846 } 847 } 848 849 if (!found) { 850 parent_menu.SuspendLayout (); 851 parent_menu.Items.Insert (0, new MdiControlStrip.SystemMenuItem (form)); 852 parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Close)); 853 parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Max)); 854 parent_menu.Items.Add (new MdiControlStrip.ControlBoxMenuItem (form, MdiControlStrip.ControlBoxType.Min)); 855 parent_menu.ResumeLayout (); 856 } 857 } 858 859 if (child_menu != null) 860 ToolStripManager.Merge (child_menu, parent_menu); 861 } 862 863 return maximize_this; 864 } 865 LookForChildMenu(Control parent)866 private MenuStrip LookForChildMenu (Control parent) 867 { 868 foreach (Control c in parent.Controls) { 869 if (c is MenuStrip) 870 return (MenuStrip)c; 871 872 if (c is ToolStripContainer || c is ToolStripPanel) { 873 MenuStrip ms = LookForChildMenu (c); 874 875 if (ms != null) 876 return ms; 877 } 878 } 879 880 return null; 881 } 882 RemoveControlMenuItems(MdiWindowManager wm)883 internal void RemoveControlMenuItems (MdiWindowManager wm) 884 { 885 Form form = wm.form; 886 MenuStrip parent_menu = form.MdiParent.MainMenuStrip; 887 888 // Only remove the items if the form requesting still owns the menu items 889 if (parent_menu != null) { 890 parent_menu.SuspendLayout (); 891 892 for (int i = parent_menu.Items.Count - 1; i >= 0; i--) { 893 if (parent_menu.Items[i] is MdiControlStrip.SystemMenuItem) { 894 if ((parent_menu.Items[i] as MdiControlStrip.SystemMenuItem).MdiForm == form) 895 parent_menu.Items.RemoveAt (i); 896 } else if (parent_menu.Items[i] is MdiControlStrip.ControlBoxMenuItem) { 897 if ((parent_menu.Items[i] as MdiControlStrip.ControlBoxMenuItem).MdiForm == form) 898 parent_menu.Items.RemoveAt (i); 899 } 900 } 901 902 parent_menu.ResumeLayout (); 903 } 904 } 905 SetWindowState(Form form, FormWindowState old_window_state, FormWindowState new_window_state, bool is_activating_child)906 internal void SetWindowState (Form form, FormWindowState old_window_state, FormWindowState new_window_state, bool is_activating_child) 907 { 908 bool mdiclient_layout; 909 910 MdiWindowManager wm = (MdiWindowManager) form.window_manager; 911 912 if (!is_activating_child && new_window_state == FormWindowState.Maximized && !wm.IsActive) { 913 ActivateChild (form); 914 return; 915 } 916 917 if (old_window_state == FormWindowState.Normal) 918 wm.NormalBounds = form.Bounds; 919 920 if (SetWindowStates (wm)) 921 return; 922 923 if (old_window_state == new_window_state) 924 return; 925 926 mdiclient_layout = old_window_state == FormWindowState.Maximized || new_window_state == FormWindowState.Maximized; 927 928 switch (new_window_state) { 929 case FormWindowState.Minimized: 930 ArrangeIconicWindows (false); 931 break; 932 case FormWindowState.Maximized: 933 form.Bounds = wm.MaximizedBounds; 934 break; 935 case FormWindowState.Normal: 936 form.Bounds = wm.NormalBounds; 937 break; 938 } 939 940 wm.UpdateWindowDecorations (new_window_state); 941 942 form.ResetCursor (); 943 944 if (mdiclient_layout) 945 Parent.PerformLayout (); 946 947 XplatUI.RequestNCRecalc (Parent.Handle); 948 XplatUI.RequestNCRecalc (form.Handle); 949 if (!setting_windowstates) 950 SizeScrollBars (); 951 } 952 internal int ChildrenCreated { 953 get { return mdi_created; } 954 set { mdi_created = value; } 955 } 956 957 internal Form ActiveMdiChild { 958 get { 959 if (ParentForm != null && !ParentForm.Visible) 960 return null; 961 962 if (Controls.Count < 1) 963 return null; 964 965 if (!ParentForm.IsHandleCreated) 966 return null; 967 968 if (!ParentForm.has_been_visible) 969 return null; 970 971 if (!ParentForm.Visible) 972 return active_child; 973 974 active_child = null; 975 for (int i = 0; i < Controls.Count; i++) { 976 if (Controls [i].Visible) { 977 active_child = (Form) Controls [i]; 978 break; 979 } 980 } 981 return active_child; 982 } 983 set { 984 ActivateChild (value); 985 } 986 } 987 ActivateActiveMdiChild()988 internal void ActivateActiveMdiChild () 989 { 990 if (ParentForm.is_changing_visible_state > 0) 991 return; 992 993 for (int i = 0; i < Controls.Count; i++) { 994 if (Controls [i].Visible) { 995 ActivateChild ((Form) Controls [i]); 996 return; 997 } 998 } 999 } 1000 } 1001 } 1002 1003