C# TabStop并关注一个GroupBox

C# TabStop并关注一个GroupBox,c#,winforms,focus,groupbox,tabstop,C#,Winforms,Focus,Groupbox,Tabstop,我创建了一个扩展GroupBox的自定义控件。这个控件支持折叠和扩展,我使用GroupBoxRenderer和ButtonRenderer使它看起来像一个角落里有按钮的典型GroupBox。我已经处理了所有适当的鼠标事件,有效地使“按钮”的行为和外观像一个普通的按钮。现在我遇到了一个问题,GroupBox使用TabStop无法接收焦点。我是否可以让我的可折叠GroupBox从TabStop接收焦点 我希望我能利用来自的技巧在进入比赛中设置焦点,但我还没有想出一个好方法来确定什么时候应该真正获得焦

我创建了一个扩展GroupBox的自定义控件。这个控件支持折叠和扩展,我使用GroupBoxRenderer和ButtonRenderer使它看起来像一个角落里有按钮的典型GroupBox。我已经处理了所有适当的鼠标事件,有效地使“按钮”的行为和外观像一个普通的按钮。现在我遇到了一个问题,GroupBox使用TabStop无法接收焦点。我是否可以让我的可折叠GroupBox从TabStop接收焦点

我希望我能利用来自的技巧在进入比赛中设置焦点,但我还没有想出一个好方法来确定什么时候应该真正获得焦点。我可能会想出一种方法,找到TabIndex下一个最高和最低的兄弟姐妹(如果TabIndex相同,则为ChildIndex),然后确定他们是否失去了焦点,但这似乎有点老套,如果我没有完全正确的理解,很有可能会崩溃

注意:我最初确实创建了用户控件,但这不是我想要的,原因包括:

  • 它不是一个包含按钮和groupbox的控件(只是看起来有点像那样),而是一个groupbox
  • 灵活性
  • 后端代码和UI之间的耦合
  • 动态布局
  • 在许多项目中共享,这些项目需要工具箱支持并自定义整个控件的UI和布局
  • 以下是展开时的外观:

    现在,当它被折叠(并具有焦点)时:
    CheckGroup=>这里是一种自定义控件的方法,该控件继承自控件,并在OnPaint方法中使用GroupBoxRenderer和CheckBoxRenderer。它是一个容器,通过更改CheckBoxRenderer的绘制方式来模拟焦点。此代码折叠检查组并禁用任何子控件,但您可以根据需要删除其中一个或两个

    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Windows.Forms.VisualStyles;
    namespace CoolControls
    {
    
    [Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(System.ComponentModel.Design.IDesigner))] 
    public partial class CheckGroup : Control
    {
        public event EventHandler CheckBoxGotFocus;
        public event EventHandler CheckBoxLostFocus;
    
        private int _CheckBoxSideLength;
        private Rectangle _CheckBoxBorderRectangle;
        private bool _Focused = false;
        private bool _Checked;
        private CheckBoxState _CheckedState = CheckBoxState.UncheckedNormal;
        private int _ExpandedHeight;
    
        [Category("Behavior")]
        [Description("Get or set whether the checkbox is checked.")]
        public bool Checked
        {
            get { return _Checked; }
            set
            {
                SetCheckedState(value);
            }
        }
    
        public CheckGroup()
        {
            InitializeComponent();
            InitControl();
        }
    
        private void InitControl()
        {
            _CheckBoxSideLength = 15;
            _Checked = true;
            _Focused = false;
            _CheckBoxBorderRectangle = new Rectangle(0, 0, _CheckBoxSideLength - 1, _CheckBoxSideLength - 1);
        }
    
        private void SetCheckedState(bool pToChecked)
        {
            _Checked = pToChecked;
            if (_Checked)
            {
                _CheckedState = CheckBoxState.CheckedNormal;
                this.Height = _ExpandedHeight;
            }
            else
            {
                _CheckedState = CheckBoxState.UncheckedNormal;
                this.Height = _CheckBoxSideLength;
            }
            foreach (Control c in this.Controls)
            {
                c.Enabled = _Checked;
            }
            this.Invalidate();
        }
    
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            Graphics g = pe.Graphics;
            GroupBoxRenderer.DrawGroupBox(g, ClientRectangle, "   " + this.Text, this.Font, this.ForeColor, TextFormatFlags.Left, GroupBoxState.Normal);
            CheckBoxRenderer.DrawCheckBox(g, ClientRectangle.Location, _CheckBoxBorderRectangle, "", null, TextFormatFlags.Left, _Focused, _CheckedState);
        }
    
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            if (_Checked)
            {
                _ExpandedHeight = this.Size.Height;
            }
        }
    
        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);
            if (e.Location.Y <= _CheckBoxSideLength)
            {
                SetCheckedState(!_Checked);
            }
        }
    
        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            _Focused = true;
            Invalidate();
            CheckBoxGotFocus.Invoke(this, new EventArgs());
        }
    
        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            _Focused = false;
            Invalidate();
            CheckBoxLostFocus.Invoke(this, new EventArgs());
        }
    
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.KeyCode == Keys.Space)
            {
                SetCheckedState(!_Checked);
            }
        }
    
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            Invalidate();
        }
    }
    }
    
    使用系统;
    使用系统组件模型;
    使用系统图;
    使用系统文本;
    使用System.Windows.Forms;
    使用System.Windows.Forms.VisualStyles;
    名称空间控件
    {
    [Designer(“System.Windows.Forms.Design.ParentControlDesigner,System.Design”,typeof(System.ComponentModel.Design.IDesigner))]
    公共部分类检查组:控件
    {
    公共事件事件处理程序CheckBoxGotFocus;
    公共事件处理程序CheckBoxLostFocus;
    专用整数_CheckBoxSideLength;
    私有矩形_checkboxborder矩形;
    private bool_Focused=假;
    检查私人布尔;
    私有CheckBoxState _CheckedState=CheckBoxState.UncheckedNormal;
    私人内部扩展高度;
    [类别(“行为”)]
    [说明(“获取或设置复选框是否已选中。”)]
    公共图书馆检查
    {
    获取{return\u Checked;}
    设置
    {
    SetCheckedState(值);
    }
    }
    公共检查组()
    {
    初始化组件();
    InitControl();
    }
    私有void InitControl()
    {
    _CheckBoxSideLength=15;
    _选中=正确;
    _聚焦=假;
    _CheckBoxBorderRectangle=新矩形(0,0,_-CheckBoxSideLength-1,_-CheckBoxSideLength-1);
    }
    私有void SetCheckedState(bool pToChecked)
    {
    _已检查=已检查;
    如果(_选中)
    {
    _CheckedState=CheckBoxState.CheckedNormal;
    this.Height=\u ExpandedHeight;
    }
    其他的
    {
    _CheckedState=CheckBoxState.UncheckedNormal;
    this.Height=\u CheckBoxSideLength;
    }
    foreach(此.Controls中的控件c)
    {
    c、 已启用=\u已选中;
    }
    这个。使无效();
    }
    受保护的覆盖无效OnPaint(PaintEventArgs pe)
    {
    基础漆(pe);
    图形g=pe.图形;
    GroupBoxRenderer.DrawGroupBox(g,ClientRectangle,“+”this.Text,this.Font,this.ForeColor,TextFormatFlags.Left,GroupBoxState.Normal);
    CheckBoxRenderer.DrawCheckBox(g,ClientRectangle.Location,_CheckBoxBorderRectangle,“”,null,TextFormatFlags.Left,_Focused,_CheckedState);
    }
    IzeChanged上的受保护覆盖无效(EventArgs e)
    {
    基地.OnSizeChanged(e);
    如果(_选中)
    {
    _ExpandedHeight=this.Size.Height;
    }
    }
    MouseEventArgs e上的受保护覆盖无效(MouseEventArgs e)
    {
    base.OnMouseDown(e);
    
    如果(e.Location.Y我真的不明白,你说你
    扩展了GroupBox
    ,我认为这是某种继承,但如果是这样,为什么你必须使用
    GroupBoxRenderer
    ?你定制的
    GroupBox
    的实际基类是什么?顺便说一句,
    GroupBox
    不支持聚焦。我不认为
    GroupBox
    需要这样一个功能,你能解释一下吗?或者你想让它能够接收焦点来处理一些与焦点相关的事件,比如
    Enter
    GotFocus
    ?@KingKing我继承了GroupBox,但覆盖了OnPaint。我需要自己渲染整件事,否则GroupBox文本会在折叠/展开之后结束按钮(请参阅我添加的图像)。为了清楚起见,GroupBox可以通过编程方式接收焦点,但由于它是一个静态控件,因此不会通过TabStop机制接收焦点。