2

I have created a custom control which extends GroupBox. This control supports collapsing and expanding and I use the GroupBoxRenderer and ButtonRenderer to make it look like a typical GroupBox that has a Button in the corner. I have handled all the appropriate mouse events which effectively make the "button" behave and look like a regular Button. Now I have hit a problem where the GroupBox does not receive focus using TabStop. Is there anyway that I can get my Collapsable GroupBox to receive focus from a TabStop?

I was hoping that I could use the trick from How to set focus to a control after validation in .NET to set the focus in the Enter event but I haven't come up with a good way of determining when it should actually get the focus. I could probably devise a way of finding the siblings with the next highest and lowest TabIndex (or ChildIndex if the same TabIndex) and then determine if they lost focus but this seems a bit hacky and a high chance of breaking if I don't get it exactly right.

Note: I did initially create user control but this was not what I wanted for various reasons including:

  1. It is not a control that contains a button and a groupbox (it just so happens to sort of look that way), it is a groupbox
  2. Flexibility
  3. Coupling between backend code and UI
  4. Dynamic layout
  5. Shared across many projects which require Toolbox support and customising the UI and layout of the entire control

Here is what it looks like when expanded: enter image description here

And now when it has been collapsed (and has focus): enter image description here

4

1 回答 1

0

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

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();
    }
}
}
于 2015-03-06T22:27:18.057 回答