如何更改可选面板的边框颜色?

How to change BorderColor of a selectable Panel?

我想将所有面板的 BorderColor 更改为 Color.Lime:

foreach (Control G in GetAllControls (this))
{
    Panel p = sender as Panel;
    ControlPaint.DrawBorder(e.Graphics, p.DisplayRectangle, Color.Lime, ButtonBorderStyle.Inset);
}

它向我显示了这个错误:

Severity Code Description Project File Line Suppression State Error CS1061 'EventArgs' does not contain a definition for 'Graphics' and no accessible extension method 'Graphics' accepting a first argument of type 'EventArgs' could be found (are you missing a using directive or an assembly reference?)

作为建议,使用从 Panel 派生的自定义控件 - 如果您需要它的功能 - 或者从 Control 派生的自定义控件,以获得轻量级控件 - 如果您不需要任何预定义的行为(除了基本的 Control 功能,那是)。

例如,面板的简单调整 class 添加了一些允许定义的属性:

  • 分配给边框的颜色
  • 边框的大小
  • 选中控件时的边框颜色
  • 表示让Panel 可选:当Control进入时会改变Border Color,可以设置TabStop = true和Tab为突出显示

为了使控件可选,在设置 Selectable 属性 时修改了一些样式。
Control 调用 SetStyle() and sets ControlStyles.Selectable, ControlStyles.UserMouse and ControlStyles.StandardClick to true or false, then UpdateStyles(), to force the new style (the Control retrieves the styles from the CreateParams property), then Invalidate() 本身(这调用 OnPaint 方法,后者又引发 Paint 事件)以在新状态下绘制 Border。


将名为 PanelEx 的 class 添加到项目中,粘贴此处的内容(当然保留命名空间),构建项目,在工具箱中找到新控件并打开表格。
如果您想用这个替换所有标准面板控件,请使用 Visual Studio (CTRL+H) 的 search/replace 功能并替换现有标准 Panel 使用 PanelEx 类型键入对象(那些需要新行为的对象)。

注意 - x64 项目:
如果主项目需要以 x64 为目标,您可以将以 AnyCPU 为目标的新 Class 库项目添加到解决方案中。将此自定义控件 class(或您创建的任何其他自定义控件,当然)添加到此库。还要添加对 System.Windows.FormsSystem.Drawing 程序集的引用。
重建解决方案,Visual Studio 会将库中找到的所有控件添加到工具箱。
当您将控件从工具箱放到窗体上时,没有人会抱怨。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

[DesignerCategory("code")]
public class PanelEx : Panel
{
    private Color m_BorderColorSel = Color.Transparent;
    private Color m_BorderColor = Color.Transparent;
    private bool m_Selectable = false;
    private bool m_Selected = false;
    private int m_BorderSize = 1;

    public PanelEx() { }

    public Color BorderColor { get => m_BorderColor;
        set {
            if (value == m_BorderColor) return;
            m_BorderColor = value;
            Invalidate();
        }
    }

    public int BorderSize {
        get => m_BorderSize;
        set {
            if (value == m_BorderSize) return;
            m_BorderSize = value;
            Invalidate();
        }
    }

    public bool Selectable {
        get => m_Selectable;
        set {
            if (value == m_Selectable) return;
            m_Selectable = value;
            SetStyle(ControlStyles.Selectable | ControlStyles.UserMouse | ControlStyles.StandardClick, value);
            UpdateStyles();
            Invalidate();
        }
    }

    public Color BorderColorSelected {
        get => m_BorderColorSel;
        set {
            m_BorderColorSel = value;
            if (!Selectable || value == m_BorderColorSel) return;
            Invalidate();
        }
    }


    protected override void OnPaint(PaintEventArgs e)
    {
        Color penColor = m_Selectable && m_Selected ? m_BorderColorSel : m_BorderColor;
        int rectOffset = BorderSize / 2;
        using (Pen pen = new Pen(penColor, BorderSize)) {
            var rect = new Rectangle(rectOffset, rectOffset, ClientSize.Width - BorderSize, ClientSize.Height - BorderSize);
            e.Graphics.DrawRectangle(pen, rect);
        }
        base.OnPaint(e);
    }

    protected override void OnMouseEnter(EventArgs e)
    {
        base.OnMouseEnter(e);
        OnEnter(e);
    }
    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        OnLeave(e);
    }

    protected override void OnEnter(EventArgs e)
    {
        base.OnEnter(e);
        m_Selected = true;
        Invalidate();
    }
    protected override void OnLeave(EventArgs e)
    {
        base.OnLeave(e);
        m_Selected = false;
        Invalidate();
    }
}