如何在Winforms中为NumericUpDown控件内的值给予填充(所有边)

f0ofjuux  于 2022-11-25  发布在  其他
关注(0)|答案(2)|浏览(130)

在Winforms的NumericUpDown控件中,我遇到了为value的所有边提供填充的问题。
显然以前没有人问过这个问题。
控件的实际外观:(https://i.stack.imgur.com/KIweV.png)预期控件的外观:enter image description here
忽略两幅附图中的其他差异。只需要从顶部、底部和左侧填充值;作为这个问题的一部分。
到目前为止,我只知道有一个TextAlign属性,它可以左对齐、右对齐或居中对齐,但这对为控件的上下边缘提供填充没有帮助。
下面的代码并没有解决我的问题this.numericUpDown1.TextAlign =系统.窗口.窗体.水平对齐.居中;

bihw5rsg

bihw5rsg1#

当然,你不能控制winforms NumericUpDown控件的高度,因此它的文本标记属性只允许左、中、右(与之相对的是,一个标签有9种可能性(TopLeft、MiddleCenter、BottomRight等等)。
但是,您可以创建自己的控件来替换内置的numericUpDown,但这将需要大量的工作。
也许有人已经做了这项工作,并在某处发布了开源代码。

k0pti3hp

k0pti3hp2#

NumericUpDown控件有一个内部UpDownEdit子控件,该子控件派生自用于显示和编辑值的TextBox控件。您可以p/invoke来设置单行TextBoxLeft 和/或 Right 边距。将多行TextBoxTop 和/或 Bottom 边距添加到该子控件。
请考虑所列的扩充类别,其目的是TextBoxBase抽象类别的衍生型别。它会将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);
    }
}

相关问题