簡體   English   中英

如何在 Winforms 中為 NumericUpDown 控件內的值提供填充(所有邊)

[英]How to give padding(all sides) to a value inside NumericUpDown Control in Winforms

我遇到了這個問題,即在 Winforms 的 NumericUpDown 控件中為所有方面提供填充

顯然以前沒有人問過這個問題。

控件的實際外觀:( https://i.stack.imgur.com/KIweV.png ) 預期控件的外觀:在此處輸入圖像描述

忽略兩個附加圖像中的其他差異。 只需要從頂部、底部和左側填充值; 作為這個問題的一部分。

到目前為止,我只發現有一個 TextAlign 屬性可以左對齊或右對齊或居中對齊,但這無助於為控件的頂部和底部邊緣提供填充。

下面的代碼沒有解決我的問題 this.numericUpDown1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;

AFAIK,您無法控制 winforms NumericUpDown 控件的高度,因此它的文本屬性只允許左、中和右(相對於 label,它有 9 種可能性(TopLeft、MiddleCenter、BottomRight 和很快)。
但是,您可以創建自己的控件來替換內置的 numericUpDown,但這需要大量工作。
也許有人已經完成了這項工作並在某處發布了開源。

NumericUpDown控件有一個內部UpDownEdit子控件,派生自用於顯示和編輯值的TextBox控件。 您可以 p/invoke 設置單行TextBox左邊距和/或右邊距。 添加到多行TextBox頂部和/或底部邊距。

考慮列出的擴展 class,它以TextBoxBase抽象 class 的派生類型為目標。它將SetInnerMargin方法添加到這些類型以設置內邊距。 請注意,對於單行文本框, Padding結構的 Top 和 Bottom 屬性的值將被忽略。

// TextBox, RichTextBox...etc.
public static class TextBoxBaseExtensions
{
    private const int EM_SETRECT = 0xB3;
    private const int EM_SETMARGINS = 0xD3;

    private const int EC_LEFTMARGIN = 0x1;
    private const int EC_RIGHTMARGIN = 0x2;

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left, Top, Right, Bottom;

        public RECT(int left, int top, int right, int bottom)
        {
            Left = left;
            Top = top;
            Right = right;
            Bottom = bottom;
        }

        public RECT(Rectangle r)
        {
            Left = r.Left;
            Top = r.Top;
            Right = r.Right;
            Bottom = r.Bottom;
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, int msg, int wParam, ref RECT rect);

    public static void SetInnerMargin(this TextBoxBase self, Padding pad)
    {
        if (self.Multiline)
        {
            var r = new Rectangle(
                pad.Left, 
                pad.Top, 
                self.ClientSize.Width - pad.Left - pad.Right, 
                self.ClientSize.Height - pad.Top - pad.Bottom);
            var nr = new RECT(r);

            SendMessage(self.Handle, EM_SETRECT, 0, ref nr);
        }
        else
        {
            SendMessage(
                self.Handle,
                EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN,
                pad.Right * 0x10000 + pad.Left);
        }
    }
}

使用示例:

var pad = new Padding(5);

textBox1.SetInnerMargin(pad);
richTextBox1.SetInnerMargin(pad);
(numericUpDown1.Controls[1] as TextBox).SetInnerMargin(pad);

確保在調用此方法之前創建並分配了目標控件的句柄。 或者,訂閱他們的HandleCreated事件來調用它。

此外,您可以創建自定義控件來實現此功能。 例如:

public class NumericUpDownEx : NumericUpDown
{
    private Padding inMargin = Padding.Empty;
    /// <summary>
    /// Gets or sets the inner margins. The Left and Right only.
    /// The Top and Bottom margins are ignored.
    /// </summary>
    [DefaultValue(typeof(Padding), "0, 0, 0, 0")]
    public Padding InnerMargin
    {
        get => inMargin;
        set
        {
            if (inMargin != value)
            {
                inMargin = value;
                SetInnerMargins();
            }
        }
    }

    /// <inheritdoc cref="TextBox.TextAlign"/>
    new public HorizontalAlignment TextAlign
    {
        get => base.TextAlign;
        set
        {
            if (base.TextAlign != value)
            {
                base.TextAlign = value;
                SetInnerMargins();
            }
        }
    }

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        SetInnerMargins();
    }

    private void SetInnerMargins()
    {
        if (Controls[1] is TextBox tb)
            tb.SetInnerMargin(InnerMargin);
    }
}

SO74470685

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM