简体   繁体   中英

NumericUpDown with Unit | Custom control | Field padding

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!

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);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM