更改 NumericUpDown 控件的边框颜色

3

我对C#非常陌生,有一个问题。我可以通过将按钮的FlatStyle更改为“Flat”来更改其边框颜色。但是在使用NumericUpDown时,我无法更改FlatStyle。我仍然希望能够使用上下箭头,因此仅使用其他方法来覆盖边缘是不起作用的。以下是我在代码中简化后的版本:

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace bordertest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            BackColor = Color.Black;
            numericUpDown1.BackColor = Color.Red;
        }
    }
}

请参考此链接:https://stackoverflow.com/questions/14725328/draw-border-for-numericupdown - Meysam Asadi
只是作为一个附注,这个控件会触发绘制事件,如果有人想要在不使用继承的情况下实现相同的行为,他们可以处理Paint事件并绘制边框;然而,作为一种通用的解决方案和可重复使用的方法,派生控件更加合理。 - Reza Aghaei
2个回答

5

您可以从 NumericUpDown 派生,添加一个 BorderColor 属性,重写 OnPaint 方法并基于边框颜色绘制边框。

using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
public class MyNumericUpDown : NumericUpDown
{
    private Color borderColor = Color.Blue;
    [DefaultValue(typeof(Color), "0,0,255")]
    public Color BorderColor
    {
        get { return borderColor; }
        set
        {
            if (borderColor != value)
            {
                borderColor = value;
                Invalidate();
            }
        }
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        if (BorderStyle != BorderStyle.None)
        {
            using (var pen = new Pen(BorderColor, 1))
                e.Graphics.DrawRectangle(pen,
                    ClientRectangle.Left, ClientRectangle.Top,
                    ClientRectangle.Width - 1, ClientRectangle.Height - 1);
        }
    }
}

输入图像描述

注意: 作为侧面说明,这个控件会触发绘制事件,如果有人想要实现相同的行为而不是通过继承,他们可以处理Paint事件并绘制边框;然而作为一种通用的解决方案和可重复使用的方法,派生控件更有意义。

private void numericUpDown_Paint(object sender, PaintEventArgs e)
{
    var c = (NumericUpDown)sender;
    ControlPaint.DrawBorder(e.Graphics, c.ClientRectangle,
        Color.Red, ButtonBorderStyle.Solid);
    var r = new Rectangle(1, 1, c.Width - 2, c.Height - 2);
    e.Graphics.SetClip(r);
}

FlatNumericUpDown

我创建了一个支持BorderColorButtonHighlightColor的FlatNumericUpDown。您可以下载或克隆它:

输入图像描述


@RezeAghaei 我尝试使用您使用的第一种方法,但VS 2019给了我一个错误"CS0119 BorderStyle'是一种类型,在给定的上下文中无效"。不过,您在注释下提供的第二种方法确实可行。我想我应该更清楚地表达我的意思,因为薄边框的颜色确实改变了,这也是我想要的部分。我还想知道是否可以更改带有箭头的那些小按钮的颜色? - fauxvelocity
这两种方法都经过测试并且正常工作。可能你漏掉了什么。 - Reza Aghaei
我还创建了一个FlatNumericUpDown存储库。你可以基于它开始创建自己的FlatNumericUpDown。 - Reza Aghaei
既然您对扁平控件感兴趣,您可能还会喜欢更改TextBox边框颜色更改ComboBox边框颜色 - Reza Aghaei
您可能也对FlatDateTimePicker感兴趣。 - Reza Aghaei

2
一个自定义控件版本,它重写了 WndProc 来绘制 NumericUpDown 的边框(但它也可以应用于许多其他控件),并使用标准的 ControlPaint 渲染功能。
这样可以轻松地绘制边框(实际上,不需要任何努力),并且有多种可用的样式。 BorderStyle 属性被 隐藏,以返回扩展的 ButtonBorderStyle 值,其中包括例如 DottedDashed 样式,除了默认的 Solid
该类添加了一个公共的 BorderColor 属性,它当然会出现在 PropertyGrid 中;它允许更改边框的颜色。
它默认为 Color.DarkGray,与 SystemColors.ControlDark 类似。
如果要更加精确,您可以使用与 Reza Aghaei 使用的 Attribute 样式 相同的方式 指定 RGB 值,而不是 "DarkGray"
将此类添加到项目中,构建项目,在工具箱中找到自定义控件并像往常一样将其拖放到窗体上(如果您不知道该怎么做的话)。
► 请注意,您可以使用相同的技术应用于许多其他标准控件(包括通常不会引发 Paint 事件的 TextBox 控件),以及所有自己设计的自定义控件/组件。
这就是它的外观: NumericUpdown Custom Border Styles Custom NumericUpdown PropertyGrid
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

[DesignerCategory("Code"), ToolboxItem(true)]
public class NumericUpDownEx : NumericUpDown
{
    private const int WM_PAINT = 0x000F;
    private ButtonBorderStyle m_BorderStyle = ButtonBorderStyle.Solid;
    private Color m_BorderColor = Color.DarkGray;

    public NumericUpDownEx() { }

    public new ButtonBorderStyle BorderStyle {
        get => m_BorderStyle;
        set {
            if (m_BorderStyle != value) {
                m_BorderStyle = value;
                Invalidate();
            }
        }
    }

    [DefaultValue(typeof(Color), "DarkGray")]
    public Color BorderColor {
        get => m_BorderColor;
        set {
            if (m_BorderColor != value) {
                m_BorderColor = value;
                Invalidate();
            }
        }
    }

    protected override void WndProc(ref Message m)
    {
        base.WndProc(ref m);
        switch (m.Msg) {
            case WM_PAINT:
                if (IsHandleCreated) {
                    using (var g = Graphics.FromHwndInternal(this.Handle)) {
                        ControlPaint.DrawBorder(g, ClientRectangle, m_BorderColor, m_BorderStyle);
                    }
                    m.Result = IntPtr.Zero;
                }
                break;
        }
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接