user15427813
user15427813

Reputation:

How to change BorderColor of a selectable Panel?

I want to change all panel's BorderColor to Color.Lime:

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

It shows me this error:

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?)

Upvotes: 2

Views: 606

Answers (1)

Jimi
Jimi

Reputation: 32248

As a suggestion, use a Custom Control derived from Panel -if you need its features - or from Control, to have a lightweight Control - if you don't require any predefined behavior (except the base Control functionality, that is).

For example, a simple tweak of the Panel class that adds some properties that allow to define:

  • a Color to assign to the Border
  • the Size of the Border
  • the Color of the Border when the Control is selected
  • means to make the Panel selectable: it will change the Border Color when the Control is entered, you can set TabStop = true and Tab to highlight etc.

To make the Control selectable, some styles are modified when the Selectable property is set.
The Control calls 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() itself (this calls the OnPaint method, which in turn raises the Paint event) to draw the Border in the new state.


Add class named PanelEx to the Project, paste in what's in here (preserving the Namespace, of course), build the Project, find the new Control in the ToolBox and drop is on a Form.
If you want to replace all standard Panel Controls with this one, use the search/replace functions of Visual Studio (CTRL+H) and replace existing standard Panel Type objects (those that need the new behavior) with the PanelEx Type.

NOTE - x64 Projects:
If the main Project needs to target x64, you can add a new Class Library Project that targets AnyCPU to the Solution. Add this Custom Control class (or any other Custom Control you have built, of course) to this Library. Also add a Reference to the System.Windows.Forms and System.Drawing assemblies.
Rebuild the Solution and Visual Studio will add to the Toolbox all the Controls found in the library.
Nobody will complain when you then drop your Controls on a Form from the Toolbox.

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

Upvotes: 2

Related Questions