using System.Collections;
using System.ComponentModel;
using System.Drawing;
+using System.Runtime.InteropServices;
namespace System.Windows.Forms {
[DesignTimeVisible(false)]
public sealed class MdiClient : Control {
#region Local Variables
private int mdi_created;
- private HScrollBar hbar;
- private VScrollBar vbar;
+ private ImplicitHScrollBar hbar;
+ private ImplicitVScrollBar vbar;
private SizeGrip sizegrip;
private int hbar_value;
private int vbar_value;
private bool lock_sizing;
+ private bool initializing_scrollbars;
private int prev_bottom;
- private LayoutEventHandler initial_layout_handler;
+ private bool setting_windowstates = false;
internal ArrayList mdi_child_list;
+ private string form_text;
+ private bool setting_form_text;
+ private Form active_child;
#endregion // Local Variables
public ControlCollection(MdiClient owner) : base(owner) {
this.owner = owner;
- owner.mdi_child_list = new ArrayList ();
}
public override void Add(Control value) {
#region Public Constructors
public MdiClient()
{
+ mdi_child_list = new ArrayList ();
BackColor = SystemColors.AppWorkspace;
Dock = DockStyle.Fill;
SetStyle (ControlStyles.Selectable, false);
}
#endregion // Public Constructors
+
+ internal void SetParentText(bool text_changed)
+ {
+ if (setting_form_text)
+ return;
+
+ setting_form_text = true;
+
+ if (text_changed)
+ form_text = ParentForm.Text;
+
+ if (ParentForm.ActiveMaximizedMdiChild == null) {
+ ParentForm.Text = form_text;
+ } else {
+ string childText = ParentForm.ActiveMaximizedMdiChild.form.Text;
+ if (childText.Length > 0) {
+ ParentForm.Text = form_text + " - [" + ParentForm.ActiveMaximizedMdiChild.form.Text + "]";
+ } else {
+ ParentForm.Text = form_text;
+ }
+ }
+
+ setting_form_text = false;
+ }
+
internal override void OnPaintBackgroundInternal (PaintEventArgs pe)
{
if (BackgroundImage != null)
}
}
*/
+ switch ((Msg)m.Msg) {
+ case Msg.WM_NCCALCSIZE:
+ XplatUIWin32.NCCALCSIZE_PARAMS ncp;
+
+ if (m.WParam == (IntPtr) 1) {
+ ncp = (XplatUIWin32.NCCALCSIZE_PARAMS) Marshal.PtrToStructure (m.LParam,
+ typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
+
+ int bw = 2;
+
+ ncp.rgrc1.top += bw;
+ ncp.rgrc1.bottom -= bw;
+ ncp.rgrc1.left += bw;
+ ncp.rgrc1.right -= bw;
+
+ Marshal.StructureToPtr (ncp, m.LParam, true);
+ }
+
+ break;
+
+ case Msg.WM_NCPAINT:
+ PaintEventArgs pe = XplatUI.PaintEventStart (Handle, false);
+
+ Rectangle clip;
+ clip = new Rectangle (0, 0, Width, Height);
+
+ ControlPaint.DrawBorder3D (pe.Graphics, clip, Border3DStyle.Sunken);
+ XplatUI.PaintEventEnd (Handle, false);
+ m.Result = IntPtr.Zero;
+ return ;
+ }
+
base.WndProc (ref m);
}
{
base.OnResize (e);
+ if (Parent != null)
+ XplatUI.InvalidateNC (Parent.Handle);
// Should probably make this into one loop
SizeScrollBars ();
ArrangeWindows ();
#region Protected Instance Methods
#endregion // Protected Instance Methods
- private void SizeScrollBars ()
+ internal void SizeScrollBars ()
{
if (lock_sizing)
return;
hbar.Visible = false;
if (vbar != null)
vbar.Visible = false;
+ if (sizegrip != null)
+ sizegrip.Visible = false;
return;
}
int right = 0;
int left = 0;
+ int top = 0;
+ int bottom = 0;
+
foreach (Form child in Controls) {
if (!child.Visible)
continue;
hbar_required = true;
left = child.Left;
}
- }
-
- int top = 0;
- int bottom = 0;
- foreach (Form child in Controls) {
- if (!child.Visible)
- continue;
+
if (child.Bottom > bottom)
bottom = child.Bottom;
if (child.Top < 0) {
}
}
- int right_edge = Right;
- int bottom_edge = Bottom;
+ int first_right = Width;
+ int first_bottom = Height;
+ int right_edge = first_right;
+ int bottom_edge = first_bottom;
int prev_right_edge;
int prev_bottom_edge;
if (hbar_required || right > right_edge) {
need_hbar = true;
- bottom_edge = Bottom - SystemInformation.HorizontalScrollBarHeight;
+ bottom_edge = first_bottom - SystemInformation.HorizontalScrollBarHeight;
} else {
need_hbar = false;
- bottom_edge = Bottom;
+ bottom_edge = first_bottom;
}
if (vbar_required || bottom > bottom_edge) {
need_vbar = true;
- right_edge = Right - SystemInformation.VerticalScrollBarWidth;
+ right_edge = first_right - SystemInformation.VerticalScrollBarWidth;
} else {
need_vbar = false;
- right_edge = Right;
+ right_edge = first_right;
}
} while (right_edge != prev_right_edge || bottom_edge != prev_bottom_edge);
if (need_hbar) {
if (hbar == null) {
- hbar = new HScrollBar ();
+ hbar = new ImplicitHScrollBar ();
Controls.AddImplicit (hbar);
}
hbar.Visible = true;
if (need_vbar) {
if (vbar == null) {
- vbar = new VScrollBar ();
+ vbar = new ImplicitVScrollBar ();
Controls.AddImplicit (vbar);
}
vbar.Visible = true;
private void CalcHBar (int left, int right, int right_edge, bool vert_vis)
{
+ initializing_scrollbars = true;
int virtual_left = Math.Min (left, 0);
int virtual_right = Math.Max (right, right_edge);
int diff = (virtual_right - virtual_left) - right_edge;
+
hbar.Left = 0;
- hbar.Top = Height - hbar.Height;
- hbar.Width = Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
+ hbar.Top = ClientRectangle.Bottom - hbar.Height;
+ hbar.Width = ClientRectangle.Width - (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
hbar.LargeChange = 50;
- hbar.Maximum = diff + 51;
+ hbar.Maximum = diff + 51 + (vert_vis ? SystemInformation.VerticalScrollBarWidth : 0);
hbar.Value = -virtual_left;
-
hbar.ValueChanged += new EventHandler (HBarValueChanged);
+ XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
+ initializing_scrollbars = false;
}
private void CalcVBar (int top, int bottom, int bottom_edge, bool horz_vis)
{
+ initializing_scrollbars = true;
int virtual_top = Math.Min (top, 0);
int virtual_bottom = Math.Max (bottom, bottom_edge);
int diff = (virtual_bottom - virtual_top) - bottom_edge;
+
vbar.Top = 0;
- vbar.Left = Width - vbar.Width;
- vbar.Height = Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
+ vbar.Left = ClientRectangle.Right - vbar.Width;
+ vbar.Height = ClientRectangle.Height - (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
vbar.LargeChange = 50;
- vbar.Maximum = diff + 51;
- vbar.Value = -virtual_top;
+ vbar.Minimum = virtual_top;
+ vbar.Maximum = diff + 51 + (horz_vis ? SystemInformation.HorizontalScrollBarHeight : 0);
vbar.ValueChanged += new EventHandler (VBarValueChanged);
-
+ XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
+ initializing_scrollbars = false;
}
private void HBarValueChanged (object sender, EventArgs e)
{
+ if (initializing_scrollbars)
+ return;
+
if (hbar.Value == hbar_value)
return;
private void VBarValueChanged (object sender, EventArgs e)
{
+ if (initializing_scrollbars)
+ return;
+
if (vbar.Value == vbar_value)
return;
prev_bottom = Bottom;
}
- private void FormLocationChanged (object sender, EventArgs e)
- {
- SizeScrollBars ();
- }
-
- private int iconic_x = -1;
- private int iconic_y = -1;
internal void ArrangeIconicWindows ()
{
int xspacing = 160;
int yspacing = 25;
- if (iconic_x == -1 && iconic_y == -1) {
- iconic_x = Left;
- iconic_y = Bottom - yspacing;
- }
+ Rectangle rect = new Rectangle (0, 0, xspacing, yspacing);
lock_sizing = true;
foreach (Form form in Controls) {
continue;
MdiWindowManager wm = (MdiWindowManager) form.WindowManager;
- // Need to get the width in the loop cause some themes might have
- // different widths for different styles
- int bw = ThemeEngine.Current.ManagedWindowBorderWidth (wm);
if (wm.IconicBounds != Rectangle.Empty) {
- form.Bounds = wm.IconicBounds;
+ if (form.Bounds != wm.IconicBounds)
+ form.Bounds = wm.IconicBounds;
continue;
}
-
+
+ // Need to get the width in the loop cause some themes might have
+ // different widths for different styles
+ int bw = ThemeEngine.Current.ManagedWindowBorderWidth (wm);
+
// The extra one pixel is a cheap hack for now until we
// handle 0 client sizes properly in the driver
- int height = wm.TitleBarHeight + (bw * 2) + 1;
- Rectangle rect = new Rectangle (iconic_x, iconic_y, xspacing, height);
- form.Bounds = wm.IconicBounds = rect;
-
- iconic_x += xspacing;
- if (iconic_x >= Right) {
- iconic_x = Left;
- iconic_y -= height;
- }
+ int height = wm.TitleBarHeight + (bw * 2) + 1;
+
+ bool success = true;
+ int startx, starty, currentx, currenty;
+
+ startx = 0;
+ starty = Bottom - yspacing - 1;
+ if (this.hbar != null && this.hbar.Visible)
+ starty -= this.hbar.Height;
+ currentx = startx;
+ currenty = starty;
+
+ do {
+ rect.X = currentx;
+ rect.Y = currenty;
+ rect.Height = height;
+ success = true;
+ foreach (Form form2 in Controls) {
+ if (form2 == form || form2.window_state != FormWindowState.Minimized)
+ continue;
+
+ if (form2.Bounds.IntersectsWith(rect)) {
+ success = false;
+ break;
+ }
+ }
+ if (!success) {
+ currentx += xspacing;
+ if (currentx + xspacing > Right) {
+ currentx = startx;
+ currenty -= Math.Max(yspacing, height);
+ }
+ }
+ } while (!success);
+ wm.IconicBounds = rect;
+ form.Bounds = wm.IconicBounds;
}
lock_sizing = false;
}
Controls.Remove (form);
form.Close ();
+
+ XplatUI.RequestNCRecalc (Handle);
+ if (Controls.Count == 0) {
+ XplatUI.RequestNCRecalc (Parent.Handle);
+ ParentForm.PerformLayout ();
+ }
+ SizeScrollBars ();
+ SetParentText (false);
}
internal void ActivateNextChild ()
{
if (Controls.Count < 1)
return;
-
+ if (Controls.Count == 1 && Controls[0] == ActiveMdiChild)
+ return;
+
Form front = (Form) Controls [0];
Form form = (Form) Controls [1];
{
if (Controls.Count < 1)
return;
-
+
+ if (ParentForm.is_changing_visible_state)
+ return;
+
Form current = (Form) Controls [0];
-
+ form.SuspendLayout ();
form.BringToFront ();
-
+ if (vbar != null && vbar.Visible)
+ XplatUI.SetZOrder (vbar.Handle, IntPtr.Zero, true, false);
+ if (hbar != null && hbar.Visible)
+ XplatUI.SetZOrder (hbar.Handle, IntPtr.Zero, true, false);
+ SetWindowStates ((MdiWindowManager) form.window_manager);
+ form.ResumeLayout (false);
if (current != form) {
- Message m = new Message ();
- m.Msg = (int) Msg.WM_NCPAINT;
- m.HWnd = current.Handle;
- m.LParam = IntPtr.Zero;
- m.WParam = new IntPtr (1);
- XplatUI.SendMessage (ref m);
-
- m.HWnd = form.Handle;
- XplatUI.SendMessage (ref m);
+ form.has_focus = false;
+ XplatUI.InvalidateNC (current.Handle);
+ XplatUI.InvalidateNC (form.Handle);
}
+ active_child = (Form) Controls [0];
+ }
+
+ internal bool SetWindowStates (MdiWindowManager wm)
+ {
+ /*
+ MDI WindowState behaviour:
+ - If the active window is maximized, all other maximized windows are normalized.
+ - If a normal window gets focus and the original active window was maximized,
+ the normal window gets maximized and the original window gets normalized.
+ - If a minimized window gets focus and the original window was maximized,
+ the minimzed window gets maximized and the original window gets normalized.
+ If the ex-minimized window gets deactivated, it will be normalized.
+ */
+ Form form = wm.form;
+
+ if (setting_windowstates) {
+ return false;
+ }
+
+ if (!form.Visible)
+ return false;
+
+ bool is_active = wm.IsActive();
+ bool maximize_this = false;
+
+ if (!is_active){
+ return false;
+ }
+
+ setting_windowstates = true;
+ foreach (Form frm in mdi_child_list) {
+ if (frm == form) {
+ continue;
+ } else if (!frm.Visible){
+ continue;
+ }
+ if (frm.WindowState == FormWindowState.Maximized && is_active) {
+ maximize_this = true;
+ if (((MdiWindowManager) frm.window_manager).was_minimized)
+ frm.WindowState = FormWindowState.Minimized;
+ else
+ frm.WindowState = FormWindowState.Normal;//
+ }
+ }
+ if (maximize_this) {
+ wm.was_minimized = form.window_state == FormWindowState.Minimized;
+ form.WindowState = FormWindowState.Maximized;
+ }
+ SetParentText(false);
+
+ XplatUI.RequestNCRecalc(ParentForm.Handle);
+ XplatUI.RequestNCRecalc (Handle);
+
+ SizeScrollBars ();
+
+ setting_windowstates = false;
+
+ return maximize_this;
}
internal int ChildrenCreated {
internal Form ActiveMdiChild {
get {
+#if NET_2_0
+ if (!ParentForm.Visible)
+ return null;
+#endif
if (Controls.Count < 1)
return null;
- return (Form) Controls [0];
+
+ if (!ParentForm.IsHandleCreated)
+ return null;
+
+ if (!ParentForm.has_been_visible)
+ return null;
+
+ if (!ParentForm.Visible)
+ return active_child;
+
+ active_child = null;
+ for (int i = 0; i < Controls.Count; i++) {
+ if (Controls [i].Visible) {
+ active_child = (Form) Controls [i];
+ break;
+ }
+ }
+ return active_child;
}
set {
ActivateChild (value);
}
}
+
+ internal void ActivateActiveMdiChild ()
+ {
+ if (ParentForm.is_changing_visible_state)
+ return;
+
+ for (int i = 0; i < Controls.Count; i++) {
+ if (Controls [i].Visible) {
+ ActivateChild ((Form) Controls [i]);
+ return;
+ }
+ }
+ }
}
}