NumericUpDown with Unit | Custom control | Field padding

流过昼夜 提交于 2019-12-17 16:49:34

问题


Im trying to create a custom control that inherits NumericUpDown to show a settable unit.

This is (visually) what I've got so far:

My Code: Looks a bit long, but isnt doing that much

class NumericUpDownUnit : NumericUpDown
{
    public event EventHandler ValueChanged;

    /// <summary>
    /// Constructor creates a label
    /// </summary>
    public NumericUpDownUnit()
    {
        this.TextChanged += new EventHandler(TextChanged_Base);
        this.Maximum = 100000000000000000;
        this.DecimalPlaces = 5;

        this.Controls.Add(lblUnit);
        lblUnit.BringToFront();

        UpdateUnit();
    }

    public void TextChanged_Base(object sender, EventArgs e)
    {
        if(ValueChanged != null)
        {
            this.ValueChanged(sender, e);
        }
    }

    /// <summary>
    /// My designer property
    /// </summary>
    private Label lblUnit = new Label();
    [Description("The text to show as the unit.")]
    public string Unit
    {
        get
        {
            return this.lblUnit.Text;
        }
        set
        {
            this.lblUnit.Text = value;
            UpdateUnit();
        }
    }

    /// <summary>
    /// When unit has changed, calculate new label-size
    /// </summary>
    public void UpdateUnit()
    {
        System.Drawing.Size size = TextRenderer.MeasureText(lblUnit.Text, lblUnit.Font);
        lblUnit.Padding = new Padding(0, 0, 0, 3);
        lblUnit.Size = new System.Drawing.Size(size.Width, this.Height);
        lblUnit.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
        lblUnit.BackColor = System.Drawing.Color.Transparent;
        lblUnit.Location = new System.Drawing.Point(this.Width-lblUnit.Width-17, 0);
    }

    /// <summary>
    /// If text ends with seperator, skip updating text as it would parse without decimal palces
    /// </summary>
    protected override void UpdateEditText()
    {
        if (!this.Text.EndsWith(".") && !this.Text.EndsWith(","))
        Text = Value.ToString("0." + new string('#', DecimalPlaces));
    }

    /// <summary>
    /// Culture fix
    /// </summary>
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (e.KeyChar.Equals('.') || e.KeyChar.Equals(','))
        {
            e.KeyChar = System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator.ToCharArray()[0];
        }
        base.OnKeyPress(e);
    }

    /// <summary>
    /// When size changes, call UpdateUnit() to recalculate the lable-size
    /// </summary>
    protected override void OnResize(EventArgs e)
    {
        UpdateUnit();
        base.OnResize(e);
    }

    /// <summary>
    /// Usability | On enter select everything
    /// </summary>
    protected override void OnEnter(EventArgs e)
    {
        this.Select(0, this.Text.Length);
        base.OnMouseEnter(e);
    }

    /// <summary>
    /// If, when leaving, text ends with a seperator, cut it out
    /// </summary>
    protected override void OnLeave(EventArgs e)
    {
        if(this.Text.EndsWith(System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator))
        {
            this.Text = this.Text.Substring(0, this.Text.Length - 1);
        }

        base.OnLeave(e);
    }
}

My problem:

The lable is currently covering the end of the box. So if a big value comes in (or the size is low) it gets covered by the label as seen in here:

I know that the NumericUpDown has something like a scroll-function when a typed in value is longer than the size of the inputbox. This is triggered at the end of the box.

Is there in any way the possibility of setting up something like padding for the text inside the box? For example setting the padding on the right to the size of my label?

I like this custom control pretty much but this one last thing is annoying.


Unfortunately I dont know how to lookup the properties of an existing control as for example there is a method called UpdateEditText(). Maybe someone can tell me how to lookup this base functions/properties.

Thanks a lot!


回答1:


NumericUpDown is a control which inherits from UpDownBase composite control. It contains an UpDownEdit and an UpDownButtons control. The UpDownEdit is a TextBox. You can change appearance of the control and its children. For example, you can add a Label to the textbox control and dock it to the right of TextBox, then set text margins of textbox by sending an EM_SETMARGINS message to get such result:

Code

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ExNumericUpDown : NumericUpDown
{
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hwnd, int msg, int wParam, int lParam);
    private const int EM_SETMARGINS = 0xd3;
    private const int EC_RIGHTMARGIN = 2;
    private Label label;
    public ExNumericUpDown() : base()
    {
        var textBox = Controls[1];
        label = new Label() { Text = "MHz", Dock = DockStyle.Right, AutoSize = true };
        textBox.Controls.Add(label);
    }
    public string Label
    {
        get { return label.Text; }
        set { label.Text = value; if (IsHandleCreated) SetMargin(); }
    }
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        SetMargin();
    }
    private void SetMargin()
    {
        SendMessage(Controls[1].Handle, EM_SETMARGINS, EC_RIGHTMARGIN, label.Width << 16);
    }
}


来源:https://stackoverflow.com/questions/37947251/numericupdown-with-unit-custom-control-field-padding

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!