mardi 16 août 2016

C# - CheckBox height if off by 1 pixel from what it is set to

Using the method SetPropertyBulk to set the height of a CheckBox to 16, its actual height ends up being an extra 1 pixel higher (17).

Relevant methods:

    public IEnumerable<Control> GetAllControls(Control parentControl, Type type = null)
    {
        var controls = parentControl.Controls.Cast<Control>();

        if (type != null)
        {
            return
                controls.SelectMany(ctrl => GetAllControls(ctrl, type))
                    .Concat(controls)
                    .Where(c => c.GetType() == type);
        }
        return controls.SelectMany(ctrl => GetAllControls(ctrl)).Concat(controls);
    }

    public void SetPropertyBulk(string propertyS, object val, Type t = null,
        Control parentControl = null)
    {
        Control parent = parentControl ?? _f;

        foreach (Control c in GetAllControls(parent, t))
        {
            PropertyInfo p;

            try
            {
                p = c.GetType().GetProperty(propertyS,
                    BindingFlags.Public
                    | BindingFlags.Instance
                    | BindingFlags.FlattenHierarchy);
            }
            catch (AmbiguousMatchException)
            {
                p = c.GetType().GetProperty(propertyS,
                    BindingFlags.Public
                    | BindingFlags.Instance
                    | BindingFlags.DeclaredOnly);
                Debug.Print($"Ambiguous match for property {propertyS} " +
                            $"in control {c}");
            }       

            if (p != null && p.CanWrite)
            {
                try
                {
                    p.SetValue(c, val, null);
                    Debug.Print($"================\n" +
                                $"Set property\n" +
                                $"Type: {c}\n" +
                                $"Property: {p.Name}\n" +
                                $"Value: {val}\n" +
                                $"Check: {p.GetValue(c)}");
                }
                catch (ArgumentException)
                {
                    Debug.Print(
                        $"The given value {val} is not valid for the " +
                        $"given property {propertyS} in control {c}.");
                }
            }
            else
            {
                Debug.Print($"The given property {propertyS} does not " +
                            $"exist for control {c}.");
            }
        }
    }

    public void SetPropertyBulk(string propertyS, object val, ICollection<Type> t,
        Control parentControl = null)
    {
        foreach (Type type in t)
        {
            SetPropertyBulk(propertyS, val, type);
        }
    }

I'm calling the methods in the form load event like so:

        const int cHeight = 16;

        SetPropertyBulk("Height", cHeight,
            new List<Type>
            {
                typeof(Label),
                typeof(CheckBox),
                typeof(TextBox),
                typeof(NumericUpDown)
            });
        SetPropertyBulk("MinimumSize", new Size(0, cHeight),
            new List<Type> {typeof(Label), typeof(CheckBox)});
        SetPropertyBulk("AutoSize", true,
            new List<Type> {typeof(Label), typeof(CheckBox)});

I'm checking the value of the height property like so:

        Debug.Print($"Check Top: {GenChkScreen.Top}");
        Debug.Print($"Check Bottom: {GenChkScreen.Bottom}");
        Debug.Print($"Check Height: {GenChkScreen.Height}");

And it returns:

Check Top: 15
Check Bottom: 32
Check Height: 17

I also have a Debug.Print in SetPropertyBulk, which for the CheckBox returns:

================
Set property
Type: System.Windows.Forms.CheckBox, CheckState: 0
Property: Height
Value: 16
Check: 16

The former debug output returns a height of 17, but PropertyInfo.GetValue() in the latter debug output returns a height of 16. By setting the CheckBox's BackColor property to a colour different from the form and counting the pixels, the actual size of the CheckBox is 17.

Why is the height not being set to 16? Why is PropertyInfo.GetValue() returning the wrong height (or, unbeknownst to me, the height is being changed again after being set in SetPropertyBulk.)




Aucun commentaire:

Enregistrer un commentaire