首先声明:
本文的代码,不是我自己写的,应该是从网上找的,主要是功能好用,所以,记录下,以后也好用。
代码
#region Enums
/// <summary>
/// Enumeration to sepcify the visual style to be applied to the CollapsibleSplitter control
/// </summary>
public enum VisualStyles
{
Mozilla = 0,
XP,
Win9x,
DoubleDots,
Lines
}
/// <summary>
/// Enumeration to specify the current animation state of the control.
/// </summary>
public enum SplitterState
{
Collapsed = 0,
Expanding,
Expanded,
Collapsing
}
#endregion
/// <summary>
/// A custom collapsible splitter that can resize, hide and show associated form controls
/// </summary>
[ToolboxBitmap(typeof(CollapsibleSplitter))]
[DesignerAttribute(typeof(CollapsibleSplitterDesigner))]
public class CollapsibleSplitter : System.Windows.Forms.Splitter
{
#region Private Properties
// declare and define some base properties
private bool hot;
private System.Drawing.Color hotColor = CalculateColor(SystemColors.Highlight, SystemColors.Window, 70);
private System.Windows.Forms.Control controlToHide;
private System.Drawing.Rectangle rr;
private System.Windows.Forms.Form parentForm;
private bool expandParentForm;
private VisualStyles visualStyle;
// Border added in version 1.3
private System.Windows.Forms.Border3DStyle borderStyle = System.Windows.Forms.Border3DStyle.Flat;
// animation controls introduced in version 1.22
private System.Windows.Forms.Timer animationTimer;
private int controlWidth;
private int controlHeight;
private int parentFormWidth;
private int parentFormHeight;
private SplitterState currentState;
private int animationDelay = 20;
private int animationStep = 20;
private bool useAnimations;
private IVisualStyle styleDrawer;
#endregion
#region Public Properties
/// <summary>
/// The initial state of the Splitter. Set to True if the control to hide is not visible by default
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("False"),
Description("The initial state of the Splitter. Set to True if the control to hide is not visible by default")]
public bool IsCollapsed
{
get
{
if (this.controlToHide != null)
return !this.controlToHide.Visible;
else
return true;
}
}
/// <summary>
/// The System.Windows.Forms.Control that the splitter will collapse
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue(""),
Description("The System.Windows.Forms.Control that the splitter will collapse")]
public System.Windows.Forms.Control ControlToHide
{
get { return this.controlToHide; }
set { this.controlToHide = value; }
}
/// <summary>
/// Determines if the collapse and expanding actions will be animated
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("True"),
Description("Determines if the collapse and expanding actions will be animated")]
public bool UseAnimations
{
get { return this.useAnimations; }
set { this.useAnimations = value; }
}
/// <summary>
/// The delay in millisenconds between animation steps
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("20"),
Description("The delay in millisenconds between animation steps")]
public int AnimationDelay
{
get { return this.animationDelay; }
set { this.animationDelay = value; }
}
/// <summary>
/// The amount of pixels moved in each animation step
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("20"),
Description("The amount of pixels moved in each animation step")]
public int AnimationStep
{
get { return this.animationStep; }
set { this.animationStep = value; }
}
/// <summary>
/// When true the entire parent form will be expanded and collapsed, otherwise just the contol to expand will be changed
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("False"),
Description("When true the entire parent form will be expanded and collapsed, otherwise just the contol to expand will be changed")]
public bool ExpandParentForm
{
get { return this.expandParentForm; }
set { this.expandParentForm = value; }
}
/// <summary>
/// The visual style that will be painted on the control
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("VisualStyles.XP"),
Description("The visual style that will be painted on the control")]
public VisualStyles VisualStyle
{
get { return this.visualStyle; }
set
{
/*
this.visualStyle = value;
this.Invalidate();
* */
this.visualStyle = value;
switch (value)
{
case VisualStyles.Mozilla:
styleDrawer = new VisualStyleMozilla();
break;
case VisualStyles.XP:
styleDrawer = new VisualStyleXP();
break;
case VisualStyles.Win9x:
styleDrawer = new VisualStyleWin9x();
break;
case VisualStyles.DoubleDots:
styleDrawer = new VisualStyleDoubleDots();
break;
case VisualStyles.Lines:
styleDrawer = new VisualStyleLines();
break;
}
this.Invalidate();
}
}
/// <summary>
/// An optional border style to paint on the control. Set to Flat for no border
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("System.Windows.Forms.Border3DStyle.Flat"),
Description("An optional border style to paint on the control. Set to Flat for no border")]
public System.Windows.Forms.Border3DStyle BorderStyle3D
{
get { return this.borderStyle; }
set
{
this.borderStyle = value;
this.Invalidate();
}
}
#endregion
#region Public Methods
public void ToggleState()
{
this.ToggleSplitter();
}
#endregion
#region Constructor
public CollapsibleSplitter()
{
// Register mouse events
this.Click += new System.EventHandler(OnClick);
this.Resize += new System.EventHandler(OnResize);
this.MouseLeave += new System.EventHandler(OnMouseLeave);
this.MouseMove += new MouseEventHandler(OnMouseMove);
// Setup the animation timer control
this.animationTimer = new System.Windows.Forms.Timer();
this.animationTimer.Interval = animationDelay;
this.animationTimer.Tick += new System.EventHandler(this.animationTimerTick);
}
#endregion
#region Overrides
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
this.parentForm = this.FindForm();
// set the current state
if (this.controlToHide != null)
{
if (this.controlToHide.Visible)
{
this.currentState = SplitterState.Expanded;
}
else
{
this.currentState = SplitterState.Collapsed;
}
}
}
protected override void OnEnabledChanged(System.EventArgs e)
{
base.OnEnabledChanged(e);
this.Invalidate();
}
#endregion
#region Event Handlers
protected override void OnMouseDown(MouseEventArgs e)
{
// if the hider control isn't hot, let the base resize action occur
if (this.controlToHide != null)
{
if (!this.hot && this.controlToHide.Visible)
{
base.OnMouseDown(e);
}
}
}
private void OnResize(object sender, System.EventArgs e)
{
this.Invalidate();
}
// this method was updated in version 1.11 to fix a flickering problem
// discovered by John O'Byrne
private void OnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
// check to see if the mouse cursor position is within the bounds of our control
if (e.X >= rr.X && e.X <= rr.X + rr.Width && e.Y >= rr.Y && e.Y <= rr.Y + rr.Height)
{
if (!this.hot)
{
this.hot = true;
this.Cursor = Cursors.Hand;
this.Invalidate();
}
}
else
{
if (this.hot)
{
this.hot = false;
this.Invalidate(); ;
}
this.Cursor = Cursors.Default;
if (controlToHide != null)
{
if (!controlToHide.Visible)
this.Cursor = Cursors.Default;
else // Changed in v1.2 to support Horizontal Splitters
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
this.Cursor = Cursors.VSplit;
}
else
{
this.Cursor = Cursors.HSplit;
}
}
}
}
}
private void OnMouseLeave(object sender, System.EventArgs e)
{
// ensure that the hot state is removed
this.hot = false;
this.Invalidate(); ;
}
private void OnClick(object sender, System.EventArgs e)
{
if (controlToHide != null && hot &&
currentState != SplitterState.Collapsing &&
currentState != SplitterState.Expanding)
{
ToggleSplitter();
}
}
private void ToggleSplitter()
{
// if an animation is currently in progress for this control, drop out
if (currentState == SplitterState.Collapsing || currentState == SplitterState.Expanding)
return;
controlWidth = controlToHide.Width;
controlHeight = controlToHide.Height;
if (controlToHide.Visible)
{
if (useAnimations)
{
currentState = SplitterState.Collapsing;
if (parentForm != null)
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
parentFormWidth = parentForm.Width - controlWidth;
}
else
{
parentFormHeight = parentForm.Height - controlHeight;
}
}
this.animationTimer.Enabled = true;
}
else
{
// no animations, so just toggle the visible state
currentState = SplitterState.Collapsed;
controlToHide.Visible = false;
if (expandParentForm && parentForm != null)
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
parentForm.Width -= controlToHide.Width;
}
else
{
parentForm.Height -= controlToHide.Height;
}
}
}
}
else
{
// control to hide is collapsed
if (useAnimations)
{
currentState = SplitterState.Expanding;
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
if (parentForm != null)
{
parentFormWidth = parentForm.Width + controlWidth;
}
controlToHide.Width = 0;
}
else
{
if (parentForm != null)
{
parentFormHeight = parentForm.Height + controlHeight;
}
controlToHide.Height = 0;
}
controlToHide.Visible = true;
this.animationTimer.Enabled = true;
}
else
{
// no animations, so just toggle the visible state
currentState = SplitterState.Expanded;
controlToHide.Visible = true;
if (expandParentForm && parentForm != null)
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
parentForm.Width += controlToHide.Width;
}
else
{
parentForm.Height += controlToHide.Height;
}
}
}
}
}
#endregion
#region Implementation
#region Animation Timer Tick
private void animationTimerTick(object sender, System.EventArgs e)
{
switch (currentState)
{
case SplitterState.Collapsing:
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
// vertical splitter
if (controlToHide.Width > animationStep)
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width -= animationStep;
}
controlToHide.Width -= animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width = parentFormWidth;
}
controlToHide.Visible = false;
animationTimer.Enabled = false;
controlToHide.Width = controlWidth;
currentState = SplitterState.Collapsed;
this.Invalidate();
}
}
else
{
// horizontal splitter
if (controlToHide.Height > animationStep)
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height -= animationStep;
}
controlToHide.Height -= animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height = parentFormHeight;
}
controlToHide.Visible = false;
animationTimer.Enabled = false;
controlToHide.Height = controlHeight;
currentState = SplitterState.Collapsed;
this.Invalidate();
}
}
break;
case SplitterState.Expanding:
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
// vertical splitter
if (controlToHide.Width < (controlWidth - animationStep))
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width += animationStep;
}
controlToHide.Width += animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width = parentFormWidth;
}
controlToHide.Width = controlWidth;
controlToHide.Visible = true;
animationTimer.Enabled = false;
currentState = SplitterState.Expanded;
this.Invalidate();
}
}
else
{
// horizontal splitter
if (controlToHide.Height < (controlHeight - animationStep))
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height += animationStep;
}
controlToHide.Height += animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height = parentFormHeight;
}
controlToHide.Height = controlHeight;
controlToHide.Visible = true;
animationTimer.Enabled = false;
currentState = SplitterState.Expanded;
this.Invalidate();
}
}
break;
}
}
#endregion
#region Paint the control
// OnPaint is now an override rather than an event in version 1.1
protected override void OnPaint(PaintEventArgs e)
{
// create a Graphics object
Graphics g = e.Graphics;
// find the rectangle for the splitter and paint it
Rectangle r = this.ClientRectangle; // fixed in version 1.1
g.FillRectangle(new SolidBrush(this.BackColor), r);
#region Vertical Splitter
// Check the docking style and create the control rectangle accordingly
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
// create a new rectangle in the vertical center of the splitter for our collapse control button
rr = new Rectangle(r.X, (int)r.Y + ((r.Height - 115) / 2), 8, 115);
// force the width to 8px so that everything always draws correctly
this.Width = 8;
// draw the background color for our control image
if (hot)
{
g.FillRectangle(new SolidBrush(hotColor), new Rectangle(rr.X + 1, rr.Y, 6, 115));
}
else
{
g.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(rr.X + 1, rr.Y, 6, 115));
}
// draw the top & bottom lines for our control image
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + 1, rr.Y, rr.X + rr.Width - 2, rr.Y);
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + 1, rr.Y + rr.Height, rr.X + rr.Width - 2, rr.Y + rr.Height);
if (this.Enabled)
{
// draw the arrows for our control image
// the ArrowPointArray is a point array that defines an arrow shaped polygon
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 2, rr.Y + 3));
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 2, rr.Y + rr.Height - 9));
}
// draw the dots for our control image using a loop
int x = rr.X + 3;
int y = rr.Y + 14;
// Visual Styles added in version 1.1
#region 重构后废除的代码
/*
switch (visualStyle)
{
case VisualStyles.Mozilla:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y + (i * 3), x + 1, y + 1 + (i * 3));
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
if (hot)
{
g.DrawLine(new Pen(hotColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
else
{
g.DrawLine(new Pen(this.BackColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
}
break;
case VisualStyles.DoubleDots:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x - 1, y + (i * 3), 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 2, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + 1, y + (i * 3), 1, 1);
}
break;
case VisualStyles.Win9x:
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 2, y);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 2, y, x + 2, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 90, x + 2, y + 90);
break;
case VisualStyles.XP:
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x, y + (i * 5), 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1, y + 1 + (i * 5), 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x, y + (i * 5), 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x, y + (i * 5) + 1);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x + 1, y + (i * 5));
}
break;
case VisualStyles.Lines:
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 2), x + 2, y + (i * 2));
}
break;
}
*/
#endregion
styleDrawer.DrawVertical(g, x, y, hot ? hotColor : BackColor);
// Added in version 1.3
if (this.borderStyle != System.Windows.Forms.Border3DStyle.Flat)
{
// Paint the control border
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Left);
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Right);
}
}
#endregion
// Horizontal Splitter support added in v1.2
#region Horizontal Splitter
else if (this.Dock == DockStyle.Top || this.Dock == DockStyle.Bottom)
{
// create a new rectangle in the horizontal center of the splitter for our collapse control button
rr = new Rectangle((int)r.X + ((r.Width - 115) / 2), r.Y, 115, 8);
// force the height to 8px
this.Height = 8;
// draw the background color for our control image
if (hot)
{
g.FillRectangle(new SolidBrush(hotColor), new Rectangle(rr.X, rr.Y + 1, 115, 6));
}
else
{
g.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(rr.X, rr.Y + 1, 115, 6));
}
// draw the left & right lines for our control image
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X, rr.Y + 1, rr.X, rr.Y + rr.Height - 2);
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + rr.Width, rr.Y + 1, rr.X + rr.Width, rr.Y + rr.Height - 2);
if (this.Enabled)
{
// draw the arrows for our control image
// the ArrowPointArray is a point array that defines an arrow shaped polygon
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 3, rr.Y + 2));
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + rr.Width - 9, rr.Y + 2));
}
// draw the dots for our control image using a loop
int x = rr.X + 14;
int y = rr.Y + 3;
// Visual Styles added in version 1.1
#region 重构后废除的代码
/*
switch (visualStyle)
{
case VisualStyles.Mozilla:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x + (i * 3), y, x + 1 + (i * 3), y + 1);
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1 + (i * 3), y + 1, x + 2 + (i * 3), y + 2);
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
if (hot)
{
g.DrawLine(new Pen(hotColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
else
{
g.DrawLine(new Pen(this.BackColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
}
break;
case VisualStyles.DoubleDots:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y - 1, 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y + 2, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y + 1, 1, 1);
}
break;
case VisualStyles.Win9x:
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 2);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 88, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 2, x + 88, y + 2);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 88, y, x + 88, y + 2);
break;
case VisualStyles.XP:
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x + (i * 5), y, 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 5), y + 1, 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x + (i * 5), y, 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5) + 1, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5), y + 1);
}
break;
case VisualStyles.Lines:
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 2), y, x + (i * 2), y + 2);
}
break;
}
*/
#endregion
styleDrawer.DrawHorizontal(g, x, y, hot ? hotColor : BackColor);
// Added in version 1.3
if (this.borderStyle != System.Windows.Forms.Border3DStyle.Flat)
{
// Paint the control border
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Top);
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Bottom);
}
}
#endregion
else
{
throw new Exception("The Collapsible Splitter control cannot have the Filled or None Dockstyle property");
}
// dispose the Graphics object
g.Dispose();
}
#endregion
#region Arrow Polygon Array
// This creates a point array to draw a arrow-like polygon
private Point[] ArrowPointArray(int x, int y)
{
Point[] point = new Point[3];
if (controlToHide != null)
{
// decide which direction the arrow will point
if (
(this.Dock == DockStyle.Right && controlToHide.Visible)
|| (this.Dock == DockStyle.Left && !controlToHide.Visible)
)
{
// right arrow
point[0] = new Point(x, y);
point[1] = new Point(x + 3, y + 3);
point[2] = new Point(x, y + 6);
}
else if (
(this.Dock == DockStyle.Right && !controlToHide.Visible)
|| (this.Dock == DockStyle.Left && controlToHide.Visible)
)
{
// left arrow
point[0] = new Point(x + 3, y);
point[1] = new Point(x, y + 3);
point[2] = new Point(x + 3, y + 6);
}
// Up/Down arrows added in v1.2
else if (
(this.Dock == DockStyle.Top && controlToHide.Visible)
|| (this.Dock == DockStyle.Bottom && !controlToHide.Visible)
)
{
// up arrow
point[0] = new Point(x + 3, y);
point[1] = new Point(x + 6, y + 4);
point[2] = new Point(x, y + 4);
}
else if (
(this.Dock == DockStyle.Top && !controlToHide.Visible)
|| (this.Dock == DockStyle.Bottom && controlToHide.Visible)
)
{
// down arrow
point[0] = new Point(x, y);
point[1] = new Point(x + 6, y);
point[2] = new Point(x + 3, y + 3);
}
}
return point;
}
#endregion
#region Color Calculator
// this method was borrowed from the RichUI Control library by Sajith M
private static Color CalculateColor(Color front, Color back, int alpha)
{
// solid color obtained as a result of alpha-blending
Color frontColor = Color.FromArgb(255, front);
Color backColor = Color.FromArgb(255, back);
float frontRed = frontColor.R;
float frontGreen = frontColor.G;
float frontBlue = frontColor.B;
float backRed = backColor.R;
float backGreen = backColor.G;
float backBlue = backColor.B;
float fRed = frontRed * alpha / 255 + backRed * ((float)(255 - alpha) / 255);
byte newRed = (byte)fRed;
float fGreen = frontGreen * alpha / 255 + backGreen * ((float)(255 - alpha) / 255);
byte newGreen = (byte)fGreen;
float fBlue = frontBlue * alpha / 255 + backBlue * ((float)(255 - alpha) / 255);
byte newBlue = (byte)fBlue;
return Color.FromArgb(255, newRed, newGreen, newBlue);
}
#endregion
#endregion
}
/// <summary>
/// A simple designer class for the CollapsibleSplitter control to remove
/// unwanted properties at design time.
/// </summary>
public class CollapsibleSplitterDesigner : System.Windows.Forms.Design.ControlDesigner
{
public CollapsibleSplitterDesigner()
{
}
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
properties.Remove("IsCollapsed");
properties.Remove("BorderStyle");
properties.Remove("Size");
}
}
#region 显示风格的接口和实现
interface IVisualStyle
{
void DrawVertical(Graphics g, int x, int y, Color lineColor);
void DrawHorizontal(Graphics g, int x, int y, Color lineColor);
}
public class VisualStyleMozilla : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y + (i * 3), x + 1, y + 1 + (i * 3));
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
g.DrawLine(new Pen(lineColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x + (i * 3), y, x + 1 + (i * 3), y + 1);
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1 + (i * 3), y + 1, x + 2 + (i * 3), y + 2);
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
g.DrawLine(new Pen(lineColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
}
}
public class VisualStyleXP : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x, y + (i * 5), 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1, y + 1 + (i * 5), 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x, y + (i * 5), 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x, y + (i * 5) + 1);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x + 1, y + (i * 5));
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x + (i * 5), y, 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 5), y + 1, 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x + (i * 5), y, 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5) + 1, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5), y + 1);
}
}
}
public class VisualStyleWin9x : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 2, y);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 2, y, x + 2, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 90, x + 2, y + 90);
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 2);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 88, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 2, x + 88, y + 2);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 88, y, x + 88, y + 2);
}
}
public class VisualStyleDoubleDots : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x - 1, y + (i * 3), 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 2, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + 1, y + (i * 3), 1, 1);
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y - 1, 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y + 2, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y + 1, 1, 1);
}
}
}
public class VisualStyleLines : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 2), x + 2, y + (i * 2));
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 2), y, x + (i * 2), y + 2);
}
}
}
#endregion
#region Enums
/// <summary>
/// Enumeration to sepcify the visual style to be applied to the CollapsibleSplitter control
/// </summary>
public enum VisualStyles
{
Mozilla = 0,
XP,
Win9x,
DoubleDots,
Lines
}
/// <summary>
/// Enumeration to specify the current animation state of the control.
/// </summary>
public enum SplitterState
{
Collapsed = 0,
Expanding,
Expanded,
Collapsing
}
#endregion
/// <summary>
/// A custom collapsible splitter that can resize, hide and show associated form controls
/// </summary>
[ToolboxBitmap(typeof(CollapsibleSplitter))]
[DesignerAttribute(typeof(CollapsibleSplitterDesigner))]
public class CollapsibleSplitter : System.Windows.Forms.Splitter
{
#region Private Properties
// declare and define some base properties
private bool hot;
private System.Drawing.Color hotColor = CalculateColor(SystemColors.Highlight, SystemColors.Window, 70);
private System.Windows.Forms.Control controlToHide;
private System.Drawing.Rectangle rr;
private System.Windows.Forms.Form parentForm;
private bool expandParentForm;
private VisualStyles visualStyle;
// Border added in version 1.3
private System.Windows.Forms.Border3DStyle borderStyle = System.Windows.Forms.Border3DStyle.Flat;
// animation controls introduced in version 1.22
private System.Windows.Forms.Timer animationTimer;
private int controlWidth;
private int controlHeight;
private int parentFormWidth;
private int parentFormHeight;
private SplitterState currentState;
private int animationDelay = 20;
private int animationStep = 20;
private bool useAnimations;
private IVisualStyle styleDrawer;
#endregion
#region Public Properties
/// <summary>
/// The initial state of the Splitter. Set to True if the control to hide is not visible by default
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("False"),
Description("The initial state of the Splitter. Set to True if the control to hide is not visible by default")]
public bool IsCollapsed
{
get
{
if (this.controlToHide != null)
return !this.controlToHide.Visible;
else
return true;
}
}
/// <summary>
/// The System.Windows.Forms.Control that the splitter will collapse
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue(""),
Description("The System.Windows.Forms.Control that the splitter will collapse")]
public System.Windows.Forms.Control ControlToHide
{
get { return this.controlToHide; }
set { this.controlToHide = value; }
}
/// <summary>
/// Determines if the collapse and expanding actions will be animated
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("True"),
Description("Determines if the collapse and expanding actions will be animated")]
public bool UseAnimations
{
get { return this.useAnimations; }
set { this.useAnimations = value; }
}
/// <summary>
/// The delay in millisenconds between animation steps
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("20"),
Description("The delay in millisenconds between animation steps")]
public int AnimationDelay
{
get { return this.animationDelay; }
set { this.animationDelay = value; }
}
/// <summary>
/// The amount of pixels moved in each animation step
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("20"),
Description("The amount of pixels moved in each animation step")]
public int AnimationStep
{
get { return this.animationStep; }
set { this.animationStep = value; }
}
/// <summary>
/// When true the entire parent form will be expanded and collapsed, otherwise just the contol to expand will be changed
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("False"),
Description("When true the entire parent form will be expanded and collapsed, otherwise just the contol to expand will be changed")]
public bool ExpandParentForm
{
get { return this.expandParentForm; }
set { this.expandParentForm = value; }
}
/// <summary>
/// The visual style that will be painted on the control
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("VisualStyles.XP"),
Description("The visual style that will be painted on the control")]
public VisualStyles VisualStyle
{
get { return this.visualStyle; }
set
{
/*
this.visualStyle = value;
this.Invalidate();
* */
this.visualStyle = value;
switch (value)
{
case VisualStyles.Mozilla:
styleDrawer = new VisualStyleMozilla();
break;
case VisualStyles.XP:
styleDrawer = new VisualStyleXP();
break;
case VisualStyles.Win9x:
styleDrawer = new VisualStyleWin9x();
break;
case VisualStyles.DoubleDots:
styleDrawer = new VisualStyleDoubleDots();
break;
case VisualStyles.Lines:
styleDrawer = new VisualStyleLines();
break;
}
this.Invalidate();
}
}
/// <summary>
/// An optional border style to paint on the control. Set to Flat for no border
/// </summary>
[Bindable(true), Category("Collapsing Options"), DefaultValue("System.Windows.Forms.Border3DStyle.Flat"),
Description("An optional border style to paint on the control. Set to Flat for no border")]
public System.Windows.Forms.Border3DStyle BorderStyle3D
{
get { return this.borderStyle; }
set
{
this.borderStyle = value;
this.Invalidate();
}
}
#endregion
#region Public Methods
public void ToggleState()
{
this.ToggleSplitter();
}
#endregion
#region Constructor
public CollapsibleSplitter()
{
// Register mouse events
this.Click += new System.EventHandler(OnClick);
this.Resize += new System.EventHandler(OnResize);
this.MouseLeave += new System.EventHandler(OnMouseLeave);
this.MouseMove += new MouseEventHandler(OnMouseMove);
// Setup the animation timer control
this.animationTimer = new System.Windows.Forms.Timer();
this.animationTimer.Interval = animationDelay;
this.animationTimer.Tick += new System.EventHandler(this.animationTimerTick);
}
#endregion
#region Overrides
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
this.parentForm = this.FindForm();
// set the current state
if (this.controlToHide != null)
{
if (this.controlToHide.Visible)
{
this.currentState = SplitterState.Expanded;
}
else
{
this.currentState = SplitterState.Collapsed;
}
}
}
protected override void OnEnabledChanged(System.EventArgs e)
{
base.OnEnabledChanged(e);
this.Invalidate();
}
#endregion
#region Event Handlers
protected override void OnMouseDown(MouseEventArgs e)
{
// if the hider control isn't hot, let the base resize action occur
if (this.controlToHide != null)
{
if (!this.hot && this.controlToHide.Visible)
{
base.OnMouseDown(e);
}
}
}
private void OnResize(object sender, System.EventArgs e)
{
this.Invalidate();
}
// this method was updated in version 1.11 to fix a flickering problem
// discovered by John O'Byrne
private void OnMouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
// check to see if the mouse cursor position is within the bounds of our control
if (e.X >= rr.X && e.X <= rr.X + rr.Width && e.Y >= rr.Y && e.Y <= rr.Y + rr.Height)
{
if (!this.hot)
{
this.hot = true;
this.Cursor = Cursors.Hand;
this.Invalidate();
}
}
else
{
if (this.hot)
{
this.hot = false;
this.Invalidate(); ;
}
this.Cursor = Cursors.Default;
if (controlToHide != null)
{
if (!controlToHide.Visible)
this.Cursor = Cursors.Default;
else // Changed in v1.2 to support Horizontal Splitters
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
this.Cursor = Cursors.VSplit;
}
else
{
this.Cursor = Cursors.HSplit;
}
}
}
}
}
private void OnMouseLeave(object sender, System.EventArgs e)
{
// ensure that the hot state is removed
this.hot = false;
this.Invalidate(); ;
}
private void OnClick(object sender, System.EventArgs e)
{
if (controlToHide != null && hot &&
currentState != SplitterState.Collapsing &&
currentState != SplitterState.Expanding)
{
ToggleSplitter();
}
}
private void ToggleSplitter()
{
// if an animation is currently in progress for this control, drop out
if (currentState == SplitterState.Collapsing || currentState == SplitterState.Expanding)
return;
controlWidth = controlToHide.Width;
controlHeight = controlToHide.Height;
if (controlToHide.Visible)
{
if (useAnimations)
{
currentState = SplitterState.Collapsing;
if (parentForm != null)
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
parentFormWidth = parentForm.Width - controlWidth;
}
else
{
parentFormHeight = parentForm.Height - controlHeight;
}
}
this.animationTimer.Enabled = true;
}
else
{
// no animations, so just toggle the visible state
currentState = SplitterState.Collapsed;
controlToHide.Visible = false;
if (expandParentForm && parentForm != null)
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
parentForm.Width -= controlToHide.Width;
}
else
{
parentForm.Height -= controlToHide.Height;
}
}
}
}
else
{
// control to hide is collapsed
if (useAnimations)
{
currentState = SplitterState.Expanding;
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
if (parentForm != null)
{
parentFormWidth = parentForm.Width + controlWidth;
}
controlToHide.Width = 0;
}
else
{
if (parentForm != null)
{
parentFormHeight = parentForm.Height + controlHeight;
}
controlToHide.Height = 0;
}
controlToHide.Visible = true;
this.animationTimer.Enabled = true;
}
else
{
// no animations, so just toggle the visible state
currentState = SplitterState.Expanded;
controlToHide.Visible = true;
if (expandParentForm && parentForm != null)
{
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
parentForm.Width += controlToHide.Width;
}
else
{
parentForm.Height += controlToHide.Height;
}
}
}
}
}
#endregion
#region Implementation
#region Animation Timer Tick
private void animationTimerTick(object sender, System.EventArgs e)
{
switch (currentState)
{
case SplitterState.Collapsing:
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
// vertical splitter
if (controlToHide.Width > animationStep)
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width -= animationStep;
}
controlToHide.Width -= animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width = parentFormWidth;
}
controlToHide.Visible = false;
animationTimer.Enabled = false;
controlToHide.Width = controlWidth;
currentState = SplitterState.Collapsed;
this.Invalidate();
}
}
else
{
// horizontal splitter
if (controlToHide.Height > animationStep)
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height -= animationStep;
}
controlToHide.Height -= animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height = parentFormHeight;
}
controlToHide.Visible = false;
animationTimer.Enabled = false;
controlToHide.Height = controlHeight;
currentState = SplitterState.Collapsed;
this.Invalidate();
}
}
break;
case SplitterState.Expanding:
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
// vertical splitter
if (controlToHide.Width < (controlWidth - animationStep))
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width += animationStep;
}
controlToHide.Width += animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Width = parentFormWidth;
}
controlToHide.Width = controlWidth;
controlToHide.Visible = true;
animationTimer.Enabled = false;
currentState = SplitterState.Expanded;
this.Invalidate();
}
}
else
{
// horizontal splitter
if (controlToHide.Height < (controlHeight - animationStep))
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height += animationStep;
}
controlToHide.Height += animationStep;
}
else
{
if (expandParentForm && parentForm.WindowState != FormWindowState.Maximized
&& parentForm != null)
{
parentForm.Height = parentFormHeight;
}
controlToHide.Height = controlHeight;
controlToHide.Visible = true;
animationTimer.Enabled = false;
currentState = SplitterState.Expanded;
this.Invalidate();
}
}
break;
}
}
#endregion
#region Paint the control
// OnPaint is now an override rather than an event in version 1.1
protected override void OnPaint(PaintEventArgs e)
{
// create a Graphics object
Graphics g = e.Graphics;
// find the rectangle for the splitter and paint it
Rectangle r = this.ClientRectangle; // fixed in version 1.1
g.FillRectangle(new SolidBrush(this.BackColor), r);
#region Vertical Splitter
// Check the docking style and create the control rectangle accordingly
if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
{
// create a new rectangle in the vertical center of the splitter for our collapse control button
rr = new Rectangle(r.X, (int)r.Y + ((r.Height - 115) / 2), 8, 115);
// force the width to 8px so that everything always draws correctly
this.Width = 8;
// draw the background color for our control image
if (hot)
{
g.FillRectangle(new SolidBrush(hotColor), new Rectangle(rr.X + 1, rr.Y, 6, 115));
}
else
{
g.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(rr.X + 1, rr.Y, 6, 115));
}
// draw the top & bottom lines for our control image
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + 1, rr.Y, rr.X + rr.Width - 2, rr.Y);
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + 1, rr.Y + rr.Height, rr.X + rr.Width - 2, rr.Y + rr.Height);
if (this.Enabled)
{
// draw the arrows for our control image
// the ArrowPointArray is a point array that defines an arrow shaped polygon
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 2, rr.Y + 3));
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 2, rr.Y + rr.Height - 9));
}
// draw the dots for our control image using a loop
int x = rr.X + 3;
int y = rr.Y + 14;
// Visual Styles added in version 1.1
#region 重构后废除的代码
/*
switch (visualStyle)
{
case VisualStyles.Mozilla:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y + (i * 3), x + 1, y + 1 + (i * 3));
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
if (hot)
{
g.DrawLine(new Pen(hotColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
else
{
g.DrawLine(new Pen(this.BackColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
}
break;
case VisualStyles.DoubleDots:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x - 1, y + (i * 3), 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 2, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + 1, y + (i * 3), 1, 1);
}
break;
case VisualStyles.Win9x:
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 2, y);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 2, y, x + 2, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 90, x + 2, y + 90);
break;
case VisualStyles.XP:
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x, y + (i * 5), 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1, y + 1 + (i * 5), 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x, y + (i * 5), 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x, y + (i * 5) + 1);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x + 1, y + (i * 5));
}
break;
case VisualStyles.Lines:
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 2), x + 2, y + (i * 2));
}
break;
}
*/
#endregion
styleDrawer.DrawVertical(g, x, y, hot ? hotColor : BackColor);
// Added in version 1.3
if (this.borderStyle != System.Windows.Forms.Border3DStyle.Flat)
{
// Paint the control border
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Left);
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Right);
}
}
#endregion
// Horizontal Splitter support added in v1.2
#region Horizontal Splitter
else if (this.Dock == DockStyle.Top || this.Dock == DockStyle.Bottom)
{
// create a new rectangle in the horizontal center of the splitter for our collapse control button
rr = new Rectangle((int)r.X + ((r.Width - 115) / 2), r.Y, 115, 8);
// force the height to 8px
this.Height = 8;
// draw the background color for our control image
if (hot)
{
g.FillRectangle(new SolidBrush(hotColor), new Rectangle(rr.X, rr.Y + 1, 115, 6));
}
else
{
g.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(rr.X, rr.Y + 1, 115, 6));
}
// draw the left & right lines for our control image
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X, rr.Y + 1, rr.X, rr.Y + rr.Height - 2);
g.DrawLine(new Pen(SystemColors.ControlDark, 1), rr.X + rr.Width, rr.Y + 1, rr.X + rr.Width, rr.Y + rr.Height - 2);
if (this.Enabled)
{
// draw the arrows for our control image
// the ArrowPointArray is a point array that defines an arrow shaped polygon
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + 3, rr.Y + 2));
g.FillPolygon(new SolidBrush(SystemColors.ControlDarkDark), ArrowPointArray(rr.X + rr.Width - 9, rr.Y + 2));
}
// draw the dots for our control image using a loop
int x = rr.X + 14;
int y = rr.Y + 3;
// Visual Styles added in version 1.1
#region 重构后废除的代码
/*
switch (visualStyle)
{
case VisualStyles.Mozilla:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x + (i * 3), y, x + 1 + (i * 3), y + 1);
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1 + (i * 3), y + 1, x + 2 + (i * 3), y + 2);
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
if (hot)
{
g.DrawLine(new Pen(hotColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
else
{
g.DrawLine(new Pen(this.BackColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
}
break;
case VisualStyles.DoubleDots:
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y - 1, 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y + 2, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y + 1, 1, 1);
}
break;
case VisualStyles.Win9x:
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 2);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 88, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 2, x + 88, y + 2);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 88, y, x + 88, y + 2);
break;
case VisualStyles.XP:
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x + (i * 5), y, 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 5), y + 1, 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x + (i * 5), y, 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5) + 1, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5), y + 1);
}
break;
case VisualStyles.Lines:
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 2), y, x + (i * 2), y + 2);
}
break;
}
*/
#endregion
styleDrawer.DrawHorizontal(g, x, y, hot ? hotColor : BackColor);
// Added in version 1.3
if (this.borderStyle != System.Windows.Forms.Border3DStyle.Flat)
{
// Paint the control border
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Top);
ControlPaint.DrawBorder3D(e.Graphics, this.ClientRectangle, this.borderStyle, Border3DSide.Bottom);
}
}
#endregion
else
{
throw new Exception("The Collapsible Splitter control cannot have the Filled or None Dockstyle property");
}
// dispose the Graphics object
g.Dispose();
}
#endregion
#region Arrow Polygon Array
// This creates a point array to draw a arrow-like polygon
private Point[] ArrowPointArray(int x, int y)
{
Point[] point = new Point[3];
if (controlToHide != null)
{
// decide which direction the arrow will point
if (
(this.Dock == DockStyle.Right && controlToHide.Visible)
|| (this.Dock == DockStyle.Left && !controlToHide.Visible)
)
{
// right arrow
point[0] = new Point(x, y);
point[1] = new Point(x + 3, y + 3);
point[2] = new Point(x, y + 6);
}
else if (
(this.Dock == DockStyle.Right && !controlToHide.Visible)
|| (this.Dock == DockStyle.Left && controlToHide.Visible)
)
{
// left arrow
point[0] = new Point(x + 3, y);
point[1] = new Point(x, y + 3);
point[2] = new Point(x + 3, y + 6);
}
// Up/Down arrows added in v1.2
else if (
(this.Dock == DockStyle.Top && controlToHide.Visible)
|| (this.Dock == DockStyle.Bottom && !controlToHide.Visible)
)
{
// up arrow
point[0] = new Point(x + 3, y);
point[1] = new Point(x + 6, y + 4);
point[2] = new Point(x, y + 4);
}
else if (
(this.Dock == DockStyle.Top && !controlToHide.Visible)
|| (this.Dock == DockStyle.Bottom && controlToHide.Visible)
)
{
// down arrow
point[0] = new Point(x, y);
point[1] = new Point(x + 6, y);
point[2] = new Point(x + 3, y + 3);
}
}
return point;
}
#endregion
#region Color Calculator
// this method was borrowed from the RichUI Control library by Sajith M
private static Color CalculateColor(Color front, Color back, int alpha)
{
// solid color obtained as a result of alpha-blending
Color frontColor = Color.FromArgb(255, front);
Color backColor = Color.FromArgb(255, back);
float frontRed = frontColor.R;
float frontGreen = frontColor.G;
float frontBlue = frontColor.B;
float backRed = backColor.R;
float backGreen = backColor.G;
float backBlue = backColor.B;
float fRed = frontRed * alpha / 255 + backRed * ((float)(255 - alpha) / 255);
byte newRed = (byte)fRed;
float fGreen = frontGreen * alpha / 255 + backGreen * ((float)(255 - alpha) / 255);
byte newGreen = (byte)fGreen;
float fBlue = frontBlue * alpha / 255 + backBlue * ((float)(255 - alpha) / 255);
byte newBlue = (byte)fBlue;
return Color.FromArgb(255, newRed, newGreen, newBlue);
}
#endregion
#endregion
}
/// <summary>
/// A simple designer class for the CollapsibleSplitter control to remove
/// unwanted properties at design time.
/// </summary>
public class CollapsibleSplitterDesigner : System.Windows.Forms.Design.ControlDesigner
{
public CollapsibleSplitterDesigner()
{
}
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
properties.Remove("IsCollapsed");
properties.Remove("BorderStyle");
properties.Remove("Size");
}
}
#region 显示风格的接口和实现
interface IVisualStyle
{
void DrawVertical(Graphics g, int x, int y, Color lineColor);
void DrawHorizontal(Graphics g, int x, int y, Color lineColor);
}
public class VisualStyleMozilla : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y + (i * 3), x + 1, y + 1 + (i * 3));
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
g.DrawLine(new Pen(lineColor), x + 2, y + 1 + (i * 3), x + 2, y + 2 + (i * 3));
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawLine(new Pen(SystemColors.ControlLightLight), x + (i * 3), y, x + 1 + (i * 3), y + 1);
// dark dot
g.DrawLine(new Pen(SystemColors.ControlDarkDark), x + 1 + (i * 3), y + 1, x + 2 + (i * 3), y + 2);
// overdraw the background color as we actually drew 2px diagonal lines, not just dots
g.DrawLine(new Pen(lineColor), x + 1 + (i * 3), y + 2, x + 2 + (i * 3), y + 2);
}
}
}
public class VisualStyleXP : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x, y + (i * 5), 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1, y + 1 + (i * 5), 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x, y + (i * 5), 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x, y + (i * 5) + 1);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 5), x + 1, y + (i * 5));
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 18; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLight), x + (i * 5), y, 2, 2);
// light light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 5), y + 1, 1, 1);
// dark dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDarkDark), x + (i * 5), y, 1, 1);
// dark fill
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5) + 1, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 5), y, x + (i * 5), y + 1);
}
}
}
public class VisualStyleWin9x : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 2, y);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 2, y, x + 2, y + 90);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 90, x + 2, y + 90);
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x, y + 2);
g.DrawLine(new Pen(SystemColors.ControlLightLight), x, y, x + 88, y);
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + 2, x + 88, y + 2);
g.DrawLine(new Pen(SystemColors.ControlDark), x + 88, y, x + 88, y + 2);
}
}
public class VisualStyleDoubleDots : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x - 1, y + (i * 3), 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 2, y + 1 + (i * 3), 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + 1, y + (i * 3), 1, 1);
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 30; i++)
{
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y - 1, 1, 1);
i++;
// light dot
g.DrawRectangle(new Pen(SystemColors.ControlLightLight), x + 1 + (i * 3), y + 2, 1, 1);
// dark dot
g.DrawRectangle(new Pen(SystemColors.ControlDark), x + (i * 3), y + 1, 1, 1);
}
}
}
public class VisualStyleLines : IVisualStyle
{
public void DrawVertical(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x, y + (i * 2), x + 2, y + (i * 2));
}
}
public void DrawHorizontal(Graphics g, int x, int y, Color lineColor)
{
for (int i = 0; i < 44; i++)
{
g.DrawLine(new Pen(SystemColors.ControlDark), x + (i * 2), y, x + (i * 2), y + 2);
}
}
}
#endregion
使用方法:
左放一个panel ,然后拖这个控件,然后右边放一个panel,
如果要双击该控件隐藏左边panel,则设置左边panel的Dock为Left,该控件的Dock为Left,然后,右边的控件为Fill,
然后设置该控件的ControlToHide为左边控件。
使用介绍
his.collapsibleSplitter1.AnimationDelay = 20;
this.collapsibleSplitter1.AnimationStep = 20;
this.collapsibleSplitter1.BorderStyle3D = System.Windows.Forms.Border3DStyle.RaisedOuter;
this.collapsibleSplitter1.ControlToHide = this.panel11;
this.collapsibleSplitter1.Dock = System.Windows.Forms.DockStyle.Right;
this.collapsibleSplitter1.ExpandParentForm = false;
this.collapsibleSplitter1.Location = new System.Drawing.Point(332, 0);
this.collapsibleSplitter1.Name = "collapsibleSplitter1";
this.collapsibleSplitter1.TabIndex = 1;
this.collapsibleSplitter1.TabStop = false;
this.collapsibleSplitter1.UseAnimations = false;
this.collapsibleSplitter1.VisualStyle = BOCO.ENoss.Framework.Busi.Core.VisualStyles.Mozilla;
///省去了左右panel的定义。
主要是设置两panel的Dock属性就行了
his.collapsibleSplitter1.AnimationDelay = 20;
this.collapsibleSplitter1.AnimationStep = 20;
this.collapsibleSplitter1.BorderStyle3D = System.Windows.Forms.Border3DStyle.RaisedOuter;
this.collapsibleSplitter1.ControlToHide = this.panel11;
this.collapsibleSplitter1.Dock = System.Windows.Forms.DockStyle.Right;
this.collapsibleSplitter1.ExpandParentForm = false;
this.collapsibleSplitter1.Location = new System.Drawing.Point(332, 0);
this.collapsibleSplitter1.Name = "collapsibleSplitter1";
this.collapsibleSplitter1.TabIndex = 1;
this.collapsibleSplitter1.TabStop = false;
this.collapsibleSplitter1.UseAnimations = false;
this.collapsibleSplitter1.VisualStyle = BOCO.ENoss.Framework.Busi.Core.VisualStyles.Mozilla;
///省去了左右panel的定义。
主要是设置两panel的Dock属性就行了
有事Q我:
姓名:颜昌钢
联系方式:yanchanggang@boco.com.cn
电话:13886086508
QQ:95550107
公司:亿阳集团武汉分公司
移动飞信:647360243