Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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

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

enter image description here

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:

enter image description 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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
266 views
Welcome To Ask or Share your Answers For Others

1 Answer

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:

enter image description here

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...