Return to Snippet

Revision: 30088
at September 9, 2010 01:00 by jimfred


Updated Code
// ToggleButton
   // This class subclasses a CheckBox to combine the benefits of a Checkbox and 
   // Checkbox-with-Button-Appearance by combining a checkbox and button into one control.
   // 
   // Requirements: 
   // [1] Two states (like a checkbox).
   // [2] Visually imply action/control (like a button). 
   //     I think a Checkbox fails this requirement.
   // [3] It should be intuitively obvious what the state is and what the button will do when clicked.
   //     A checkbox meets the state requirement but fails the Action requirement because
   //     checkboxes are typically used for configuration rather than action.
   //     I think a Checkbox-with-button-appearance fails because it's not obvious if the button is depressed or not.
   //     I think a button-with-changing-text fails. Does the text show state or the on-click (oposite) action?
   //     Designers use button-with-changing-text inconsistently.
   // [4] Explicity show State even with poor dispplay visibility. 
   //     I think a Checkbox-with-button-appearance fails this requirement.
   // [5] Works on all resolutions and themes, doesn't look to 'flashy' and must 'fit-in'
   //     I think a 2-bitmapped button would fail this requirement.
   //     Many 3-rd party buttons fail this requirement.
   // 
   // This class uses DrawToBitmap to capture a temporary Checkbox's appearance.
   // It captures just the checkbox without the text.
   // I want to use a standard checkbox to be consistent with system-wide styles.
   //
   // Design usage:
   // [1] Add this class ToggleButton to project.
   // [2] Add 'normal' checkbox to WinForm
   // [3] Change it's class to this ToggleButton class (in both the declaration and instantiation).
   // [4] Set properties...
   //     Appearance = System.Windows.Forms.Appearance.Button;
   //     TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
   //
   // Room for improvement:
   //    Create a user control that's more portable (although it's easy to add a class to a project).
   public class ToggleButton : CheckBox
   {
      //constructor
      public ToggleButton() : base() 
      {
         this.SuspendLayout();
         
         if (bmChecked == null) // If the static bitmaps haven't been constructed, create them.
         {
            System.Windows.Forms.CheckBox chkTemp = new System.Windows.Forms.CheckBox();

            chkTemp.AutoSize = true;
            chkTemp.BackColor = System.Drawing.Color.Transparent;
            chkTemp.Location = new System.Drawing.Point(123, 128);
            chkTemp.Name = "chkSmall";
            chkTemp.Size = chkTemp.PreferredSize;
            chkTemp.TabIndex = 2;
            chkTemp.UseVisualStyleBackColor = false;

            bmChecked = new Bitmap(chkTemp.Width, chkTemp.Height);
            bmUnChecked = new Bitmap(chkTemp.Width, chkTemp.Height);
            bmDisabled = new Bitmap(chkTemp.Width, chkTemp.Height);

            // Set checkbox false and capture bitmap.
            chkTemp.Checked = false;
            chkTemp.DrawToBitmap(bmUnChecked, new Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

            // Set checkbox true and capture bitmap.
            chkTemp.Checked = true;
            chkTemp.DrawToBitmap(bmChecked, new Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

            // Set checkbox false/disabled and capture bitmap.
            chkTemp.Checked = false;
            chkTemp.Enabled = false;
            chkTemp.DrawToBitmap(bmDisabled, new Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

            chkTemp.Visible = false;

         }
         this.CheckedChanged += new System.EventHandler(this.btnToggleButton_Changed);
         this.EnabledChanged += new System.EventHandler(this.btnToggleButton_Changed);
         this.Image = this.Checked ? bmChecked : bmUnChecked;
         this.ResumeLayout(false);
         btnToggleButton_Changed(null, null);
      }


      private void btnToggleButton_Changed(object sender, EventArgs e)
      {
         Image = 
            !Enabled ? bmDisabled :
            Checked  ? bmChecked  : 
            bmUnChecked;
      }

      // Create 3 static bitmaps to swap-out when the button changes.
      // Static saves space (we don't need a copy for each instance of this class) but it seemed to break the design-time display.
      private static Bitmap bmChecked;
      private static Bitmap bmUnChecked;
      private static Bitmap bmDisabled;

   }

Revision: 30087
at August 9, 2010 08:33 by jimfred


Updated Code
public class ToggleButton2 : System.Windows.Forms.CheckBox
{
   // This class subclasses a CheckBox to combine the benefits of a Checkbox and 
   // Checkbox-with-Button-Appearance by combining a checkbox and button into one control.
   // 
   // Requirements: 
   // [1] Two states (like a checkbox).
   // [2] Visually imply action/control (like a button). 
   //     I think a Checkbox fails this requirement.
   // [3] It should be intuitively obvious what the state is and what the button will do when clicked.
   //     A checkbox meets the state requirement but fails the Action requirement because
   //     checkboxes are typically used for configuration rather than action.
   //     I think a Checkbox-with-button-appearance fails because it's not obvious if the button is depressed or not.
   //     I think a button-with-changing-text fails. Does the text show state or the on-click (oposite) action?
   //     Designers use button-with-changing-text inconsistently.
   // [4] Explicity show State even with poor dispplay visibility. 
   //     I think a Checkbox-with-button-appearance fails this requirement.
   // [5] Works on all resolutions and themes, doesn't look to 'flashy' and must 'fit-in'
   //     I think a 2-bitmapped button would fail this requirement.
   //     Many 3-rd party buttons fail this requirement.
   // 
   // This class uses DrawToBitmap to capture a temporary Checkbox's appearance.
   // It captures just the checkbox without the text.
   // I want to use a standard checkbox to be consistent with system-wide styles.
   //
   // Design usage:
   // [1] Add this class ToggleButton to project.
   // [2] Add 'normal' checkbox to WinForm
   // [3] Change it's class to this ToggleButton class (in both the declaration and instantiation).
   // [4] Set properties...
   //     Appearance = System.Windows.Forms.Appearance.Button;
   //     TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
   //
   // Room for improvement:
   //    Create a user control that's more portable (although it's easy to add a class to a project).


   //constructor
   public ToggleButton2()
      : base()
   {
      // imageList is static to save space.
      if (imageList == null)
      {
         System.Windows.Forms.CheckBox chkTemp = new System.Windows.Forms.CheckBox(); // Temporary checkbox with no text.

         chkTemp.AutoSize = true;
         chkTemp.BackColor = System.Drawing.Color.Transparent;
         chkTemp.Size = new System.Drawing.Size(16, 16);
         chkTemp.UseVisualStyleBackColor = false;

         imageList = new System.Windows.Forms.ImageList();
         imageList.TransparentColor = System.Drawing.Color.Transparent;

         System.Drawing.Bitmap[] bm = 
         {
            new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height),
            new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height)
         };

         // Set checkbox false and capture bitmap.
         chkTemp.Checked = false;
         chkTemp.DrawToBitmap(bm[0], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
         imageList.Images.Add(bm[0]);

         // Set checkbox true and capture bitmap.
         chkTemp.Checked = true;
         chkTemp.DrawToBitmap(bm[1], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
         imageList.Images.Add(bm[1]);
      }

      this.ImageList = imageList;
      this.CheckedChanged += new System.EventHandler(this.btnToggleButton_CheckedChanged);

      btnToggleButton_CheckedChanged(null,null);

   }

   // Prevents Image property from deleting the ImageList.
   new public Image Image { get { return null; } set { ; } }

   // Change this.Image
   private void btnToggleButton_CheckedChanged(object sender, System.EventArgs e)
   {
      this.ImageIndex = this.Checked ? 1 : 0;
   }

   static private ImageList imageList;
}

Revision: 30086
at August 9, 2010 08:05 by jimfred


Updated Code
public class ToggleButton2 : System.Windows.Forms.CheckBox
{
   // This class subclasses a CheckBox to combine the benefits of a Checkbox and 
   // Checkbox-with-Button-Appearance by combining a checkbox and button into one control.
   // 
   // Requirements: 
   // [1] Two states (like a checkbox).
   // [2] Visually imply action/control (like a button). 
   //     I think a Checkbox fails this requirement.
   // [3] It should be intuitively obvious what the state is and what the button will do when clicked.
   //     A checkbox meets the state requirement but fails the Action requirement because
   //     checkboxes are typically used for configuration rather than action.
   //     I think a Checkbox-with-button-appearance fails because it's not obvious if the button is depressed or not.
   //     I think a button-with-changing-text fails. Does the text show state or the on-click (oposite) action?
   //     Designers use button-with-changing-text inconsistently.
   // [4] Explicity show State even with poor dispplay visibility. 
   //     I think a Checkbox-with-button-appearance fails this requirement.
   // [5] Works on all resolutions and themes, doesn't look to 'flashy' and must 'fit-in'
   //     I think a 2-bitmapped button would fail this requirement.
   //     Many 3-rd party buttons fail this requirement.
   // 
   // This class uses DrawToBitmap to capture a temporary Checkbox's appearance.
   // It captures just the checkbox without the text.
   // I want to use a standard checkbox to be consistent with system-wide styles.
   //
   // Design usage:
   // [1] Add this class ToggleButton to project.
   // [2] Add 'normal' checkbox to WinForm
   // [3] Change it's class to this ToggleButton class (in both the declaration and instantiation).
   // [4] Set properties...
   //     Appearance = System.Windows.Forms.Appearance.Button;
   //     TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
   //
   // Room for improvement:
   //    Create a user control that's more portable (although it's easy to add a class to a project).


   //constructor
   public ToggleButton2()
      : base()
   {
      // imageList is static to save space.
      if (imageList == null)
      {
         System.Windows.Forms.CheckBox chkTemp = new System.Windows.Forms.CheckBox(); // Temporary checkbox with no text.

         chkTemp.AutoSize = true;
         chkTemp.BackColor = System.Drawing.Color.Transparent;
         chkTemp.Size = new System.Drawing.Size(15, 14);
         chkTemp.UseVisualStyleBackColor = false;

         imageList = new System.Windows.Forms.ImageList();
         imageList.TransparentColor = System.Drawing.Color.Transparent;

         System.Drawing.Bitmap[] bm = 
         {
            new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height),
            new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height)
         };

         // Set checkbox false and capture bitmap.
         chkTemp.Checked = false;
         chkTemp.DrawToBitmap(bm[0], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
         imageList.Images.Add(bm[0]);

         // Set checkbox true and capture bitmap.
         chkTemp.Checked = true;
         chkTemp.DrawToBitmap(bm[1], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
         imageList.Images.Add(bm[1]);
      }

      this.ImageList = imageList;
      this.CheckedChanged += new System.EventHandler(this.btnToggleButton_CheckedChanged);

      btnToggleButton_CheckedChanged(null,null);

   }

   // Prevents Image property from deleting the ImageList.
   new public Image Image { get { return null; } set { ; } }

   // Change this.Image
   private void btnToggleButton_CheckedChanged(object sender, System.EventArgs e)
   {
      this.ImageIndex = this.Checked ? 1 : 0;
   }

   static private ImageList imageList;
}

Revision: 30085
at August 9, 2010 06:54 by jimfred


Updated Code
public class ToggleButton2 : System.Windows.Forms.CheckBox
{
   // This class subclasses a CheckBox to combine the benefits of a Checkbox and 
   // Checkbox-with-Button-Appearance by combining a checkbox and button into one control.
   // 
   // Requirements: 
   // [1] Two states (like a checkbox).
   // [2] Visually imply action/control (like a button). 
   //     I think a Checkbox fails this requirement.
   // [3] It should be intuitively obvious what the state is and what the button will do when clicked.
   //     A checkbox meets the state requirement but fails the Action requirement because
   //     checkboxes are typically used for configuration rather than action.
   //     I think a Checkbox-with-button-appearance fails because it's not obvious if the button is depressed or not.
   //     I think a button-with-changing-text fails. Does the text show state or the on-click (oposite) action?
   //     Designers use button-with-changing-text inconsistently.
   // [4] Explicity show State even with poor dispplay visibility. 
   //     I think a Checkbox-with-button-appearance fails this requirement.
   // [5] Works on all resolutions and themes, doesn't look to 'flashy' and must 'fit-in'
   //     I think a 2-bitmapped button would fail this requirement.
   //     Many 3-rd party buttons fail this requirement.
   // 
   // This class uses DrawToBitmap to capture a temporary Checkbox's appearance.
   // It captures just the checkbox without the text.
   // I want to use a standard checkbox to be consistent with system-wide styles.
   //
   // Design usage:
   // [1] Add this class ToggleButton to project.
   // [2] Add 'normal' checkbox to WinForm
   // [3] Change it's class to this ToggleButton class (in both the declaration and instantiation).
   // [4] Set properties...
   //     Appearance = System.Windows.Forms.Appearance.Button;
   //     TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
   //
   // Room for improvement:
   //    Create a user control that's more portable (although it's easy to add a class to a project).
   //    Consider making the ImageList static merely to save space.


   //constructor
   public ToggleButton2()
      : base()
   {
      if (imageList == null)
      {
         System.Windows.Forms.CheckBox chkTemp = new System.Windows.Forms.CheckBox(); // Temporary checkbox with no text.

         chkTemp.AutoSize = true;
         chkTemp.BackColor = System.Drawing.Color.Transparent;
         chkTemp.Size = new System.Drawing.Size(15, 14);
         chkTemp.UseVisualStyleBackColor = false;

         imageList = new System.Windows.Forms.ImageList();
         imageList.TransparentColor = System.Drawing.Color.Transparent;

         System.Drawing.Bitmap[] bm = 
         {
            new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height),
            new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height)
         };

         // Set checkbox false and capture bitmap.
         chkTemp.Checked = false;
         chkTemp.DrawToBitmap(bm[0], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
         imageList.Images.Add(bm[0]);

         // Set checkbox true and capture bitmap.
         chkTemp.Checked = true;
         chkTemp.DrawToBitmap(bm[1], new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));
         imageList.Images.Add(bm[1]);
      }

      this.ImageList = imageList;
      this.CheckedChanged += new System.EventHandler(this.btnToggleButton_CheckedChanged);

      btnToggleButton_CheckedChanged(null,null);

   }

   // Prevents Image property from deleting the ImageList.
   new public Image Image { get { return null; } set { ; } }

   // Change this.Image
   private void btnToggleButton_CheckedChanged(object sender, System.EventArgs e)
   {
      this.ImageIndex = this.Checked ? 1 : 0;
   }

   static private ImageList imageList;
}

Revision: 30084
at August 7, 2010 10:05 by jimfred


Updated Code
public class ToggleButton : System.Windows.Forms.CheckBox
{
   // This class subclasses a CheckBox to combine the benefits of a Checkbox and 
   // Checkbox-with-Button-Appearance by combining a checkbox and button into one control.
   // 
   // Requirements: 
   // [1] Two states (like a checkbox).
   // [2] Visually imply action/control (like a button). 
   //     I think a Checkbox fails this requirement.
   // [3] It should be intuitively obvious what the state is and what the button will do when clicked.
   //     A checkbox meets the state requirement but fails the Action requirement because
   //     checkboxes are typically used for configuration rather than action.
   //     I think a Checkbox-with-button-appearance fails because it's not obvious if the button is depressed or not.
   //     I think a button-with-changing-text fails. Does the text show state or the on-click (oposite) action?
   //     Designers use button-with-changing-text inconsistently.
   // [4] Explicity show State even with poor dispplay visibility. 
   //     I think a Checkbox-with-button-appearance fails this requirement.
   // [5] Works on all resolutions and themes, doesn't look to 'flashy' and must 'fit-in'
   //     I think a 2-bitmapped button would fail this requirement.
   //     Many 3-rd party buttons fail this requirement.
   // 
   // This class uses DrawToBitmap to capture a temporary Checkbox's appearance.
   // It captures just the checkbox without the text.
   // I want to use a standard checkbox to be consistent with system-wide styles.
   //
   // Design usage:
   // [1] Add this class ToggleButton to project.
   // [2] Add 'normal' checkbox to WinForm
   // [3] Change it's class to this ToggleButton class (in both the declaration and instantiation).
   // [4] Set properties...
   //     Appearance = System.Windows.Forms.Appearance.Button;
   //     TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
   //
   // Room for improvement:
   //    There's probably a way to automatically change Image based on state. I don't know yet.
   //    Create a user control that's more portable (although it's easy to add a class to a project).
   //    Consider making the bitmaps static merely to save space.

   System.Drawing.Bitmap bmChecked;
   System.Drawing.Bitmap bmUnChecked;

   //constructor
   public ToggleButton() : base() 
   {
      
      System.Windows.Forms.CheckBox chkTemp = new System.Windows.Forms.CheckBox(); // Temporary checkbox with no text.

      chkTemp.AutoSize = true;
      chkTemp.BackColor = System.Drawing.Color.Transparent;
      chkTemp.Size = new System.Drawing.Size(15, 14);
      chkTemp.UseVisualStyleBackColor = false;

      bmChecked = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);
      bmUnChecked = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);

      // Set checkbox false and capture bitmap.
      chkTemp.Checked = false; 
      chkTemp.DrawToBitmap(bmUnChecked, new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

      // Set checkbox true and capture bitmap.
      chkTemp.Checked = true;
      chkTemp.DrawToBitmap(bmChecked, new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

      this.CheckedChanged += new System.EventHandler(this.btnToggleButton_CheckedChanged);

      this.Image = this.Checked ? bmChecked : bmUnChecked;

   }

   // Change the this.Image
   private void btnToggleButton_CheckedChanged(object sender, System.EventArgs e)
   {
      this.Image = this.Checked ? bmChecked : bmUnChecked;
   }

}

Revision: 30083
at August 7, 2010 05:43 by jimfred


Initial Code
public class ToggleButton : System.Windows.Forms.CheckBox
{
   // This class subclasses a CheckBox to combine the benefits of a Checkbox and Checkbox with Button Appearance by combining a checkbox and button into one control.
   // Requirements: 
   //    - Two states (like a checkbox).
   //    - Visually imply action/control (like a button)
   //    - Explicity show State (unlike a checkbox with button appearance).
   // The problem with a Button with changing text: People use this technique inconsistently - sometime the text shows status, sometime it shows the action to be taken
   // The problem with a simple Checkbox is that a checkbox implies config rather than action.
   // The problem with a simple Checkbox with a Button Appearance is that the state is not obvious
   // 
   // This uses DrawToBitmap to capture a temporary Checkbox's appearance to be consistent with system-wide styles.
   //
   // Design usage:
   // [1] Add this class ToggleButton to project.
   // [2] Add 'normal' checkbox to WinForm
   // [3] Change it's class to this ToggleButton.
   // [4] Set properties...
   //     Appearance = System.Windows.Forms.Appearance.Button;
   //     TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
   //
   // Room for improvement:
   // There's probably a way to automatically change Image based on state. I don't know yet.
   // Create a user control that's more portable (although it's easy to add a class to a project).
   // Consider making the bitmaps static merely to save space.

   System.Drawing.Bitmap bmChecked;
   System.Drawing.Bitmap bmUnChecked;

   //constructor
   public ToggleButton() : base() 
   {
      
      System.Windows.Forms.CheckBox chkTemp = new System.Windows.Forms.CheckBox(); // Temporary checkbox with no text.

      chkTemp.AutoSize = true;
      chkTemp.BackColor = System.Drawing.Color.Transparent;
      chkTemp.Size = new System.Drawing.Size(15, 14);
      chkTemp.UseVisualStyleBackColor = false;

      bmChecked = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);
      bmUnChecked = new System.Drawing.Bitmap(chkTemp.Width, chkTemp.Height);

      // Set checkbox false and capture bitmap.
      chkTemp.Checked = false; 
      chkTemp.DrawToBitmap(bmUnChecked, new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

      // Set checkbox true and capture bitmap.
      chkTemp.Checked = true;
      chkTemp.DrawToBitmap(bmChecked, new System.Drawing.Rectangle(0, 0, chkTemp.Width, chkTemp.Height));

      this.CheckedChanged += new System.EventHandler(this.btnToggleButton_CheckedChanged);

      this.Image = this.Checked ? bmChecked : bmUnChecked;

   }

   // Change the this.Image
   private void btnToggleButton_CheckedChanged(object sender, System.EventArgs e)
   {
      this.Image = this.Checked ? bmChecked : bmUnChecked;
   }

}

Initial URL


Initial Description
See comments in code.

Initial Title
C# WinForm, subclass a Checkbox control to create a better two-state button (Adds Checkbox within a Button)

Initial Tags


Initial Language
C#