📄 mdiclientcontroller.cs
字号:
#region Using Directives
using System;
using System.Drawing;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Runtime.InteropServices;
#endregion // Using Directives
namespace Custom.Windows.Forms
{
/// <summary>
/// Listens for messages sent to a <see cref="System.Windows.Forms.MdiClient"/>
/// class and controls its properties.
/// </summary>
[ToolboxBitmap(typeof(MdiClientController))]
public class MdiClientController : NativeWindow, IComponent, IDisposable
{
#region Private Fields
private Form parentForm;
private MdiClient mdiClient;
private BorderStyle borderStyle;
private Color backColor;
private bool autoScroll;
private Image image;
private ContentAlignment imageAlign;
private bool stretchImage;
private ISite site;
#endregion // Private Fields
#region Public Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Slusser.Components.MdiClientController"/> class.
/// </summary>
public MdiClientController() : this(null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Slusser.Components.MdiClientController"/> class
/// for the given MDI form.
/// </summary>
/// <param name="parentForm">The MDI form.</param>
public MdiClientController(Form parentForm)
{
// Initialize the variables.
this.site = null;
this.parentForm = null;
this.mdiClient = null;
this.backColor = SystemColors.AppWorkspace;
this.borderStyle = BorderStyle.Fixed3D;
this.autoScroll = true;
this.image = null;
this.imageAlign = ContentAlignment.MiddleCenter;
this.stretchImage = false;
// Set the ParentForm property.
this.ParentForm = parentForm;
}
#endregion // Public Constructors
#region Public Events
/// <summary>
/// Occurs when the control is redrawn.
/// </summary>
[Category("Appearance"), Description("Occurs when a control needs repainting.")]
public event PaintEventHandler Paint;
/// <summary>
/// Occurs when the control is disposed.
/// </summary>
[Browsable(false)]
public event EventHandler Disposed;
/// <summary>
/// Occurs when the <see cref="System.Windows.Forms.NativeWindow"/> handle
/// is assigned.
/// </summary>
[Browsable(false)]
public event EventHandler HandleAssigned;
#endregion // Public Events
#region Public Properties
/// <summary>
/// Gets or sets the <see cref="System.ComponentModel.ISite"/> of
/// the <see cref="System.ComponentModel.Component"/>.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public ISite Site
{
get { return site; }
set
{
site = value;
if(site == null)
return;
// If the component is dropped onto a form during design-time,
// set the ParentForm property.
IDesignerHost host = (value.GetService(typeof(IDesignerHost)) as IDesignerHost);
if(host != null)
{
Form parent = host.RootComponent as Form;
if(parent != null)
ParentForm = parent;
}
}
}
/// <summary>
/// Gets or sets the form that the <see cref="System.Windows.Forms.MdiClient"/>
/// control is assigned to.
/// </summary>
[Browsable(false)]
public Form ParentForm
{
get { return parentForm; }
set
{
// If the ParentForm has previously been set,
// unwire events connected to the old parent.
if(parentForm != null)
parentForm.HandleCreated -= new EventHandler(ParentFormHandleCreated);
parentForm = value;
if(parentForm == null)
return;
// If the parent form has not been created yet,
// wait to initialize the MDI client until it is.
if(parentForm.IsHandleCreated)
{
InitializeMdiClient();
RefreshProperties();
}
else
parentForm.HandleCreated += new EventHandler(ParentFormHandleCreated);
}
}
/// <summary>
/// Gets the <see cref="System.Windows.Forms.MdiClient"/> being controlled.
/// </summary>
[Browsable(false)]
public MdiClient MdiClient
{
get { return mdiClient; }
}
/// <summary>
/// Gets or sets the background color for the control.
/// </summary>
[Category("Appearance"), DefaultValue(typeof(Color), "AppWorkspace")]
[Description("The backcolor used to display text and graphics in the control.")]
public Color BackColor
{
// Use the BackColor property of the MdiClient control. This is one of
// the few properties in the MdiClient class that actually works.
get
{
if(mdiClient != null)
return mdiClient.BackColor;
return backColor;
}
set
{
backColor = value;
if(mdiClient != null)
mdiClient.BackColor = value;
}
}
/// <summary>
/// Indicates the border style for the control.
/// </summary>
/// <exception cref="System.ComponentModel.InvalidEnumArgumentException">The value
/// assigned to the property is not a member of
/// the <see cref="System.Windows.Forms.BorderStyle"/> enumeration.</exception>
[DefaultValue(BorderStyle.Fixed3D), Category("Appearance")]
[Description("Indicates whether the MDI area should have a border.")]
public BorderStyle BorderStyle
{
get { return borderStyle; }
set
{
// Error-check the enum.
if(!Enum.IsDefined(typeof(BorderStyle), value))
throw new InvalidEnumArgumentException("value", (int)value, typeof(BorderStyle));
borderStyle = value;
if(mdiClient == null)
return;
// This property can actually be visible in design-mode,
// but to keep it consistent with the others,
// prevent this from being show at design-time.
if(site != null && site.DesignMode)
return;
// There is no BorderStyle property exposed by the MdiClient class,
// but this can be controlled by Win32 functions. A Win32 ExStyle
// of WS_EX_CLIENTEDGE is equivalent to a Fixed3D border and a
// Style of WS_BORDER is equivalent to a FixedSingle border.
// This code is inspired Jason Dori's article:
// "Adding designable borders to user controls".
// http://www.codeproject.com/cs/miscctrl/CsAddingBorders.asp
// Get styles using Win32 calls
int style = GetWindowLong(mdiClient.Handle, GWL_STYLE);
int exStyle = GetWindowLong(mdiClient.Handle, GWL_EXSTYLE);
// Add or remove style flags as necessary.
switch(borderStyle)
{
case BorderStyle.Fixed3D:
exStyle |= WS_EX_CLIENTEDGE;
style &= ~WS_BORDER;
break;
case BorderStyle.FixedSingle:
exStyle &= ~WS_EX_CLIENTEDGE;
style |= WS_BORDER;
break;
case BorderStyle.None:
style &= ~WS_BORDER;
exStyle &= ~WS_EX_CLIENTEDGE;
break;
}
// Set the styles using Win32 calls
SetWindowLong(mdiClient.Handle, GWL_STYLE, style);
SetWindowLong(mdiClient.Handle, GWL_EXSTYLE, exStyle);
// Cause an update of the non-client area.
UpdateStyles();
}
}
/// <summary>
/// Gets or sets a value indicating whether the container will allow the user to
/// scroll to any controls placed outside of its visible boundaries.
/// </summary>
[DefaultValue(true), Category("Layout")]
[Description("Determines whether scrollbars will automatically appear if controls are placed outside the MDI client area.")]
public bool AutoScroll
{
get { return autoScroll; }
set
{
// By default the MdiClient control scrolls. It can appear though that
// there are no scrollbars by turning them off when the non-client
// area is calculated. I decided to expose this method following
// the .NET vernacular of an AutoScroll property.
autoScroll = value;
if(mdiClient != null)
UpdateStyles();
}
}
/// <summary>
/// Gets or sets the image that the
/// <see cref="Slusser.Components.MdiClientController"/> displays.
/// </summary>
[DefaultValue(null), Category("Appearance")]
[Description("The image displayed in the MDI client area.")]
public Image Image
{
get { return image; }
set
{
image = value;
if(mdiClient != null)
mdiClient.Invalidate();
}
}
/// <summary>
/// Gets or sets the alignment of the background image.
/// </summary>
/// <exception cref="System.ComponentModel.InvalidEnumArgumentException">The
/// value assigned to the property is not a member of
/// the <see cref="System.Drawing.ContentAlignment"/> enumeration.</exception>
[Category("Appearance"), DefaultValue(ContentAlignment.MiddleCenter)]
[Description("Determines the position of the image within the MDI client area.")]
public ContentAlignment ImageAlign
{
get { return imageAlign; }
set
{
// Error-check the enum.
if(!Enum.IsDefined(typeof(ContentAlignment), value))
throw new InvalidEnumArgumentException("value", (int)value, typeof(ContentAlignment));
imageAlign = value;
if(mdiClient != null)
mdiClient.Invalidate();
}
}
/// <summary>
/// Gets or sets a value indicating whether the
/// <see cref="Slusser.Components.MdiClientController.Image"/> should
/// be stretched to fill the entire client area.
/// </summary>
[Category("Appearance"), DefaultValue(false)]
[Description("Determines whether the image should be scaled to fill the entire client area.")]
public bool StretchImage
{
get { return stretchImage; }
set
{
stretchImage = value;
if(mdiClient != null)
mdiClient.Invalidate();
}
}
/// <summary>
/// Gets the handle for this window.
/// </summary>
[Browsable(false)]
public new IntPtr Handle
{
// Hide this from the property grid during design-time.
get { return base.Handle; }
}
#endregion // Public Properties
#region Public Methods
/// <summary>
/// Releases all resources used by the
/// <see cref="System.ComponentModel.Component"/>.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Reestablishes a connection to the <see cref="System.Windows.Forms.MdiClient"/>
/// control if the <see cref="Slusser.Components.MdiClientController.ParentForm"/>
/// hasn't changed but its <see cref="System.Windows.Forms.Form.IsMdiContainer"/>
/// property has.
/// </summary>
public void RenewMdiClient()
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -