Click here to Skip to main content
15,891,951 members
Articles / Desktop Programming / Win32

A Group of GroupBox

Rate me:
Please Sign up or sign in to vote.
4.77/5 (10 votes)
16 Dec 2010CPOL5 min read 55K   1.1K   28  
CheckGroupBox, RadioGroupBox, CollapsibleGroupBox controls
// Copyright (c) 2010 2011 2012 ����(also tr0217)
// mailto:tr0217@163.com
// The earliest release time: 2010-12-08
// Last modification time: 2010-12-16
// Accompanying files of necessity:
// 
//
//
// This file and the accompanying files of this project may be freely used provided the following
// conditions are met:
//        * This copyright statement is not removed or modified.
//        * The code is not sold in uncompiled form.  (Release as a compiled binary which is part
//          of an application is fine)
//        * The design, code, or compiled binaries are not "Re-branded".
//        
// Optional:
//        * Redistributions in binary form must reproduce the above copyright notice.
//        * I receive a fully licensed copy of the product (regardless of whether the product is
//          is free, shrinkwrap, or commercial).  This is optional, though if you release products
//          which use code I've contributed to, I would appreciate a fully licensed copy.
//
// In addition, you may not:
//        * Publicly release modified versions of the code or publicly release works derived from
//          the code without express written authorization.
//
// NO WARRANTY:
//        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;

namespace TR0217.ControlEx
{
    [ToolboxBitmap(typeof(RadioGroupBox), "RadioGroupBox.bmp")]
    public class RadioGroupBox : GroupBox
    {
        private bool _checked;
        private bool _autoCheck = true;
        private bool _autoEnabledState = true;
        private RadioButtonState _radioButtonState = RadioButtonState.UncheckedNormal;

       
        private const int _checkPaneWidth = 12;
        private bool _calc = true;
        private Rectangle _checkBoxRect = new Rectangle(9,0,_checkPaneWidth,_checkPaneWidth);
        private string _vText;



        /// <summary>
        /// Indicates whether the radio button is checked or when the other radio button has the same parent unchecked.
        /// </summary>
        [Description("Indicates whether the radio button is checked or when the other radio button has the same parent unchecked.")]
        [Category("Appearance")]
        [DefaultValue(true)]
        public bool AutoCheck
        {
            get { return _autoCheck; }
            set { _autoCheck = value; }
        }

        /// <summary>
        /// Indicates whether the radio button is checked or not.
        /// </summary>
        [Description("Indicates whether the radio button is checked or not.")]
        [Category("Appearance")]
        [DefaultValue(false)]
        public bool Checked
        {
            get
            {
                return _checked;
            }
            set
            {
                if (value != _checked)
                {
                    _checked = value;
                    if (CheckedChanged != null)
                        CheckedChanged(this, new EventArgs());

                    if(_checked)
                        this.PerformAutoUpdates();

                    if (_autoEnabledState)
                    {
                        foreach (Control control in this.Controls)
                        {
                            control.Enabled = _checked;
                        }
                    }
                    
                }
                _radioButtonState = _checked ? RadioButtonState.CheckedNormal : RadioButtonState.UncheckedNormal;
                this.Invalidate(_checkBoxRect);
            }
        }

        /// <summary>
        /// Determines if child controls of the GroupBox are disabled when unchecked, 
        /// and child controls of the GroupBox are enabled when checked 
        /// </summary>
        [Description("Determines if child controls of the GroupBox are disabled when unchecked,"
            + "and child controls of the GroupBox are enabled when checked")]
        [Category("Appearance")]
        [DefaultValue(true)]
        public bool AutoEnabledState
        {
            get { return _autoEnabledState; }
            set { _autoEnabledState = value; }
        }

        private void PerformAutoUpdates()
        {
            if (_autoCheck)
            {
                Control parentInternal = this.Parent;
                if (parentInternal != null)
                {
                    Control.ControlCollection controls = parentInternal.Controls;
                    for (int i = 0; i < controls.Count; i++)
                    {
                        Control control2 = controls[i];
                        if ((control2 != this))
                        {
                            if (control2 is RadioButton)
                            {
                                RadioButton component = (RadioButton)control2;
                                if (component.AutoCheck && component.Checked)
                                {
                                    component.Checked = false;
                                }
                            }
                            else if (control2 is RadioGroupBox)
                            {
                                RadioGroupBox component = (RadioGroupBox)control2;
                                if (component.AutoCheck && component.Checked)
                                {
                                    TypeDescriptor.GetProperties(this)["Checked"].SetValue(component, false);
                                }
                            }
                        }
                    }
                }
            }
        }

        private void ReleaseHandler(Control parent)
        {
            parent.ControlRemoved -= parent_ControlRemoved;
            parent.ControlAdded -= parent_ControlAdded;
            Control.ControlCollection controls = parent.Controls;
            for (int i = 0; i < controls.Count; i++)
            {
                Control control2 = controls[i];
                if ((control2 != this))
                {
                    if (control2 is RadioButton)
                    {
                        RadioButton radioButton = (RadioButton)control2;
                        radioButton.CheckedChanged -= radioButton_CheckedChanged;
                    }
//                    else if (control2 is RadioGroupBox)
//                    {
//                        RadioGroupBox radioGroupBox = (RadioGroupBox)control2;
//                        radioGroupBox.CheckedChanged -= radioGroupBox_CheckedChanged;
//                    }
                }
            }
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            Control parent = this.Parent;
            if (parent != null)
            {
                parent.ControlAdded += new ControlEventHandler(parent_ControlAdded);
                parent.ControlRemoved += new ControlEventHandler(parent_ControlRemoved);
                Control.ControlCollection controls = parent.Controls;
                for (int i = 0; i < controls.Count; i++)
                {
                    Control control2 = controls[i];
                    if ((control2 != this))
                    {
                        if (control2 is RadioButton)
                        {
                            RadioButton radioButton = (RadioButton)control2;
                            radioButton.CheckedChanged += new EventHandler(radioButton_CheckedChanged);
                        }
                        //else if (control2 is RadioGroupBox)
                        //{
                        //    RadioGroupBox radioGroupBox = (RadioGroupBox)control2;
                        //    radioGroupBox.CheckedChanged += new EventHandler(radioGroupBox_CheckedChanged);
                        //}
                    }
                }
            }
        }

        void parent_ControlRemoved(object sender, ControlEventArgs e)
        {
            Control parent = sender as Control;
            if (e.Control is RadioButton)
            {
                RadioButton radioButton = e.Control as RadioButton;
                radioButton.CheckedChanged -= radioButton_CheckedChanged;

            }
            else if (e.Control is RadioGroupBox)
            {
                if (e.Control == this)
                     this.ReleaseHandler(parent);
                //if (e.Control != this)
                //    radioGroupBox.CheckedChanged -= radioGroupBox_CheckedChanged;
                //else
                //    this.ReleaseHandler(parent);
            }
        }

        void parent_ControlAdded(object sender, ControlEventArgs e)
        {
            if (e.Control is RadioButton)
            {
                RadioButton radioButton = e.Control as RadioButton;
                radioButton.CheckedChanged += radioButton_CheckedChanged;
            }
            //else if (e.Control is RadioGroupBox)
            //{
            //    RadioGroupBox radioGroupBox = e.Control as RadioGroupBox;
            //    if(radioGroupBox != this)
            //        radioGroupBox.CheckedChanged += radioGroupBox_CheckedChanged;
            //}
        }

        void radioGroupBox_CheckedChanged(object sender, EventArgs e)
        {
            if(_autoCheck)
            {
                RadioGroupBox radioGroupBox = sender as RadioGroupBox;
                if (radioGroupBox.Checked)
                {
                    this.Checked = false;
                }
            }                
        }

        void radioButton_CheckedChanged(object sender, EventArgs e)
        {
            if (_autoCheck)
            {
                RadioButton radioButton = sender as RadioButton;
                if (radioButton.Checked)
                {
                    this.Checked = false;
                }
            } 
        }

        /// <summary>
        /// Occurs whenever the Checked property of the CheckBox is changed.
        /// </summary>
        [Description("Occurs whenever the Checked property of the CheckBox is changed.")]
        public event EventHandler CheckedChanged;

        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            if (_autoEnabledState)
            {
                e.Control.Enabled = _checked;
            }
        }

        protected override void OnTextChanged(EventArgs e)
        {
            base.OnTextChanged(e);
            _calc = true;
        }

        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);
            _checkBoxRect.Height = (base.Font.Height - 5) | 1;
            _calc = true;
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (_checkBoxRect.Contains(e.Location))
                this.Checked = true;
            else
                base.OnMouseUp(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (_checkBoxRect.Contains(e.Location))
            {
                _radioButtonState = _checked ? RadioButtonState.CheckedPressed : RadioButtonState.UncheckedPressed;
                this.Invalidate(_checkBoxRect);
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            _radioButtonState = _checked ? RadioButtonState.CheckedNormal : RadioButtonState.UncheckedNormal;
            this.Invalidate(_checkBoxRect);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if ((base.Width > 10) && (base.Height > 10))
            {
                GroupBoxState state = base.Enabled ? GroupBoxState.Normal : GroupBoxState.Disabled;
                Color textColor = base.Enabled ? this.ForeColor : ControlPaint.Dark(this.BackColor);
                TextFormatFlags flags = TextFormatFlags.PreserveGraphicsTranslateTransform | TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.TextBoxControl | TextFormatFlags.WordBreak;
                if (!this.ShowKeyboardCues)
                {
                    flags |= TextFormatFlags.HidePrefix;
                }
                if (this.RightToLeft == RightToLeft.Yes)
                {
                    flags |= TextFormatFlags.RightToLeft | TextFormatFlags.Right;
                }

                if (_calc)
                {
                    string t = " 01%^GJWIabdfgjkwi,:\"'`~-_}]?.>\\";
                    int letterWidth = (int)e.Graphics.MeasureString(t, this.Font).Width / 32;
                    int w = (_checkPaneWidth + letterWidth) / letterWidth;
                    string text = new string(' ', w);
                    if (!string.IsNullOrEmpty(base.Text))
                    {
                        _vText = text + base.Text;
                        _checkBoxRect.Width = _checkPaneWidth + base.Text.Length * letterWidth;
                    }
                    _calc = false;
                }

                GroupBoxRenderer.DrawGroupBox(e.Graphics, new Rectangle(0, 0, base.Width, base.Height), _vText, this.Font, flags, state);
                int chkOffset = (_checkBoxRect.Height - _checkPaneWidth) / 2;
                chkOffset = chkOffset < 0 ? 0 : chkOffset;
                RadioButtonRenderer.DrawRadioButton(e.Graphics, new Point(_checkBoxRect.X, chkOffset), _radioButtonState);
            }
            else
            {
                base.OnPaint(e);
            }
        }
    }
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions