【问题标题】:Change Border Color of NumericUpDown更改 NumericUpDown 的边框颜色
【发布时间】:2021-01-25 00:44:51
【问题描述】:

我对 C# 很陌生,有一个问题。我已经能够通过将它们的 FlatStyle 更改为“Flat”来更改按钮等的边框颜色。使用NumericUpDown,我无法更改平面样式。我希望仍然能够使用向上和向下箭头,因此仅使用其他东西来覆盖边缘是行不通的。这是我在代码中所做的简化版本:

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

【问题讨论】:

  • 顺便说一句,这个控件引发了画图事件,如果有人出于任何原因想要在没有继承的情况下实现相同的行为,他们可以处理画图事件并绘制边框;但是,作为通用解决方案和可重用解决方案,派生控件更有意义。

标签: c# .net winforms numericupdown


【解决方案1】:

您可以从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);
        }
    }
}

注意:顺便说一句,这个控件引发了绘制事件,如果出于某种原因有人想要在没有继承的情况下实现相同的行为,他们可以处理绘制事件并绘制边框;但是,作为通用解决方案和可重用解决方案,派生控件更有意义。

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' 是一种类型,在给定的上下文中无效”。您在注释下提供的第二种方法确实有效。我认为我应该更清楚我想要什么,因为细边框的颜色确实发生了变化,这是我想要的一部分。我也想知道我是否也可以改变那些带有箭头的小按钮的颜色?
  • 两种方法都经过测试并且工作正常。可能你错过了什么。
  • 我还创建了一个 FlatNumericUpDown 存储库。您可以在此基础上开始创建自己的 FlatNumericUpDown。
  • 如果你对平面控制感兴趣,你可能也会喜欢Change TextBox BorderColorChange ComboBox BorderColor
  • 您可能还对FlatDateTimePicker感兴趣。
【解决方案2】:

覆盖WndProc 以使用标准ControlPaint 呈现功能绘制NumericUpDown(但它可以应用于许多其他控件)边框的自定义控件版本。

这允许绘制边框不费力气(实际上,没有:) 并且有多种开箱即用的样式。

BorderStyle 属性是shadowed,返回扩展的ButtonBorderStyle 值,除了默认值之外,还包括例如DottedDashed 样式Solid.

一个公共的BorderColor属性被添加到类中,它当然会出现在PropertyGrid中;它允许更改边框的颜色。
默认为Color.DarkGray,类似于SystemColors.ControlDark
如果您想精确,您可以使用相同的属性样式used by Reza Aghaei 来指定RGB 值而不是"DarkGray"


将这个类添加到项目中,构建项目,在工具箱中找到自定义控件,然后像往常一样将其放在窗体上(以防你不知道如何处理它:)

► 请注意,您可以将相同的技术用于许多其他标准控件(包括通常不会引发 Paint 事件的 TextBox 控件)以及您自己设计的所有自定义控件/组件.

这就是它的样子:


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

}

【讨论】:

    猜你喜欢
    • 2017-03-05
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 2017-05-24
    • 2016-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多