2016-06-21 3 views
3

Ich versuche, ein benutzerdefiniertes Steuerelement zu erstellen, das NumericUpDown erbt, um eine einstellbare Einheit anzuzeigen.NumerischUpDown mit Einheit | Benutzerdefiniertes Steuerelement | Feldauffüllung

enter image description here

Mein Code::

Dies wird (visuell), was ich so weit gekommenein bisschen zu lang aussieht, aber isnt tun, dass viel

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

Mein Problem:

Das Etikett deckt derzeit das Ende der Box. Also, wenn ein großer Wert kommt in (oder die Größe niedrig ist) es wird durch das Etikett abgedeckt, wie hier zu sehen:

enter image description here

Ich weiß, dass die NumericUpDown so etwas wie eine Scroll-Funktion hat, wenn eine eingegeben Wert ist länger als die Größe der Eingabebox. Dies wird am Ende der Box ausgelöst.

Gibt es in irgendeiner Weise die Möglichkeit, etwas wie Padding für den Text in der Box einzurichten? Zum Beispiel die Polsterung auf der rechten Seite auf die Größe meines Etiketts setzen?

Ich mag diese benutzerdefinierte Kontrolle ziemlich viel, aber diese eine letzte Sache ist nervig.


Leider weiß ich nicht, wie man die Eigenschaften eines bestehenden Steuer Nachschlag wie zum Beispiel gibt es ein Verfahren UpdateEditText() genannt wird. Vielleicht kann mir jemand sagen, wie man diese Basisfunktionen/Eigenschaften nachschaut.

Vielen Dank!

+0

Sie erhalten die "Bildlauf" -Funktion kostenlos, aber es gilt nur für den Text, den das Steuerelement rendert. Sie überlagern einfach ein "Label" an einem bestimmten Punkt. Ich denke, dass Sie wirklich versuchen möchten, den vollständigen Text zurück zum Steuerelement zu liefern und keinen Text selbst zu zeichnen. Das könnte bedeuten, dass Sie sowohl Text als auch Wert verwalten, da der Text dann nicht numerisch wäre. – DonBoitnott

+0

@DonBoitnott Das war mein erster Gedanke.Aber dann realisierte ich, dass ich mich bereits mit meiner Dezimalstelle in den Text packte. Das Teilen dieser Themen wäre also nicht so schlimm (zum Beispiel mit einem Label). Die angenommene Antwort funktioniert hier gut. – C4u

Antwort

2

NumericUpDown ist ein Steuerelement, das von UpDownBase Verbundsteuerung erbt. Es enthält eine UpDownEdit und eine UpDownButtons Steuerung. Die UpDownEdit ist eine TextBox. Sie können das Aussehen des Steuerelements und seiner untergeordneten Elemente ändern. Zum Beispiel können Sie eine Label in die Textbox-Steuerelement hinzufügen und rechts von TextBox andocken, legen Sie dann Text Ränder von Text durch eine EM_SETMARGINS Nachricht sendet solche Ergebnisse zu erhalten:

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

Funktioniert gut! Würde es dir etwas ausmachen, mir zu erzählen, wie du dieses Gif erstellt hast? Ich glaube nicht, dass es eine Stunde für dich gedauert hat. Thema bezogen: So traurig gibt es kein 'EC_LEFTMARGIN'. Damit hätte ich eine neue Eigenschaft 'UnitDock' einrichten können. – C4u

+2

** - ** Ich verwende [ScreenToGif] (https://screentogif.codeplex.com/), um einen ausgewählten Bereich des Bildschirms aufzuzeichnen und als animiertes GIF zu speichern. ** - ** Um den linken Rand zu setzen, definiere 'private const int EC_LEFTMARGIN = 1;' dann 'SendMessage (Controls [1] .Handle, EM_SETMARGINS, EC_LEFTMARGIN, label.Width);' –

+0

Wow, danke für deine Antworten! – C4u

Verwandte Themen