|
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
using System.Windows.Forms.Design;
namespace XPTaskBar
{
#region Delegates
/// <summary>
///
/// </summary>
public delegate void TaskPaneEventHandler(TaskPaneEventArgs e);
#endregion
#region TaskPane
/// <summary>
/// Summary description for TaskPane.
/// </summary>
[ToolboxItem(true)]
[DesignerAttribute(typeof(TaskPaneDesigner))]
public class TaskPane : Panel, ISupportInitialize
{
#region Event Handlers
/// <summary>
///
/// </summary>
public event TaskPaneEventHandler ExpandoAdded;
/// <summary>
///
/// </summary>
public event TaskPaneEventHandler ExpandoRemoved;
/// <summary>
///
/// </summary>
public event TaskPaneEventHandler ExpandoStateChanged;
#endregion
#region Class Data
// system defined settings for the TaskBar
protected TaskBarInfo systemSettings;
// should we animate expanding/collapsing
protected bool animate;
protected ArrayList animationHelpers;
// internal list of all Expandos in the TaskPane
protected ExpandoCollection expandoList;
// are we initialising
protected bool initialising = false;
//
protected bool classicTheme;
protected bool customTheme;
// Required designer variable
private System.ComponentModel.Container components = null;
#endregion
#region Constructor
/// <summary>
///
/// </summary>
public TaskPane()
{
// This call is required by the Windows.Forms Form Designer.
components = new System.ComponentModel.Container();
// set control styles
this.SetStyle(ControlStyles.DoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.ResizeRedraw, true);
// get the system theme settings
this.systemSettings = Util.GetSystemTaskBarSettings();
this.classicTheme = false;
this.customTheme = false;
// size
int width = (this.systemSettings.TaskPane.Padding.Left +
this.systemSettings.TaskPane.Padding.Right +
this.systemSettings.Header.BackImageWidth);
int height = width;
this.Size = new Size(width, height);
// background color
this.BackColor = systemSettings.TaskPane.GradientStartColor;
// setup sutoscrolling
this.AutoScroll = false;
this.AutoScrollMargin = new Size(this.systemSettings.TaskPane.Padding.Right,
this.systemSettings.TaskPane.Padding.Bottom);
// don't use animation
this.animate = false;
this.animationHelpers = new ArrayList();
//
this.expandoList = new ExpandoCollection();
}
#endregion
#region Methods
#region Animation
/// <summary>
///
/// </summary>
internal void StartAnimation(Expando expando)
{
AnimationHelper animationHelper = new AnimationHelper(this, expando);
this.animationHelpers.Add(animationHelper);
animationHelper.StartAnimation();
}
/// <summary>
///
/// </summary>
internal void AnimationStopped(AnimationHelper animationHelper)
{
this.animationHelpers.Remove(animationHelper);
animationHelper = null;
this.Invalidate();
}
#endregion
#region Appearance
/// <summary>
/// Forces the TaskPane and all it's Expandos to use a theme
/// equivalent to Windows XPs classic theme
/// </summary>
public void UseClassicTheme()
{
this.classicTheme = true;
this.customTheme = false;
this.systemSettings.UseClassicTheme();
foreach (Expando expando in this.expandoList)
{
expando.SystemSettings = this.systemSettings;
}
this.DoLayout();
this.Invalidate(true);
}
/// <summary>
/// Forces the TaskPane and all it's Expandos to use the
/// specified theme
/// </summary>
/// <param name="stylePath">The path to the custom
/// shellstyle.dll to use</param>
public void UseCustomTheme(string stylePath)
{
this.customTheme = true;
this.classicTheme = false;
this.systemSettings.Dispose();
this.systemSettings = null;
this.systemSettings = Util.GetSystemTaskBarSettings(stylePath);
foreach (Expando expando in this.expandoList)
{
expando.SystemSettings = this.systemSettings;
}
this.DoLayout();
this.Invalidate(true);
}
/// <summary>
/// Forces the TaskPane and all it's Expandos to use the
/// current system theme
/// </summary>
public void UseDefaultTheme()
{
this.customTheme = false;
this.classicTheme = false;
this.systemSettings.Dispose();
this.systemSettings = null;
this.systemSettings = Util.GetSystemTaskBarSettings();
foreach (Expando expando in this.expandoList)
{
expando.SystemSettings = this.systemSettings;
}
this.DoLayout();
this.Invalidate(true);
}
#endregion
#region Dispose
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
if (this.systemSettings != null)
{
this.systemSettings.Dispose();
}
}
base.Dispose(disposing);
}
#endregion
#region Expandos
/// <summary>
/// Collaspes all the Expandos contained in the TaskPane
/// </summary>
public void CollapseAll()
{
foreach (Expando expando in this.expandoList)
{
expando.Collapsed = true;
}
}
/// <summary>
/// Expands all the Expandos contained in the TaskPane
/// </summary>
public void ExpandAll()
{
foreach (Expando expando in this.expandoList)
{
expando.Collapsed = false;
}
}
/// <summary>
/// Collaspes all the Expandos contained in the TaskPane,
/// except for the specified Expando which is expanded
/// </summary>
public void CollapseAllButOne(Expando expando)
{
foreach (Expando e in this.expandoList)
{
if (e != expando)
{
e.Collapsed = true;
}
else
{
expando.Collapsed = false;
}
}
}
#endregion
#region ISupportInitialize Members
/// <summary>
///
/// </summary>
public void BeginInit()
{
this.initialising = true;
}
/// <summary>
///
/// </summary>
public void EndInit()
{
this.initialising = false;
this.DoLayout();
}
#endregion
#region Layout
/// <summary>
///
/// </summary>
public void DoLayout()
{
// stop the layout engine
this.SuspendLayout();
Expando e;
Point p;
// work out how wide to make the controls, and where
// the top of the first control should be
int y = this.DisplayRectangle.Y + this.Padding.Top;
int width = this.ClientSize.Width - this.Padding.Left - this.Padding.Right;
// for each control in our list...
for (int i=0; i<this.expandoList.Count; i++)
{
e = this.expandoList[i];
p = new Point(this.Padding.Left, y);
// set the width and location of the control
e.Location = p;
e.Width = width;
// update the next starting point
y += e.Height + this.Padding.Bottom;
}
// restart the layout engine
this.ResumeLayout(true);
}
#endregion
#endregion
#region Properties
#region Animation
/// <summary>
/// Specifies whether the TaskPane should animate Expando's
/// when they collapse or expand.
/// </summary>
[Bindable(true),
Category("Appearance"),
DefaultValue(false),
Description("Specifies whether the TaskPane should animate Expando's when they collapse or expand.")]
public bool Animate
{
get
{
return this.animate;
}
set
{
this.animate = value;
}
}
/// <summary>
/// Determines whether the TaskPane is currently animating
/// an Expando
/// </summary>
[Browsable(false)]
public bool IsAnimating
{
get
{
return this.animationHelpers.Count > 0;
}
}
#endregion
#region Border
/// <summary>
///
/// </summary>
protected Border Border
{
get
{
return this.systemSettings.TaskPane.Border;
}
}
/// <summary>
///
/// </summary>
protected Color BorderColor
{
get
{
return this.systemSettings.TaskPane.BorderColor;
}
}
#endregion
#region Colors
/// <summary>
/// The first color of the TaskPane's background gradient fill.
/// </summary>
[Browsable(false)]
public Color GradientStartColor
{
get
{
return this.systemSettings.TaskPane.GradientStartColor;
}
}
/// <summary>
/// The second color of the TaskPane's background gradient fill.
/// </summary>
[Browsable(false)]
public Color GradientEndColor
{
get
{
return this.systemSettings.TaskPane.GradientEndColor;
}
}
/// <summary>
/// The direction of the TaskPane's background gradient fill.
/// </summary>
[Browsable(false)]
public LinearGradientMode GradientDirection
{
get
{
return this.systemSettings.TaskPane.GradientDirection;
}
}
#endregion
#region Padding
/// <summary>
/// The amount of space between the border and the
/// Expando's along each side of the TaskPane.
/// </summary>
protected Padding Padding
{
get
{
return this.systemSettings.TaskPane.Padding;
}
}
#endregion
#endregion
#region Events
#region Controls
/// <summary>
/// Raises the ControlAdded event
/// </summary>
protected override void OnControlAdded(ControlEventArgs e)
{
base.OnControlAdded(e);
// make sure the control is an Expando
if ((e.Control as Expando) == null)
{
// remove the control
this.Controls.Remove(e.Control);
// throw a hissy fit
throw new InvalidCastException("Only Expando's can be added to the TaskPane");
}
//
OnExpandoAdded(new TaskPaneEventArgs(this, (Expando) e.Control));
}
/// <summary>
/// Raises the ControlRemoved event
/// </summary>
protected override void OnControlRemoved(ControlEventArgs e)
{
base.OnControlRemoved(e);
if (e.Control is Expando)
{
OnExpandoRemoved(new TaskPaneEventArgs(this, (Expando) e.Control));
}
}
#endregion
#region Expandos
/// <summary>
/// Event handler for the Expando StateChanged event
/// </summary>
private void expando_StateChanged(ExpandoEventArgs e)
{
OnExpandoStateChanged(new TaskPaneEventArgs(this, e.Expando));
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected virtual void OnExpandoStateChanged(TaskPaneEventArgs e)
{
// if we can perform animations...
if (this.animate && !this.DesignMode)
{
this.StartAnimation(e.Expando);
}
else
{
// if we get here, the Expando has collapsed/expanded itself
// so we need to update the layout of the controls
this.DoLayout();
// sometimes the background colors doesn't update correctly,
// so get the TaskPane to repaint itself (without painting
// the Expandos)
this.Invalidate(false);
}
//
if (ExpandoStateChanged != null)
{
ExpandoStateChanged(e);
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected virtual void OnExpandoAdded(TaskPaneEventArgs e)
{
if (!this.expandoList.Contains(e.Expando))
{
// are we initialising
if (this.initialising)
{
// add new controls to the beginning of the list
this.expandoList.Insert(0, e.Expando);
}
else
{
// otherwise add to the end of the list
this.expandoList.Add(e.Expando);
}
// set anchor styles
e.Expando.Anchor = (AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right);
}
// tell the Expando who's its daddy...
e.Expando.TaskPane = this;
e.Expando.SystemSettings = this.systemSettings;
// listen for collapse/expand events
e.Expando.StateChanged += new ExpandoEventHandler(this.expando_StateChanged);
// update the layout of the controls
this.DoLayout();
//
if (ExpandoAdded != null)
{
ExpandoAdded(e);
}
}
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected virtual void OnExpandoRemoved(TaskPaneEventArgs e)
{
// remove the control from the ExpandoCollection
this.expandoList.Remove(e.Expando);
// remove the StateChanged listener
e.Expando.StateChanged -= new ExpandoEventHandler(this.expando_StateChanged);
// update the layout of the controls
this.DoLayout();
//
if (ExpandoRemoved != null)
{
ExpandoRemoved(e);
}
}
#endregion
#region Paint
/// <summary>
/// Raises the Paint event
/// </summary>
protected override void OnPaint(PaintEventArgs e)
{
// paint background
using (LinearGradientBrush brush = new LinearGradientBrush(this.DisplayRectangle,
this.GradientStartColor,
this.GradientEndColor,
this.GradientDirection))
{
e.Graphics.FillRectangle(brush, this.DisplayRectangle);
}
}
#endregion
#region System Colors
/// <summary>
/// Raises the SystemColorsChanged event
/// </summary>
protected override void OnSystemColorsChanged(EventArgs e)
{
base.OnSystemColorsChanged(e);
// don't go any further if we are explicitly using
// the classic or a custom theme
if (this.classicTheme || this.customTheme)
{
return;
}
this.SuspendLayout();
// get rid of the current system theme info
this.systemSettings.Dispose();
this.systemSettings = null;
// get a new system theme info for the new theme
this.systemSettings = Util.GetSystemTaskBarSettings();
// update the system settings for each expando
foreach (Control control in this.Controls)
{
if (control is Expando)
{
Expando expando = (Expando) control;
expando.SystemSettings = this.systemSettings;
}
}
// update the layout of the controls
this.DoLayout();
}
#endregion
#endregion
}
#endregion
#region TaskPaneDesigner
/// <summary>
/// Summary description for ExplorerBarDesigner.
/// </summary>
public class TaskPaneDesigner : ScrollableControlDesigner
{
/// <summary>
///
/// </summary>
public TaskPaneDesigner()
{
}
/// <summary>
///
/// </summary>
protected override void PreFilterProperties(System.Collections.IDictionary properties)
{
base.PreFilterProperties(properties);
properties.Remove("BackColor");
properties.Remove("BackgroundImage");
}
}
#endregion
#region AnimationHelper
/// <summary>
///
/// </summary>
public class AnimationHelper
{
#region Class Data
//
protected TaskPane taskpane;
protected Expando expando;
//
private int animationStepNum;
protected int numAnimationSteps = 20;
protected int animationFrameInterval = 10;
protected bool animating;
protected Timer animationTimer;
#endregion
#region Constructor
/// <summary>
///
/// </summary>
public AnimationHelper(TaskPane taskpane, Expando expando)
{
this.taskpane = taskpane;
this.expando = expando;
this.animating = false;
// I know that this isn't the best way to do this, but I
// haven't quite worked out how to do it with threads so
// this will have to do for the moment
this.animationTimer = new Timer();
this.animationTimer.Tick += new EventHandler(this.animationTimer_Tick);
this.animationTimer.Interval = this.animationFrameInterval;
}
#endregion
#region Methods
/// <summary>
/// Starts the Expando collapse/expand animation
/// </summary>
public void StartAnimation()
{
// don't bother going any further if we are already animating
if (this.Animating)
{
return;
}
this.animationStepNum = 0;
// tell the expando to get redy to animate
this.expando.StartAnimation();
// start the animation timer
this.animationTimer.Start();
}
/// <summary>
/// Updates the animation for the Expando
/// </summary>
protected void PerformAnimation()
{
// if we have more animation steps to perform
if (this.animationStepNum < this.numAnimationSteps)
{
// update the animation step number
this.animationStepNum++;
// tell the animating expando to update the animation
this.expando.UpdateAnimation(this.animationStepNum, this.numAnimationSteps);
// rearrange the groups
this.taskpane.DoLayout();
}
else
{
// stop the animation
this.animationTimer.Stop();
this.expando.StopAnimation();
// let the TaskPane know that the animation has finished
// so it can do some cleaning up (like getting rid of us)
this.taskpane.AnimationStopped(this);
}
}
#endregion
#region Properties
/// <summary>
/// Gets the TaskPane that the AnimationHelper belongs to
/// </summary>
public TaskPane TaskPane
{
get
{
return this.taskpane;
}
}
/// <summary>
/// Gets the Expando that is te be animated
/// </summary>
public Expando Expando
{
get
{
return this.expando;
}
}
/// <summary>
/// Gets or sets the number of steps that are needed for the Expando
/// to get from fully expanded to fully collapsed, or visa versa
/// </summary>
public int NumAnimationSteps
{
get
{
return this.numAnimationSteps;
}
set
{
if (value < 0)
{
throw new ArgumentOutOfRangeException("value", "NumAnimationSteps must be at least 0");
}
// only change this if we are not currently animating
// (if we are animating, changing this could cause things
// to screw up big time)
if (!this.animating)
{
this.numAnimationSteps = value;
}
}
}
/// <summary>
/// Gets or sets the number of milliseconds that each "frame"
/// of the animation stays on the screen
/// </summary>
public int AnimationFrameInterval
{
get
{
return this.animationFrameInterval;
}
set
{
this.animationFrameInterval = value;
}
}
/// <summary>
/// Gets whether the Expando is currently animating
/// </summary>
public bool Animating
{
get
{
return this.animating;
}
}
#endregion
#region Events
/// <summary>
/// Event handler for the animation timer tick event
/// </summary>
private void animationTimer_Tick(object sender, EventArgs e)
{
// do the next bit of the aniation
PerformAnimation();
}
#endregion
}
#endregion
#region TaskPaneEventArgs
/// <summary>
/// Summary description for TaskPaneEventArgs.
/// </summary>
public class TaskPaneEventArgs : EventArgs
{
#region Class Data
/// <summary>
///
/// </summary>
protected TaskPane taskpane;
/// <summary>
///
/// </summary>
private Expando expando;
#endregion
#region Constructor
/// <summary>
///
/// </summary>
public TaskPaneEventArgs() : this(null, null)
{
}
/// <summary>
///
/// </summary>
/// <param name="taskPane"></param>
public TaskPaneEventArgs(TaskPane taskpane) : this(taskpane, null)
{
}
/// <summary>
///
/// </summary>
/// <param name="taskPane"></param>
/// <param name="expando"></param>
public TaskPaneEventArgs(TaskPane taskpane, Expando expando) : base()
{
this.taskpane = taskpane;
this.expando = expando;
}
#endregion
#region Properties
/// <summary>
///
/// </summary>
public TaskPane TaskPane
{
get
{
return this.taskpane;
}
}
/// <summary>
///
/// </summary>
public Expando Expando
{
get
{
return this.expando;
}
}
#endregion
}
#endregion
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.
A list of licenses authors might use can be found here
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.