context: //Copyright (c) 2008, wyDay
  //All rights reserved.
  
  //Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  
  //    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  //    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  
  //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
  using System;
  using System.ComponentModel;
  using System.Drawing;
  using System.Windows.Forms;
  using System.Windows.Forms.VisualStyles;
  
  
  //Get the latest version of SplitButton at: http://wyday.com/splitbutton/
  
  
  namespace wyDay.Controls
  {
      public class SplitButton : Button
      {
          private PushButtonState _state;
  
          private const int SplitSectionWidth = 18;
  
          private static int BorderSize = SystemInformation.Border3DSize.Width * 2;
          private bool skipNextOpen = false;
          private Rectangle dropDownRectangle = new Rectangle();
          private bool showSplit = false;
  
          private bool isSplitMenuVisible = false;
  
  
          private ContextMenuStrip m_SplitMenuStrip = null;
          private ContextMenu m_SplitMenu = null;
  
          TextFormatFlags textFormatFlags = TextFormatFlags.Default;
  
          public SplitButton()
          {
              this.AutoSize = true;
          }
  
          #region Properties
  
          [Browsable(false)]
          public override ContextMenuStrip ContextMenuStrip
          {
              get
              {
                  return m_SplitMenuStrip;
              }
              set
              {
                  m_SplitMenuStrip = value;
              }
          }
  
          [DefaultValue(null)]
          public ContextMenu SplitMenu
          {
              get { return m_SplitMenu; }
              set
              {
                  //remove the event handlers for the old SplitMenu
                  if (m_SplitMenu != null)
                  {
                      m_SplitMenu.Popup -= new EventHandler(SplitMenu_Popup);
                  }
  
                  //add the event handlers for the new SplitMenu
                  if (value != null)
                  {
                      ShowSplit = true;
                      value.Popup += new EventHandler(SplitMenu_Popup);
                  }
                  else
                      ShowSplit = false;
  
                  m_SplitMenu = value;
              }
          }
  
          [DefaultValue(null)]
          public ContextMenuStrip SplitMenuStrip
          {
              get
              {
                  return m_SplitMenuStrip;
              }
              set
              {
                  //remove the event handlers for the old SplitMenuStrip
                  if (m_SplitMenuStrip != null)
                  {
                      m_SplitMenuStrip.Closing -= new ToolStripDropDownClosingEventHandler(SplitMenuStrip_Closing);
                      m_SplitMenuStrip.Opening -= new CancelEventHandler(SplitMenuStrip_Opening);
                  }
  
                  //add the event handlers for the new SplitMenuStrip
                  if (value != null)
                  {
                      ShowSplit = true;
                      value.Closing += new ToolStripDropDownClosingEventHandler(SplitMenuStrip_Closing);
                      value.Opening += new CancelEventHandler(SplitMenuStrip_Opening);
                  }
                  else
                      ShowSplit = false;
  
  
                  m_SplitMenuStrip = value;
              }
          }
  
          [DefaultValue(false)]
          public bool ShowSplit
          {
              set
              {
                  if (value != showSplit)
                  {
                      showSplit = value;
                      Invalidate();
                      if (this.Parent != null)
                      {
                          this.Parent.PerformLayout();
                      }
                  }
              }
          }
  
          private PushButtonState State
          {
              get
              {
                  return _state;
              }
              set
              {
                  if (!_state.Equals(value))
                  {
                      _state = value;
                      Invalidate();
                  }
              }
          }
  
          #endregion Properties
  
          protected override bool IsInputKey(Keys keyData)
          {
              if (keyData.Equals(Keys.Down) && showSplit)
              {
                  return true;
              }
  
              else
              {
                  return base.IsInputKey(keyData);
              }
          }
  
          protected override void OnGotFocus(EventArgs e)
          {
              if (!showSplit)
              {
                  base.OnGotFocus(e);
                  return;
              }
  
              if (!State.Equals(PushButtonState.Pressed) && !State.Equals(PushButtonState.Disabled))
              {
                  State = PushButtonState.Default;
              }
          }
  
          protected override void OnKeyDown(KeyEventArgs kevent)
          {
              if (showSplit)
              {
                  if (kevent.KeyCode.Equals(Keys.Down) && !isSplitMenuVisible)
                  {
                      ShowContextMenuStrip();
                  }
  
                  else if (kevent.KeyCode.Equals(Keys.Space) && kevent.Modifiers == Keys.None)
                  {
                      State = PushButtonState.Pressed;
                  }
              }
  
              base.OnKeyDown(kevent);
          }
  
          protected override void OnKeyUp(KeyEventArgs kevent)
          {
              if (kevent.KeyCode.Equals(Keys.Space))
              {
                  if (Control.MouseButtons == MouseButtons.None)
                  {
                      State = PushButtonState.Normal;
                  }
              }
              else if (kevent.KeyCode.Equals(Keys.Apps))
              {
                  if (Control.MouseButtons == MouseButtons.None && !isSplitMenuVisible)
                  {
                      ShowContextMenuStrip();
                  }
              }
  
              base.OnKeyUp(kevent);
          }
  
          protected override void OnEnabledChanged(EventArgs e)
          {
              if (Enabled)
                  State = PushButtonState.Normal;
              else
                  State = PushButtonState.Disabled;
  
              base.OnEnabledChanged(e);
          }
  
          protected override void OnLostFocus(EventArgs e)
          {
              if (!showSplit)
              {
                  base.OnLostFocus(e);
                  return;
              }
  
              if (!State.Equals(PushButtonState.Pressed) && !State.Equals(PushButtonState.Disabled))
              {
                  State = PushButtonState.Normal;
              }
          }
  
          bool isMouseEntered = false;
  
          protected override void OnMouseEnter(EventArgs e)
          {
              if (!showSplit)
              {
                  base.OnMouseEnter(e);
                  return;
              }
  
              isMouseEntered = true;
  
              if (!State.Equals(PushButtonState.Pressed) && !State.Equals(PushButtonState.Disabled))
              {
                  State = PushButtonState.Hot;
              }
                 
          }
  
          protected override void OnMouseLeave(EventArgs e)
          {
              if (!showSplit)
              {
                  base.OnMouseLeave(e);
                  return;
              }
  
              isMouseEntered = false;
  
              if (!State.Equals(PushButtonState.Pressed) && !State.Equals(PushButtonState.Disabled))
              {
                  if (Focused)
                  {
                      State = PushButtonState.Default;
                  }
  
                  else
                  {
                      State = PushButtonState.Normal;
                  }
              }
          }
  
          protected override void OnMouseDown(MouseEventArgs e)
          {
              if (!showSplit)
              {
                  base.OnMouseDown(e);
                  return;
              }
  
              //handle ContextMenu re-clicking the drop-down region to close the menu
              if (m_SplitMenu != null && e.Button == MouseButtons.Left && !isMouseEntered)
                  skipNextOpen = true;
  
              if (dropDownRectangle.Contains(e.Location) && !isSplitMenuVisible && e.Button == MouseButtons.Left)
              {
                  ShowContextMenuStrip();
              }
              else
              {
                  State = PushButtonState.Pressed;
              }
          }
  
          protected override void OnMouseUp(MouseEventArgs mevent)
          {
              if (!showSplit)
              {
                  base.OnMouseUp(mevent);
                  return;
              }
  
              // if the right button was released inside the button
              if (mevent.Button == MouseButtons.Right && ClientRectangle.Contains(mevent.Location) && !isSplitMenuVisible)
              {
                  ShowContextMenuStrip();
              }
              else if (m_SplitMenuStrip == null && m_SplitMenu == null || !isSplitMenuVisible)
              {
                  SetButtonDrawState();
  
                  if (ClientRectangle.Contains(mevent.Location) && !dropDownRectangle.Contains(mevent.Location))
                  {
                      OnClick(new EventArgs());
                  }
              }
          }
  
          protected override void OnPaint(PaintEventArgs pevent)
          {
              base.OnPaint(pevent);
  
              if (!showSplit)
                  return;
  
              Graphics g = pevent.Graphics;
              Rectangle bounds = this.ClientRectangle;
  
              // draw the button background as according to the current state.
              if (State != PushButtonState.Pressed && IsDefault && !Application.RenderWithVisualStyles)
              {
                  Rectangle backgroundBounds = bounds;
                  backgroundBounds.Inflate(-1, -1);
                  ButtonRenderer.DrawButton(g, backgroundBounds, State);
  
                  // button renderer doesnt draw the black frame when themes are off
                  g.DrawRectangle(SystemPens.WindowFrame, 0, 0, bounds.Width - 1, bounds.Height - 1);
              }
              else
              {
                  ButtonRenderer.DrawButton(g, bounds, State);
              }
  
              // calculate the current dropdown rectangle.
              dropDownRectangle = new Rectangle(bounds.Right - SplitSectionWidth, 0, SplitSectionWidth, bounds.Height);
  
              int internalBorder = BorderSize;
              Rectangle focusRect =
                  new Rectangle(internalBorder - 1,
                                internalBorder - 1,
                                bounds.Width - dropDownRectangle.Width - internalBorder,
                                bounds.Height - (internalBorder * 2) + 2);
  
              bool drawSplitLine = (State == PushButtonState.Hot || State == PushButtonState.Pressed || !Application.RenderWithVisualStyles);
  
  
              if (RightToLeft == RightToLeft.Yes)
              {
  
gt:                 dropDownRectangle.X = bounds.Left + 1;