I was trying this sample found in the website: Custom Checkbox
when I add the CustomCheckbox from the toolbox to the form directly and build the project it take lot of time to be build and cause the visual studio to not respond.

Do anybody have an idea about the causes??
thanks

Recommended Answers

All 20 Replies

did you use the fix in the post you mentioned?

Here's an alternative. Use a series of labels, with autosize off, and border fixed single. Set the text to "0". Have them all in a row with the borders touching. You can have as many or as few as you want.

In the Form code right after Initialize Components(); put this:

        foreach (Label l in this.Controls.OfType<Label>())
        {
            l.Click +=new EventHandler(Label_Click);
        }

If you have other labels, name these in a unique way. Maybe "Bit0", "Bit1", etc., then use a conditional statement, If(l.Text.Contains("Bit")

Add this after the form() code:

    private void Label_Click(object sender, EventArgs e)
    {
        Label l = (Label) sender;
        int Bit = int.Parse(l.Text);
        Bit =Convert.ToInt16(!(Convert.ToBoolean(Bit)));
        l.Text = Bit.ToString();
    }

When you run your form, they all start with "0"and everytime you click one it'll toggle between a "1" and a "0".

The main point is that I want to make a custom checkbox of my design.
I tried to make a new project and new class called CustomCheckBox which inherit from the default checkbox. It will add the CustomCheckBox and pointer in the toolbox under the solution name tab components.
I overrided the OnPaint() with this code:

class CustomCheckBox : CheckBox
    //class derived from the CheckBox class
    {
        public CustomCheckBox() { }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent);   //needed
            base.FlatStyle = FlatStyle.Flat; //needed
            if (this.Checked)
                G.DrawImageUnscaled(Properties.Resources.Checked,0,0);
            else
                G.DrawImageUnscaled(Properties.Resources.Unchecked, 0, 0);
        }
    }

I even tried to add a new user control which inherit from checkbox also. The 2 ways whic I tried will work normally if I add the checkbox on the runtime:

private void button1_Click(object sender, EventArgs e)
        {
            CustomCheckBox cb = new CustomCheckBox();
            cb.Text = "Check";
            cb.Size = new Size(100,20);
            cb.Location=new System.Drawing.Point(5,5);
            //panel1.Controls.Add(cb);
            this.Controls.Add(cb);
        }

If use the event Paint in the Default checkbox with this code it will work normally but I should edit each paint event of the checkboxes in the form:

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void checkBox1_Paint(object sender, PaintEventArgs e)
        {
            if (checkBox1.Checked)
                e.Graphics.DrawImageUnscaled(Properties.Resources.CheckedBox, 0, 1);
            else
                e.Graphics.DrawImageUnscaled(Properties.Resources.UnCheckedBox, 0, 1);
        }
    }

My main goal is to add the CustomCheckBox from the tool box and be able to build and run the project normally.
I think this will clarify all points in the problem.
Thanks for your help @tinstaafl

When I use the original code from the other post, and apply the fix mentioned later in post(as I mentioned in my earlier post), everything seems to run fine.

These are the steps I used:

Started a new project as User Control Library.
Added the code as if I was adding it in runtime to a form. Basically I copied/pasted from the other post.
Once I built it, I added the binarycheckbox from the .dll in the bin/debug folder, to the toolbox.

The form I used ran fine, no unusual delays.
The control acts like a checkbox but toggles between '0' and '1'. The numbers are black on a yellow background. Are you changing this?

Here's the total code I used:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsControlLibrary1
{
    public partial class BinaryCheckBox : UserControl
    {
        public BinaryCheckBox()
        {
            InitializeComponent();
           BinarycheckBox BinCB = new BinarycheckBox();
           BinCB.AutoSize = true;
           BinCB.Name = "bin";
           BinCB.Size = new System.Drawing.Size(25, 17);
           BinCB.TabIndex = 0;
           BinCB.Text = "bla bla";
           BinCB.UseVisualStyleBackColor = true;
            this.Controls.Add(BinCB); 
        }
        class BinarycheckBox : CheckBox
        //class derived from the CheckBox class
        {
            //init vars for OnPaint
            private Font font = new Font("Ariel", 8);
            private static Brush bluebrush = new SolidBrush(Color.Blue);
            private Brush backgroundbrush = new SolidBrush(Color.Yellow);
            Pen bluepen = new Pen(bluebrush);
            private StringFormat strFormat = new StringFormat();
            //default constructor
            public BinarycheckBox()
            {
                base.FlatStyle = FlatStyle.Flat; //needed
            }
            [System.ComponentModel.DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
            public new System.Windows.Forms.FlatStyle FlatStyle
            {
                get { return base.FlatStyle; }
                set { }
            }
            //we only need to override the OnPaint method
            //we do our own painting here
            protected override void OnPaint(PaintEventArgs pevent)
            {

                base.OnPaint(pevent); //needed
                Graphics G = pevent.Graphics;
                strFormat.Alignment = StringAlignment.Center;
                strFormat.LineAlignment = StringAlignment.Center;
                RectangleF R = new RectangleF(G.ClipBounds.X, G.ClipBounds.Y, 16F, 16F);
                G.FillRectangle(backgroundbrush, R);
                if (this.Checked)
                    G.DrawString("1", font, bluebrush, R, strFormat);
                else
                    G.DrawString("0", font, bluebrush, R, strFormat);
                G.DrawRectangle(bluepen, R.X, R.Y, R.Width - 1, R.Height - 1);
            }
        }
    }
}

thanks now it worked but I want to change the checkbox pic which is a png picture that is transperant.
there is a small checkbox that is the default is shown in the background because the new checkbox pic contain transperant layers?
I used this code on the onPaint()

protected override void OnPaint(PaintEventArgs pevent)
        {
            base.OnPaint(pevent); //needed
            Graphics G = pevent.Graphics;
            if (this.Checked)
                G.DrawImageUnscaled(Properties.Resources.CheckedBox, 0, 4);
            else
                G.DrawImageUnscaled(Properties.Resources.UnCheckedBox, 0, 4);
        }

how can I hide the default checkbox pic? I used the big size of the new checkbox to show how it is being seen.

this is how it appears:
http://postimage.org/image/4kb2cveed/

try something like this:

protected override void OnPaint(PaintEventArgs pevent)
{
    base.OnPaint(pevent); //needed
    Graphics G = pevent.Graphics;
    RectangleF R = new RectangleF(G.ClipBounds.X, G.ClipBounds.Y, 16F, 16F);
    G.FillRectangle(backgroundbrush, R);
    if (this.Checked)
        G.DrawImageUnscaled(Properties.Resources.CheckedBox, (Int32)(G.ClipBounds.X), (Int32)(G.ClipBounds.Y));
    else
        G.DrawImageUnscaled(Properties.Resources.UnCheckedBox, (Int32)(G.ClipBounds.X), (Int32)(G.ClipBounds.Y));
    G.DrawRectangle(bluepen, R.X, R.Y, R.Width - 1, R.Height - 1);

}

this code gave this result

http://postimage.org/image/93aptbntr/

I want to hide any checkbox in the background(the yellow one and the default one shown in the 1st image link) and show only the image of mine because it is transperant layer.

I found somthing that can help if I accessed the default check box that is shown.

Brush brush = new SolidBrush(Color.FromArgb(alpha, red, green, blue))

where alpha is the opcacity of the colors bounded. it can be from 0 to 255.

Thanks a lot!!

You could try omitting lines 6 and 11, and see if that helps.

Your main problem is that the checkbox is not very amenable to using an image to indicate the checked state. You are trying to paint over the box and that is always going to look strange.

Here is a custom control that I hammered out quickly based on a Button. It left aligns the button image and uses the ImageList property to contain a Checked and UnChecked Image. There are three added properties: CheckedImage, UnCheckedImage and ImageSize that control the images. If you don't like the looks, you can easy overide the style properties.

The code style my seem a bit strange as I originally did it in VB and converted to C#.

public class ImageCheckBox : Button
{
    private Image _CheckedImage = new Bitmap(24, 24);
    private Image _UnCheckedImage = new Bitmap(24, 24);
    public ImageCheckBox()
    {
        _Checked = false;
        this.ImageAlign = ContentAlignment.MiddleLeft;
        base.ImageList = new ImageList();
        this.FlatAppearance.BorderSize = 0;
        this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        Checked = false;
    }

    private void SetImages()
    {
        base.ImageList.Images.Clear();
        base.ImageList.Images.Add(_UnCheckedImage);
        base.ImageList.Images.Add(_CheckedImage);
        Invalidate();
    }

    private bool _Checked;
    public bool Checked
    {
        get { return _Checked; }
        set
        {
            _Checked = value;
            if (_Checked)
            {
                ImageIndex = 1;
            }
            else
            {
                ImageIndex = 0;
            }
        }
    }

    private Size _ImageSize = new Size(24,24);
    public Size ImageSize
    {
        get { return _ImageSize; }
        set
        {
            _ImageSize = value;
            this.ImageList.ImageSize = value;
            SetImages();
        }
    }

    public Image CheckedImage
    {
        get { return _CheckedImage; }
        set
        {
            _CheckedImage.Dispose();
            _CheckedImage = value;
            SetImages();
        }
    }


    public Image UnCheckedImage
    {
        get { return _UnCheckedImage; }
        set
        {
            _UnCheckedImage.Dispose();
            _UnCheckedImage = value;
            SetImages();
        }
    }

    protected override void OnClick(System.EventArgs e)
    {
        this.Checked = !this.Checked;
    }

}

@tinstaafl: it re-give the same default checkbox in the first link posted. There must be a way to access the default image with the check box and replace or hide it.

@TnTinMN: after working on your code to make it work another problem is noticed. you can't make a transparent button on the MouseEnter event :( :S.
so it will be noticed as a button and not as a checkbox
I can provide you with pictures it you want

@TnTinMN: after working on your code to make it work another problem is noticed. you can't make a transparent button on the MouseEnter event :( :S.
so it will be noticed as a button and not as a checkbox
I can provide you with pictures it you want

Just override the OnMouseEnter method and do not call the base OnMouseEnter method.

    protected override void OnMouseEnter(EventArgs e)
    {
        //base.OnMouseEnter(e);
    }

I used to override the the OnMouseDown also to prevent showing it as a button but the picture didn't appeared well(Image). I think I should stop using a transparent image and use a normal one.

Thanks very much for you guys.

When you override OnMouseDown and do not call the base method, you prevent the OnClick method from being called. Therefore, move the code (this.Checked = !this.Checked;) from OnClick to OnMouseDown.

    protected override void OnMouseDown(MouseEventArgs mevent)
    {
        //base.OnMouseDown(mevent);
        this.Checked = !this.Checked;
    }

I know and did it. It is changing in state from checked to unchecked, but the image is not showing well; it contains white colors and don't know why.

Here's a very simple,custom control that uses labels. All you need is 2 images, sized appropriately, in Resources of your Control Library project, named 'Check' and 'Uncheck'(you can change the code to any name you want). You've got 2 properties 'Text' and 'Checked', and a 'Click' event to signal when the checkbox changes. The code is very simple, and easy to use, just build it and add the .dll as a control to your toolbox. Since there are no extra features, there's nothing to override or change to see the image.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsControlLibrary1
{

    public partial class MyCheckBox : UserControl
    {
        Image Check = Properties.Resources.Check;
        Image UnCheck = Properties.Resources.UnCheck;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;        
        public MyCheckBox()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // label1
            // 
            this.label1.BackColor = System.Drawing.SystemColors.ControlText;
            this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.label1.Location = new System.Drawing.Point(3, 2);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(30, 25);
            this.label1.TabIndex = 0;
            this.label1.Click += new System.EventHandler(this.label1_Click);
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(39, 2);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(70, 13);
            this.label2.TabIndex = 1;
            this.label2.Text = this.Name;
            // 
            // MyCheckBox
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.AutoSize = true;
            this.AutoValidate = System.Windows.Forms.AutoValidate.Disable;
            this.BackColor = System.Drawing.SystemColors.Control;
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Name = "MyCheckBox";
            this.Size = new System.Drawing.Size(118, 32);
            this.ResumeLayout(false);
            this.PerformLayout();            
        }
        public new string Text 
        {
            get
            {
                return label2.Text;
            }
            set
            {
                label2.Text = value;
            }
        }
        public bool Checked
        {
            get
            {
                return (label1.Image == Check);
            }
            set
            {
                if (value == true)
                {                    
                    label1.Image = Check;
                }
                else
                {                        
                    label1.Image = UnCheck;
                }    
            }
        }
        private void label1_Click(object sender, EventArgs e)
        {
            Checked = !Checked;
            this.InvokeOnClick(this, null);            
        }
    }
}

I changed the this.label1.BackColor = System.Drawing.SystemColors.ControlText; to this.label1.BackColor = System.Drawing.Color.Transparent; and it worked fine but I am not seeing the Text property in the properties of the usercontrol below the solution explorer. and it should contain modifications for the size; i am trying to change the size to became the best.

Does because the user control doesn't have such a property so it won't appear in the properties since the events differ from that of a normal checkbox. Is there a way to add it there so I can change the text of this control directly?

Is there a way to add it there so I can change the text of this control directly?

I made the appropriate changes. The Text property shows up in the Properties Window now.

i am trying to change the size to became the best.

Sorry I Took all the designer code out of the designer, so you could see what all was done. I added a modification so that the chekcbox and the control resize according to the image and/or the text you use. Here is the modified code.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsControlLibrary1
{

    public partial class MyCheckBox : UserControl
    {
        Image Check = Properties.Resources.Check;
        Image UnCheck = Properties.Resources.UnCheck;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Label label2;        
        public MyCheckBox()
        {
            this.label1 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            this.Name = "MyCheckBox";
            // 
            // label1
            // 
            this.label1.BackColor = System.Drawing.SystemColors.ControlText;
            this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
            this.label1.Location = new System.Drawing.Point(3, 2);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(0, 0);
            this.label1.TabIndex = 0;
            this.label1.Click += new System.EventHandler(this.label1_Click);
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(39, 2);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(70, 13);
            this.label2.TabIndex = 1;
            this.label2.Text = this.Name;
            // 
            // MyCheckBox
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.AutoSize = true;
            this.AutoValidate = System.Windows.Forms.AutoValidate.Disable;
            this.BackColor = System.Drawing.SystemColors.Control;
            this.Controls.Add(this.label2);
            this.Controls.Add(this.label1);
            this.Size = new System.Drawing.Size(0, 0);
            this.ResumeLayout(false);
            this.PerformLayout();            
        }
        [Browsable(true)]
        [EditorBrowsable(EditorBrowsableState.Always)]        
        public new string Text 
        {
            get
            {
                return label2.Text;
            }
            set
            {
                label2.Text = value;
            }
        }
        public bool Checked
        {
            get
            {
                return (label1.Image == Check);
            }
            set
            {
                if (value == true)
                {                    
                    label1.Image = Check;
                    label1.Size = Check.Size;
                    this.Size = new Size(label1.Width + label2.Width, label1.Height);
                }
                else
                {                    
                    label1.Image = UnCheck;
                    label1.Size = UnCheck.Size;
                    this.Size = new Size(label1.Width + label2.Width, label1.Height);
                }
            }
        }
        private void label1_Click(object sender, EventArgs e)
        {            
            Checked = !Checked;
            this.InvokeOnClick(this, null);            
        }
    }
}

nice job my friend there is still a small bug and it will be a very usefull class that can be used instead of hiding the default check box that microsoft should review.

The bug is that when I click on the checkbox its position will change upward by 2 pixels approximately instead of staying at the same position. I tried to solve it by myself but I failed.

It's resizing to accomodate your images. Make sure they're both the exact same size, Paint can do it.

Or you can use this modification, which will resize the control and the checkbox according to the larger dimension between the 2 images.

    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Windows.Forms;

    namespace WindowsFormsControlLibrary1
    {

        public partial class MyCheckBox : UserControl
        {
            Image Check = Properties.Resources.Check;
            Image UnCheck = Properties.Resources.UnCheck;
            private System.Windows.Forms.Label label1;
            private System.Windows.Forms.Label label2;        
            public MyCheckBox()
            {
                this.label1 = new System.Windows.Forms.Label();
                this.label2 = new System.Windows.Forms.Label();
                this.SuspendLayout();
                this.Name = "MyCheckBox";
                // 
                // label1
                // 
                this.label1.BackColor = System.Drawing.SystemColors.ControlText;
                this.label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                this.label1.Location = new System.Drawing.Point(3, 2);
                this.label1.Name = "label1";
                this.label1.Size = new System.Drawing.Size(0, 0);
                this.label1.TabIndex = 0;
                this.label1.Click += new System.EventHandler(this.label1_Click);
                // 
                // label2
                // 
                this.label2.AutoSize = true;
                this.label2.Location = new System.Drawing.Point(39, 2);
                this.label2.Name = "label2";
                this.label2.Size = new System.Drawing.Size(70, 13);
                this.label2.TabIndex = 1;
                this.label2.Text = this.Name;
                // 
                // MyCheckBox
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.AutoSize = true;
                this.AutoValidate = System.Windows.Forms.AutoValidate.Disable;
                this.BackColor = System.Drawing.SystemColors.Control;
                this.Controls.Add(this.label2);
                this.Controls.Add(this.label1);
                this.Size = new System.Drawing.Size(0, 0);
                this.ResumeLayout(false);
                this.PerformLayout();
                int DefaultHeight, DefaultWidth;
                if (Check.Width > UnCheck.Width)
                    DefaultWidth = Check.Width;
                else
                    DefaultWidth = UnCheck.Width;
                if (Check.Height > UnCheck.Height)
                    DefaultHeight = Check.Height;
                else
                    DefaultHeight = UnCheck.Height;
                this.label1.Size= new System.Drawing.Size(DefaultWidth, DefaultHeight);
                this.Size = new System.Drawing.Size(label1.Width + label2.Width, label1.Height);
            }
            [Browsable(true)]
            [EditorBrowsable(EditorBrowsableState.Always)]        
            public new string Text 
            {
                get
                {
                    return label2.Text;
                }
                set
                {
                    label2.Text = value;
                }
            }
            public bool Checked
            {
                get
                {
                    return (label1.Image == Check);
                }
                set
                {
                    if (value == true)
                    {                    
                        label1.Image = Check;
                    }
                    else
                    {                    
                        label1.Image = UnCheck;
                    }
                }
            }
            private void label1_Click(object sender, EventArgs e)
            {            
                Checked = !Checked;
                this.InvokeOnClick(this, null);            
            }
        }
    }

perfect!!
I added a click event handler on the label2 also to be toggle the check when you press on the text also so it will act as the default checkbox does
Thanks a lot my friends for your help.

I like this site more than other websites that prevent you from asking after some easy questions :@

How can I be an effective user in this site?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.