locked
Change Display Properties of Disabled Control RRS feed

  • Question

  • Hi
    I have several ComboBoxes on my forms. They are instances of a custom control inheriting from the ComboBox control.
    When the ComboBox is disabled, it displays the selected text in a gray color. However, the color is very light and barely visible. I do not want to change the backcolor of my form, for this, to create a contrast. Instead I want to be able to override the OnPaint method and handle the formatting there. But surprisingly, the OnPaint method is not being called.
    Can anyone tell me what can be done here?

    Thanks in advance
    Vikas
    Tuesday, April 7, 2009 5:44 PM

Answers

  • ComboBox is a native Windows control.  It does it's own painting and doesn't support owner-draw.  You can force OnPaint to run with SetStyle(ControlStyles.UserPaint, true) in the constructor but you're going to be quite disappointed with the result.
    Hans Passant.
    • Marked as answer by Kira Qian Tuesday, April 14, 2009 6:51 AM
    Tuesday, April 7, 2009 10:12 PM
  • Hi Vikas Manghani,

    Instead of disable a ComboBox, you can have another choice, make it read only. Through there is no ReadOnly property for ComboBox control, you can implement a ReadOnly ComboBox by yourself. Here is the code.
    public class MyComboBox : ComboBox
        {
            private bool _ReadOnle;
            private uint WM_MOUSEMOVE = 0x200;
            private uint WM_LBUTTONDOWN = 0x201;
            private uint WM_RBUTTONDOWN = 0x204;
            private uint WM_MBUTTONDOWN = 0x207;
            private uint WM_LBUTTONUP = 0x202;
            private uint WM_RBUTTONUP = 0x205;
            private uint WM_MBUTTONUP = 0x208;
            private uint WM_LBUTTONDBLCLK = 0x203;
            private uint WM_RBUTTONDBLCLK = 0x206;
            private uint WM_MBUTTONDBLCLK = 0x209;

            public MyComboBox()
            {
                this._ReadOnle = true;
                this.DropDownStyle = ComboBoxStyle.DropDownList;
                this.TabStop = false;
            }

            public bool ReadOnly
            {
                get
                {
                    return this._ReadOnle;
                }
                set
                {
                    this._ReadOnle = value;
                }
            }

            protected override void WndProc(ref Message m)
            {
                if (this._ReadOnle && (m.Msg >= WM_MOUSEMOVE && m.Msg <= WM_MBUTTONDBLCLK))
                {
                    return;
                }
                base.WndProc(ref m);
            }
        }
    To filter all the message that can change a ComboBox's value, the ComboBox will be readonly.
    Hope this help you.

    Sincerely,
    Kira Qian


    Please mark the replies as answers if they help and unmark if they don't.
    • Marked as answer by Kira Qian Tuesday, April 14, 2009 6:51 AM
    Thursday, April 9, 2009 5:45 AM
  • I'm sorry about my post. 
    My suggestion was supposed to be to hide the ComboBox by turning of the Visible property and replacing it with a TextBox.  Swapping the controls as the CB is enabled or disabled.
    Mark the best replies as answers. "Fooling computers since 1971."
    Here's a custom control that swaps out the combobox for an indentically sized textbox.  I am posting the Designer.cs file first.

    partial class ReadOnlySelectionBox
        {
            /// <summary> 
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary> 
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Component Designer generated code
    
            /// <summary> 
            /// Required method for Designer support - do not modify 
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.comboBox1 = new System.Windows.Forms.ComboBox();
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.SuspendLayout();
                // 
                // comboBox1
                // 
                this.comboBox1.FormattingEnabled = true;
                this.comboBox1.Location = new System.Drawing.Point(0, 2);
                this.comboBox1.Name = "comboBox1";
                this.comboBox1.Size = new System.Drawing.Size(121, 21);
                this.comboBox1.TabIndex = 0;
                // 
                // textBox1
                // 
                this.textBox1.Location = new System.Drawing.Point(0, 2);
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(121, 21);
                this.textBox1.TabIndex = 1;
                this.textBox1.Visible = false;
                // 
                // ReadOnlySelectionBox
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.Controls.Add(this.textBox1);
                this.Controls.Add(this.comboBox1);
                this.Name = "ReadOnlySelectionBox";
                this.Size = new System.Drawing.Size(124, 28);
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.ComboBox comboBox1;
            private System.Windows.Forms.TextBox textBox1;
        }
    Here's the user's code file.

    public partial class ReadOnlySelectionBox : UserControl
        {
            public event EventHandler<EventArgs> ReadOnlyChanged;
            private bool readOnly;
            public bool ReadOnly
            {
                get
                {
                    return readOnly;
                }
                set
                {
                    readOnly = value;
                    this.OnReadOnlyChanged(new EventArgs());
                }
            }
            //private Color disabledBackgroundColor;
            public Color DisabledBackgroundColor
            {
                get
                {
                    return this.textBox1.BackColor;
                }
                set
                {
                    this.textBox1.BackColor = value;
                }
            }
    
            public ComboBox SelectionBox
            {
                get
                {
                    return this.comboBox1;
                }
                set
                {
                    this.comboBox1 = value;
                }
            }
    
            public ReadOnlySelectionBox()
            {
                InitializeComponent();
                InitializeThis();
            }
    
            private void InitializeThis()
            {
                //this.comboBox1.Items.Add("Item1");  // test items,
                //this.comboBox1.Items.Add("Item2");  // these lines can
                //this.comboBox1.Items.Add("Item3");  // be deleted.
                this.DisabledBackgroundColor = Color.AliceBlue;
                this.textBox1.ReadOnly = true;
            }
    
            private void OnReadOnlyChanged(EventArgs e)
            {
                this.textBox1.Text = this.comboBox1.Text;
                switch (this.ReadOnly)
                {
                    case true:
                        this.comboBox1.Visible = false;
                        this.textBox1.Visible = true;
                        break;
                    case false:
                        this.comboBox1.Visible = true;
                        this.textBox1.Visible = false;
                        break;
                    default:
                        break;
                }
                if (this.ReadOnlyChanged != null)
                {
                    ReadOnlyChanged.Invoke(this, e);
                }
            }
    
        }
    Simply change the ReadOnly property on the control. 
    Modify the DisabledBackgroundColor property to your liking. Default is Color.AliceBlue.  The first one. 
    Add more properties and events if you wish.




    Mark the best replies as answers. "Fooling computers since 1971."
    • Marked as answer by Kira Qian Tuesday, April 14, 2009 6:51 AM
    Thursday, April 9, 2009 4:39 PM

All replies

  • ComboBox is a native Windows control.  It does it's own painting and doesn't support owner-draw.  You can force OnPaint to run with SetStyle(ControlStyles.UserPaint, true) in the constructor but you're going to be quite disappointed with the result.
    Hans Passant.
    • Marked as answer by Kira Qian Tuesday, April 14, 2009 6:51 AM
    Tuesday, April 7, 2009 10:12 PM
  •  

    this.textBox1.ReadOnly = true;

     

    this.textBox1.BackColor = Color.AliceBlue;


    Mark the best replies as answers. "Fooling computers since 1971."
    Tuesday, April 7, 2009 10:53 PM
  • Hi Vikas Manghani,

    Instead of disable a ComboBox, you can have another choice, make it read only. Through there is no ReadOnly property for ComboBox control, you can implement a ReadOnly ComboBox by yourself. Here is the code.
    public class MyComboBox : ComboBox
        {
            private bool _ReadOnle;
            private uint WM_MOUSEMOVE = 0x200;
            private uint WM_LBUTTONDOWN = 0x201;
            private uint WM_RBUTTONDOWN = 0x204;
            private uint WM_MBUTTONDOWN = 0x207;
            private uint WM_LBUTTONUP = 0x202;
            private uint WM_RBUTTONUP = 0x205;
            private uint WM_MBUTTONUP = 0x208;
            private uint WM_LBUTTONDBLCLK = 0x203;
            private uint WM_RBUTTONDBLCLK = 0x206;
            private uint WM_MBUTTONDBLCLK = 0x209;

            public MyComboBox()
            {
                this._ReadOnle = true;
                this.DropDownStyle = ComboBoxStyle.DropDownList;
                this.TabStop = false;
            }

            public bool ReadOnly
            {
                get
                {
                    return this._ReadOnle;
                }
                set
                {
                    this._ReadOnle = value;
                }
            }

            protected override void WndProc(ref Message m)
            {
                if (this._ReadOnle && (m.Msg >= WM_MOUSEMOVE && m.Msg <= WM_MBUTTONDBLCLK))
                {
                    return;
                }
                base.WndProc(ref m);
            }
        }
    To filter all the message that can change a ComboBox's value, the ComboBox will be readonly.
    Hope this help you.

    Sincerely,
    Kira Qian


    Please mark the replies as answers if they help and unmark if they don't.
    • Marked as answer by Kira Qian Tuesday, April 14, 2009 6:51 AM
    Thursday, April 9, 2009 5:45 AM
  • I'm sorry about my post. 
    My suggestion was supposed to be to hide the ComboBox by turning of the Visible property and replacing it with a TextBox.  Swapping the controls as the CB is enabled or disabled.
    Mark the best replies as answers. "Fooling computers since 1971."
    Thursday, April 9, 2009 1:41 PM
  • I'm sorry about my post. 
    My suggestion was supposed to be to hide the ComboBox by turning of the Visible property and replacing it with a TextBox.  Swapping the controls as the CB is enabled or disabled.
    Mark the best replies as answers. "Fooling computers since 1971."
    Here's a custom control that swaps out the combobox for an indentically sized textbox.  I am posting the Designer.cs file first.

    partial class ReadOnlySelectionBox
        {
            /// <summary> 
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.IContainer components = null;
    
            /// <summary> 
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
            protected override void Dispose(bool disposing)
            {
                if (disposing && (components != null))
                {
                    components.Dispose();
                }
                base.Dispose(disposing);
            }
    
            #region Component Designer generated code
    
            /// <summary> 
            /// Required method for Designer support - do not modify 
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                this.comboBox1 = new System.Windows.Forms.ComboBox();
                this.textBox1 = new System.Windows.Forms.TextBox();
                this.SuspendLayout();
                // 
                // comboBox1
                // 
                this.comboBox1.FormattingEnabled = true;
                this.comboBox1.Location = new System.Drawing.Point(0, 2);
                this.comboBox1.Name = "comboBox1";
                this.comboBox1.Size = new System.Drawing.Size(121, 21);
                this.comboBox1.TabIndex = 0;
                // 
                // textBox1
                // 
                this.textBox1.Location = new System.Drawing.Point(0, 2);
                this.textBox1.Name = "textBox1";
                this.textBox1.Size = new System.Drawing.Size(121, 21);
                this.textBox1.TabIndex = 1;
                this.textBox1.Visible = false;
                // 
                // ReadOnlySelectionBox
                // 
                this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                this.Controls.Add(this.textBox1);
                this.Controls.Add(this.comboBox1);
                this.Name = "ReadOnlySelectionBox";
                this.Size = new System.Drawing.Size(124, 28);
                this.ResumeLayout(false);
                this.PerformLayout();
    
            }
    
            #endregion
    
            private System.Windows.Forms.ComboBox comboBox1;
            private System.Windows.Forms.TextBox textBox1;
        }
    Here's the user's code file.

    public partial class ReadOnlySelectionBox : UserControl
        {
            public event EventHandler<EventArgs> ReadOnlyChanged;
            private bool readOnly;
            public bool ReadOnly
            {
                get
                {
                    return readOnly;
                }
                set
                {
                    readOnly = value;
                    this.OnReadOnlyChanged(new EventArgs());
                }
            }
            //private Color disabledBackgroundColor;
            public Color DisabledBackgroundColor
            {
                get
                {
                    return this.textBox1.BackColor;
                }
                set
                {
                    this.textBox1.BackColor = value;
                }
            }
    
            public ComboBox SelectionBox
            {
                get
                {
                    return this.comboBox1;
                }
                set
                {
                    this.comboBox1 = value;
                }
            }
    
            public ReadOnlySelectionBox()
            {
                InitializeComponent();
                InitializeThis();
            }
    
            private void InitializeThis()
            {
                //this.comboBox1.Items.Add("Item1");  // test items,
                //this.comboBox1.Items.Add("Item2");  // these lines can
                //this.comboBox1.Items.Add("Item3");  // be deleted.
                this.DisabledBackgroundColor = Color.AliceBlue;
                this.textBox1.ReadOnly = true;
            }
    
            private void OnReadOnlyChanged(EventArgs e)
            {
                this.textBox1.Text = this.comboBox1.Text;
                switch (this.ReadOnly)
                {
                    case true:
                        this.comboBox1.Visible = false;
                        this.textBox1.Visible = true;
                        break;
                    case false:
                        this.comboBox1.Visible = true;
                        this.textBox1.Visible = false;
                        break;
                    default:
                        break;
                }
                if (this.ReadOnlyChanged != null)
                {
                    ReadOnlyChanged.Invoke(this, e);
                }
            }
    
        }
    Simply change the ReadOnly property on the control. 
    Modify the DisabledBackgroundColor property to your liking. Default is Color.AliceBlue.  The first one. 
    Add more properties and events if you wish.




    Mark the best replies as answers. "Fooling computers since 1971."
    • Marked as answer by Kira Qian Tuesday, April 14, 2009 6:51 AM
    Thursday, April 9, 2009 4:39 PM