繁体   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