/// <summary> /// Invalidates the size checking to see if the furthest /// child point exceeds the current height and width. /// </summary> internal void InvalidateSize() { Point largestPoint = new Point(0, 0); for (int i = 0; i < Children.Count; i++) { MDIChild mdiChild = Children[i]; Point farPosition = new Point(mdiChild.Position.X + mdiChild.Width, mdiChild.Position.Y + mdiChild.Height); if (farPosition.X > largestPoint.X) { largestPoint.X = farPosition.X; } if (farPosition.Y > largestPoint.Y) { largestPoint.Y = farPosition.Y; } } if (_windowCanvas.Width != largestPoint.X) { _windowCanvas.Width = largestPoint.X; } if (_windowCanvas.Height != largestPoint.Y) { _windowCanvas.Height = largestPoint.Y; } }
/// <summary> /// Dependency property event once the maximize box value has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void MaximizeBoxValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { MDIChild mdiChild = (MDIChild)sender; bool visible = (bool)e.NewValue; if (visible) { bool minimizeVisible = true; if (mdiChild.minimizeButton != null) { minimizeVisible = mdiChild.minimizeButton.Visibility == Visibility.Visible; } if (mdiChild.maximizeButton != null) { mdiChild.maximizeButton.IsEnabled = true; } if (!minimizeVisible) { if (mdiChild.maximizeButton != null) { mdiChild.minimizeButton.Visibility = Visibility.Visible; } if (mdiChild.maximizeButton != null) { mdiChild.maximizeButton.Visibility = Visibility.Visible; } } } else { bool minimizeEnabled = true; if (mdiChild.minimizeButton != null) { minimizeEnabled = mdiChild.minimizeButton.IsEnabled; } if (mdiChild.maximizeButton != null) { mdiChild.maximizeButton.IsEnabled = false; } if (!minimizeEnabled) { if (mdiChild.maximizeButton != null) { mdiChild.minimizeButton.Visibility = Visibility.Hidden; } if (mdiChild.maximizeButton != null) { mdiChild.maximizeButton.Visibility = Visibility.Hidden; } } } }
/// <summary> /// Focuses a child and brings it into view. /// </summary> /// <param name="mdiChild">The MDI child.</param> internal static void Focus(MDIChild mdiChild) { if (mdiChild == null) { return; } mdiChild.Container._buttonsBorder.Child = mdiChild.Buttons; int maxZindex = 0; for (int i = 0; i < mdiChild.Container.Children.Count; i++) { int zindex = Panel.GetZIndex(mdiChild.Container.Children[i]); if (zindex > maxZindex) { maxZindex = zindex; } if (mdiChild.Container.Children[i] != mdiChild) { mdiChild.Container.Children[i].Focused = false; } else { mdiChild.Focused = true; } } Panel.SetZIndex(mdiChild, maxZindex + 1); }
/// <summary> /// Dependency property event once the position value has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void PositionValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if ((Point)e.NewValue == (Point)e.OldValue) { return; } MDIChild mdiChild = (MDIChild)sender; Point newPosition = (Point)e.NewValue; Canvas.SetTop(mdiChild, newPosition.Y < 0 ? 0 : newPosition.Y); Canvas.SetLeft(mdiChild, newPosition.X < 0 ? 0 : newPosition.X); }
private void Children_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: { MDIChild mdiChild = Children[e.NewStartingIndex], topChild = GetTopChild(); if (topChild != null && topChild.WindowState == WindowState.Maximized) { mdiChild.Loaded += (s, a) => mdiChild.WindowState = WindowState.Maximized; } mdiChild.Position = new Point(_windowOffset, _windowOffset); _windowCanvas.Children.Add(mdiChild); mdiChild.Loaded += (s, a) => Focus(mdiChild); _windowOffset += WindowOffset; if (_windowOffset + mdiChild.Width > ActualWidth) { _windowOffset = 0; } if (_windowOffset + mdiChild.Height > ActualHeight) { _windowOffset = 0; } } break; case NotifyCollectionChangedAction.Remove: { _windowCanvas.Children.Remove((MDIChild)e.OldItems[0]); Focus(GetTopChild()); } break; case NotifyCollectionChangedAction.Reset: _windowCanvas.Children.Clear(); break; } InvalidateSize(); }
/// <summary> /// Dependency property event once the focused value has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void FocusedValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { if ((bool)e.NewValue == (bool)e.OldValue) { return; } MDIChild mdiChild = (MDIChild)sender; bool focused = (bool)e.NewValue; if (focused) { mdiChild.Dispatcher.BeginInvoke(new Func <IInputElement, IInputElement>(Keyboard.Focus), System.Windows.Threading.DispatcherPriority.ApplicationIdle, mdiChild.Content); mdiChild.RaiseEvent(new RoutedEventArgs(GotFocusEvent, mdiChild)); } else { mdiChild.RaiseEvent(new RoutedEventArgs(LostFocusEvent, mdiChild)); } }
/// <summary> /// Handles the SizeChanged event of the MdiContainer control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="System.Windows.SizeChangedEventArgs"/> instance containing the event data.</param> private void MdiContainer_SizeChanged(object sender, SizeChangedEventArgs e) { if (Children.Count == 0) { return; } for (int i = 0; i < Children.Count; i++) { MDIChild mdiChild = Children[i]; if (mdiChild.WindowState == WindowState.Maximized) { mdiChild.Width = ActualWidth; mdiChild.Height = ActualHeight; } if (mdiChild.WindowState == WindowState.Minimized) { mdiChild.Position = new Point(mdiChild.Position.X, mdiChild.Position.Y + e.NewSize.Height - e.PreviousSize.Height); } } }
/// <summary> /// Focuses a child and brings it into view. /// </summary> /// <param name="mdiChild">The MDI child.</param> internal static void Focus(MDIChild mdiChild) { if (mdiChild == null) return; mdiChild.Container._buttonsBorder.Child = mdiChild.Buttons; int maxZindex = 0; for (int i = 0; i < mdiChild.Container.Children.Count; i++) { int zindex = Panel.GetZIndex(mdiChild.Container.Children[i]); if (zindex > maxZindex) maxZindex = zindex; if (mdiChild.Container.Children[i] != mdiChild) { mdiChild.Container.Children[i].Focused = false; } else mdiChild.Focused = true; } Panel.SetZIndex(mdiChild, maxZindex + 1); }
private static void MDILayoutValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { MDIContainer mdiContainer = (MDIContainer)sender; MDILayoutType value = (MDILayoutType)e.NewValue; if (value == MDILayoutType.ArrangeIcons || mdiContainer.Children.Count < 1) { return; } // 1. WindowState.Maximized -> WindowState.Normal List <MDIChild> minimizedWindows = new List <MDIChild>(), normalWindows = new List <MDIChild>(); foreach (MDIChild mdiChild in mdiContainer.Children) { switch (mdiChild.WindowState) { case WindowState.Minimized: minimizedWindows.Add(mdiChild); break; case WindowState.Maximized: mdiChild.WindowState = WindowState.Normal; normalWindows.Add(mdiChild); break; default: normalWindows.Add(mdiChild); break; } } minimizedWindows.Sort(new MDIChildComparer()); normalWindows.Sort(new MDIChildComparer()); // 2. Arrange minimized windows double containerHeight = mdiContainer.InnerHeight; for (int i = 0; i < minimizedWindows.Count; i++) { MDIChild mdiChild = minimizedWindows[i]; int capacity = Convert.ToInt32(mdiContainer.ActualWidth) / MDIChild.MinimizedWidth, row = i / capacity + 1, col = i % capacity; containerHeight = mdiContainer.InnerHeight - MDIChild.MinimizedHeight * row; double newLeft = MDIChild.MinimizedWidth * col; mdiChild.Position = new Point(newLeft, containerHeight); } // 3. Resize & arrange normal windows switch (value) { case MDILayoutType.Cascade: { double newWidth = mdiContainer.ActualWidth * 0.58, // should be non-linear formula here newHeight = containerHeight * 0.67, windowOffset = 0; foreach (MDIChild mdiChild in normalWindows) { if (mdiChild.Resizable) { mdiChild.Width = newWidth; mdiChild.Height = newHeight; } mdiChild.Position = new Point(windowOffset, windowOffset); windowOffset += WindowOffset; if (windowOffset + mdiChild.Width > mdiContainer.ActualWidth) { windowOffset = 0; } if (windowOffset + mdiChild.Height > containerHeight) { windowOffset = 0; } } } break; case MDILayoutType.TileHorizontal: { int cols = (int)Math.Sqrt(normalWindows.Count), rows = normalWindows.Count / cols; List <int> col_count = new List <int>(); // windows per column for (int i = 0; i < cols; i++) { if (normalWindows.Count % cols > cols - i - 1) { col_count.Add(rows + 1); } else { col_count.Add(rows); } } double newWidth = mdiContainer.ActualWidth / cols, newHeight = containerHeight / col_count[0], offsetTop = 0, offsetLeft = 0; for (int i = 0, col_index = 0, prev_count = 0; i < normalWindows.Count; i++) { if (i >= prev_count + col_count[col_index]) { prev_count += col_count[col_index++]; offsetLeft += newWidth; offsetTop = 0; newHeight = containerHeight / col_count[col_index]; } MDIChild mdiChild = normalWindows[i]; if (mdiChild.Resizable) { mdiChild.Width = newWidth; mdiChild.Height = newHeight; } mdiChild.Position = new Point(offsetLeft, offsetTop); offsetTop += newHeight; } } break; case MDILayoutType.TileVertical: { int rows = (int)Math.Sqrt(normalWindows.Count), cols = normalWindows.Count / rows; List <int> col_count = new List <int>(); // windows per column for (int i = 0; i < cols; i++) { if (normalWindows.Count % cols > cols - i - 1) { col_count.Add(rows + 1); } else { col_count.Add(rows); } } double newWidth = mdiContainer.ActualWidth / cols, newHeight = containerHeight / col_count[0], offsetTop = 0, offsetLeft = 0; for (int i = 0, col_index = 0, prev_count = 0; i < normalWindows.Count; i++) { if (i >= prev_count + col_count[col_index]) { prev_count += col_count[col_index++]; offsetLeft += newWidth; offsetTop = 0; newHeight = containerHeight / col_count[col_index]; } MDIChild mdiChild = normalWindows[i]; if (mdiChild.Resizable) { mdiChild.Width = newWidth; mdiChild.Height = newHeight; } mdiChild.Position = new Point(offsetLeft, offsetTop); offsetTop += newHeight; } } break; } mdiContainer.InvalidateSize(); mdiContainer.MDILayout = MDILayoutType.ArrangeIcons; }
/// <summary> /// Dependency property event once the windows state value has changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param> private static void WindowStateValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { MDIChild mdiChild = (MDIChild)sender; WindowState previousWindowState = (WindowState)e.OldValue; WindowState windowState = (WindowState)e.NewValue; if (mdiChild.Container == null || previousWindowState == windowState) { return; } if (previousWindowState == WindowState.Maximized) { for (int i = 0; i < mdiChild.Container.Children.Count; i++) { if (mdiChild.Container.Children[i] != mdiChild && mdiChild.Container.Children[i].WindowState == WindowState.Maximized && mdiChild.Container.Children[i].MaximizeBox) { mdiChild.Container.Children[i].WindowState = WindowState.Normal; } } ScrollViewer sv = (ScrollViewer)((Grid)mdiChild.Container.Content).Children[1]; sv.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; sv.VerticalScrollBarVisibility = ScrollBarVisibility.Auto; mdiChild.Buttons.Children.Clear(); mdiChild.buttonsPanel.Children.Add(mdiChild.minimizeButton); mdiChild.buttonsPanel.Children.Add(mdiChild.maximizeButton); mdiChild.buttonsPanel.Children.Add(mdiChild.closeButton); } if (previousWindowState == WindowState.Minimized) { mdiChild.minimizedPosition = mdiChild.Position; } switch (windowState) { case WindowState.Normal: { mdiChild.Position = new Point(mdiChild.originalDimension.X, mdiChild.originalDimension.Y); mdiChild.Width = mdiChild.originalDimension.Width; mdiChild.Height = mdiChild.originalDimension.Height; } break; case WindowState.Minimized: { if (previousWindowState == WindowState.Normal) { mdiChild.originalDimension = new Rect(mdiChild.Position.X, mdiChild.Position.Y, mdiChild.ActualWidth, mdiChild.ActualHeight); } double newLeft, newTop; if (mdiChild.minimizedPosition.X >= 0 || mdiChild.minimizedPosition.Y >= 0) { newLeft = mdiChild.minimizedPosition.X; newTop = mdiChild.minimizedPosition.Y; } else { int minimizedWindows = 0; for (int i = 0; i < mdiChild.Container.Children.Count; i++) { if (mdiChild.Container.Children[i] != mdiChild && mdiChild.Container.Children[i].WindowState == WindowState.Minimized) { minimizedWindows++; } } int capacity = Convert.ToInt32(mdiChild.Container.ActualWidth) / MDIChild.MinimizedWidth, row = minimizedWindows / capacity + 1, col = minimizedWindows % capacity; newTop = mdiChild.Container.InnerHeight - MDIChild.MinimizedHeight * row; newLeft = MDIChild.MinimizedWidth * col; } mdiChild.Position = new Point(newLeft, newTop); mdiChild.Width = MDIChild.MinimizedWidth; mdiChild.Height = MDIChild.MinimizedHeight; } break; case WindowState.Maximized: { if (previousWindowState == WindowState.Normal) { mdiChild.originalDimension = new Rect(mdiChild.Position.X, mdiChild.Position.Y, mdiChild.ActualWidth, mdiChild.ActualHeight); } mdiChild.buttonsPanel.Children.Clear(); StackPanel sp = new StackPanel { Orientation = Orientation.Horizontal }; sp.Children.Add(mdiChild.minimizeButton); sp.Children.Add(mdiChild.maximizeButton); sp.Children.Add(mdiChild.closeButton); mdiChild.Buttons = sp; mdiChild.Position = new Point(0, 0); mdiChild.Width = mdiChild.Container.ActualWidth; mdiChild.Height = mdiChild.Container.InnerHeight - 2; // ContentBorder.BorderThickness="1" in template if (mdiChild.Container.AllowWindowStateMax) { MDIContainer mdiContainer = mdiChild.Container; mdiContainer.AllowWindowStateMax = false; for (int i = 0; i < mdiContainer.Children.Count; i++) { if (mdiContainer.Children[i] != mdiChild) { if (mdiContainer.Children[i].WindowState == WindowState.Normal && mdiContainer.Children[i].MaximizeBox) { mdiContainer.Children[i].WindowState = WindowState.Maximized; } else if (mdiContainer.Children[i].WindowState == WindowState.Maximized) { mdiContainer.Children[i].Height = mdiContainer.InnerHeight; } } } ScrollViewer sv = (ScrollViewer)((Grid)mdiContainer.Content).Children[1]; sv.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; sv.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden; mdiChild.Focus(); mdiContainer.InvalidateSize(); mdiContainer.AllowWindowStateMax = true; } } break; } }