context: using System;
  using System.Drawing;
  using System.Drawing.Imaging;
  using System.Windows.Forms;
  using System.ComponentModel;
  
  namespace DockSample.Customization
  {
  	internal class InertButton : Button
  	{
  		private enum RepeatClickStatus
  		{
  			Disabled,
  			Started,
  			Repeating,
  			Stopped
  		}
  
  		private class RepeatClickEventArgs : EventArgs
  		{
  			private static RepeatClickEventArgs _empty;
  
  			static RepeatClickEventArgs()
  			{
  				_empty = new RepeatClickEventArgs();
  			}
  
  			public new static RepeatClickEventArgs Empty
  			{
  				get	{	return _empty;	}
  			}
  		}
  
  		private IContainer components = new Container();
  		private int m_borderWidth = 1;
  		private bool m_mouseOver = false;
  		private bool m_mouseCapture = false;
  		private bool m_isPopup = false;
  		private Image m_imageEnabled = null;
  		private Image m_imageDisabled = null;
  		private int m_imageIndexEnabled = -1;
  		private int m_imageIndexDisabled = -1;
  		private bool m_monochrom = true;
  		private ToolTip m_toolTip = null;
  		private string m_toolTipText = "";
  		private Color m_borderColor = Color.Empty;
  
  		public InertButton()
  		{
  			InternalConstruct(null, null);
  		}
  
  		public InertButton(Image imageEnabled)
  		{
  			InternalConstruct(imageEnabled, null);
  		}
  
  		public InertButton(Image imageEnabled, Image imageDisabled)
  		{
  			InternalConstruct(imageEnabled, imageDisabled);
  		}
  		
  		private void InternalConstruct(Image imageEnabled, Image imageDisabled)
  		{
  			// Remember parameters
  			ImageEnabled = imageEnabled;
  			ImageDisabled = imageDisabled;
  
  			// Prevent drawing flicker by blitting from memory in WM_PAINT
  			SetStyle(ControlStyles.ResizeRedraw, true);
  			SetStyle(ControlStyles.UserPaint, true);
  			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
  
  			// Prevent base class from trying to generate double click events and
  			// so testing clicks against the double click time and rectangle. Getting
  			// rid of this allows the user to press then release button very quickly.
  			//SetStyle(ControlStyles.StandardDoubleClick, false);
  
  			// Should not be allowed to select this control
  			SetStyle(ControlStyles.Selectable, false);
  
  			m_timer = new Timer();
  			m_timer.Enabled = false;
  			m_timer.Tick += new EventHandler(Timer_Tick);
  		}
  
  		protected override void Dispose(bool disposing)
  		{
  			if (disposing)
  			{
  				if (components != null)
  					components.Dispose();
  			}
  			base.Dispose(disposing);
  		}
  
  		public Color BorderColor
  		{
  			get	{	return m_borderColor;	}
  			set
  			{
  				if (m_borderColor != value)
  				{
  					m_borderColor = value;
  					Invalidate();
  				}
  			}
  		}
  
  		private bool ShouldSerializeBorderColor()
  		{
  			return (m_borderColor != Color.Empty);
  		}
  
  		public int BorderWidth
  		{
  			get { return m_borderWidth; }
  
  			set
  			{
  				if (value < 1)
  					value = 1;
  				if (m_borderWidth != value)
  				{
  					m_borderWidth = value;
  					Invalidate();
  				}
  			}
  		}
  
  		public Image ImageEnabled
  		{
  			get
  			{ 
  				if (m_imageEnabled != null)
  					return m_imageEnabled;
  
  				try
  				{
  					if (ImageList == null || ImageIndexEnabled == -1)
  						return null;
  					else
  						return ImageList.Images[m_imageIndexEnabled];
  				}
  				catch
  				{
  					return null;
  				}
  			}
  
  			set
  			{
  				if (m_imageEnabled != value)
  				{
  					m_imageEnabled = value;
  					Invalidate();
  				}
  			}
  		}
  
  		private bool ShouldSerializeImageEnabled()
  		{
  			return (m_imageEnabled != null);
  		}
  
  		public Image ImageDisabled
  		{
  			get
  			{
  				if (m_imageDisabled != null)
  					return m_imageDisabled;
  
  				try
  				{
  					if (ImageList == null || ImageIndexDisabled == -1)
  						return null;
  					else
  						return ImageList.Images[m_imageIndexDisabled];
  				}
  				catch
  				{
  					return null;
  				}
  			}
  
  			set
  			{
  				if (m_imageDisabled != value)
  				{
  					m_imageDisabled = value;
  					Invalidate();
  				}
  			}
  		}
  
  		public int ImageIndexEnabled
  		{
  			get	{	return m_imageIndexEnabled;	}
  			set
  			{
  				if (m_imageIndexEnabled != value)
  				{
  					m_imageIndexEnabled = value;
  					Invalidate();
  				}
  			}
  		}
  
  		public int ImageIndexDisabled
  		{
  			get	{	return m_imageIndexDisabled;	}
  			set
  			{
  				if (m_imageIndexDisabled != value)
  				{
  					m_imageIndexDisabled = value;
  					Invalidate();
  				}
  			}
  		}
  
  		public bool IsPopup
  		{
  			get { return m_isPopup; }
  
  			set
  			{
  				if (m_isPopup != value)
  				{
  					m_isPopup = value;
  					Invalidate();
  				}
  			}
  		}
  
  		public bool Monochrome
  		{
  			get	{	return m_monochrom;	}
  			set
  			{
  				if (value != m_monochrom)
  				{
  					m_monochrom = value;
  					Invalidate();
  				}
  			}
  		}
  
  		public bool RepeatClick
  		{
  			get	{	return (ClickStatus != RepeatClickStatus.Disabled);	}
  			set	{	ClickStatus = RepeatClickStatus.Stopped;	}
  		}
  
  		private RepeatClickStatus m_clickStatus = RepeatClickStatus.Disabled;
  		private RepeatClickStatus ClickStatus
  		{
  			get	{	return m_clickStatus;	}
  			set
  			{
  				if (m_clickStatus == value)
  					return;
  
  				m_clickStatus = value;
  				if (ClickStatus == RepeatClickStatus.Started)
  				{
  					Timer.Interval = RepeatClickDelay;
  					Timer.Enabled = true;
  				}
  				else if (ClickStatus == RepeatClickStatus.Repeating)
  					Timer.Interval = RepeatClickInterval;
  				else
  					Timer.Enabled = false;
  			}
  		}
  
  		private int m_repeatClickDelay = 500;
  		public int RepeatClickDelay
  		{
  			get	{	return m_repeatClickDelay;	} 
  			set	{	m_repeatClickDelay = value;	}
  		}
  
  		private int m_repeatClickInterval = 100;
  		public int RepeatClickInterval
  		{
  			get	{	return m_repeatClickInterval;	}
  			set	{	m_repeatClickInterval = value;	}
  		}
  
  		private Timer m_timer;
  		private Timer Timer
  		{
  			get	{	return m_timer;	}
  		}
  
  		public string ToolTipText
  		{
  			get	{	return m_toolTipText;	}
  			set
  			{
  				if (m_toolTipText != value)
  				{
  					if (m_toolTip == null)
  						m_toolTip = new ToolTip(this.components);
  					m_toolTipText = value;
  					m_toolTip.SetToolTip(this, value);
  				}
  			}
  		}
  
  		private void Timer_Tick(object sender, EventArgs e)
  		{
  			if (m_mouseCapture && m_mouseOver)
  				OnClick(RepeatClickEventArgs.Empty);
  			if (ClickStatus == RepeatClickStatus.Started)
  				ClickStatus = RepeatClickStatus.Repeating;
  		}
  
  		/// <exclude/>
  		protected override void OnMouseDown(MouseEventArgs e)
  		{
  			base.OnMouseDown(e);
  
  			if (e.Button != MouseButtons.Left)
  				return;
  
  			if (m_mouseCapture == false || m_mouseOver == false)
  			{
  				m_mouseCapture = true;
  				m_mouseOver = true;
  
  				//Redraw to show button state
  				Invalidate();
  			}
  
  			if (RepeatClick)
  			{
  				OnClick(RepeatClickEventArgs.Empty);
  				ClickStatus = RepeatClickStatus.Started;
  			}
  		}
  
  		/// <exclude/>
  		protected override void OnClick(EventArgs e)
  		{
  			if (RepeatClick && !(e is RepeatClickEventArgs))
  				return;
  
  			base.OnClick (e);
  		}
  
  		/// <exclude/>
  		protected override void OnMouseUp(MouseEventArgs e)
  		{
  			base.OnMouseUp(e);
  
  			if (e.Button != MouseButtons.Left)
  				return;
  
  			if (m_mouseOver == true || m_mouseCapture == true)
  			{
  				m_mouseOver = false;
  				m_mouseCapture = false;
  
  				// Redraw to show button state
  				Invalidate();
  			}
  
  			if (RepeatClick)
  				ClickStatus = RepeatClickStatus.Stopped;
  		}
  
  		/// <exclude/>
  		protected override void OnMouseMove(MouseEventArgs e)
  		{
  			base.OnMouseMove(e);
  
  			// Is mouse point inside our client rectangle
  			bool over = this.ClientRectangle.Contains(new Point(e.X, e.Y));
  
  			// If entering the button area or leaving the button area...
  			if (over != m_mouseOver)
  			{
  				// Update state
  				m_mouseOver = over;
  
  				// Redraw to show button state
  				Invalidate();
  			}
  		}
  
  		/// <exclude/>
  		protected override void OnMouseEnter(EventArgs e)
  		{
  			// Update state to reflect mouse over the button area
  			if (!m_mouseOver)
  			{
  				m_mouseOver = true;
  
  				// Redraw to show button state
  				Invalidate();
  			}
  
  			base.OnMouseEnter(e);
  		}
  
  		/// <exclude/>
  		protected override void OnMouseLeave(EventArgs e)
  		{
  			// Update state to reflect mouse not over the button area
  			if (m_mouseOver)
  			{
  				m_mouseOver = false;
  
  				// Redraw to show button state
  				Invalidate();
  			}
  
  			base.OnMouseLeave(e);
  		}
  
  		/// <exclude/>
  		protected override void OnPaint(PaintEventArgs e)
  		{
  			base.OnPaint(e);
  			DrawBackground(e.Graphics);
  			DrawImage(e.Graphics);
  			DrawText(e.Graphics);
  			DrawBorder(e.Graphics);
  		}
  
  		private void DrawBackground(Graphics g)
  		{
  			using (SolidBrush brush = new SolidBrush(BackColor))
  			{
  				g.FillRectangle(brush, ClientRectangle);
  			}
  		}
  
  		private void DrawImage(Graphics g)
  		{
  			Image image = this.Enabled ? ImageEnabled : ((ImageDisabled != null) ? ImageDisabled : ImageEnabled);
  			ImageAttributes imageAttr = null;
  
  			if (null == image)
  				return;
  
  			if (m_monochrom)
  			{
  				imageAttr = new ImageAttributes();
  
  				// transform the monochrom image
  				// white -> BackColor
  				// black -> ForeColor
  				ColorMap[] colorMap = new ColorMap[2];
  				colorMap[0] = new ColorMap();
  				colorMap[0].OldColor = Color.White;
  				colorMap[0].NewColor = this.BackColor;
  				colorMap[1] = new ColorMap();
  				colorMap[1].OldColor = Color.Black;
  				colorMap[1].NewColor = this.ForeColor;
  				imageAttr.SetRemapTable(colorMap);
  			}
  
  			Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
  
  			if ((!Enabled) && (null == ImageDisabled))
  			{
  				using (Bitmap bitmapMono = new Bitmap(image, ClientRectangle.Size))
  				{
  					if (imageAttr != null)
  					{
  						using (Graphics gMono = Graphics.FromImage(bitmapMono))
  						{
  							gMono.DrawImage(image, new Point[3] { new Point(0, 0), new Point(image.Width - 1, 0), new Point(0, image.Height - 1) }, rect, GraphicsUnit.Pixel, imageAttr);
  						}
  					}
  					ControlPaint.DrawImageDisabled(g, bitmapMono, 0, 0, this.BackColor);
  				}
  			}
  			else
  			{
  				// Three points provided are upper-left, upper-right and 
  				// lower-left of the destination parallelogram. 
  				Point[] pts = new Point[3];
  				pts[0].X = (Enabled && m_mouseOver && m_mouseCapture) ? 1 : 0;
  				pts[0].Y = (Enabled && m_mouseOver && m_mouseCapture) ? 1 : 0;
  				pts[1].X = pts[0].X + ClientRectangle.Width;
  				pts[1].Y = pts[0].Y;
  				pts[2].X = pts[0].X;
  				pts[2].Y = pts[1].Y + ClientRectangle.Height;
  
  				if (imageAttr == null)
  					g.DrawImage(image, pts, rect, GraphicsUnit.Pixel);
  				else
  					g.DrawImage(image, pts, rect, GraphicsUnit.Pixel, imageAttr);
  			}
  		}	
  
  		private void DrawText(Graphics g)
  		{
  			if (Text == string.Empty)
  				return;
  
  			Rectangle rect = ClientRectangle;
  
  			rect.X += BorderWidth;
  			rect.Y += BorderWidth;
  			rect.Width -= 2 * BorderWidth;
  
gt: 			rect.Height -= 2 * BorderWidth;