【问题标题】:Redraw button graphic on MouseOver or click在 MouseOver 上重绘按钮图形或单击
【发布时间】:2019-12-26 13:56:40
【问题描述】:

我创建了一个自定义按钮(关闭按钮),如下所示:

当我将鼠标移到按钮上时,它的颜色变为红色,如下所示:

当鼠标悬停在按钮上时,我想将按钮上的“X”重绘为白色,看起来像这样(我已经在油漆中修改了上面的图像以显示我希望它的外观):

我不知道该怎么做。

我的自定义按钮基本上继承自常规 Button 控件,并带有一些自定义设置。代码如下:

public class CloseButton : Button
{
    public CloseButton()
    {
        this.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
        this.FlatAppearance.BorderSize = 0;
        this.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
        this.FlatAppearance.MouseOverBackColor = System.Drawing.Color.DarkRed;
        this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.Size = new System.Drawing.Size(50, 30);
        this.UseVisualStyleBackColor = true;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        GraphicsPath gPath;
        Pen gPen;
        gPen = new Pen(System.Drawing.SystemColors.ControlText);
        gPath = new GraphicsPath();
        gPath.AddLine(20, 10, 30, 20);
        gPath.CloseFigure();
        gPath.AddLine(20, 20, 30, 10);
        gPath.CloseFigure();
        e.Graphics.DrawPath(gPen, gPath);
    }
}

我已尝试更改 OnPaint() 方法,以便笔颜色由控件的背景色确定,如下所示:

if ((this.BackColor.Equals(System.Drawing.Color.DarkRed) || this.BackColor.Equals(System.Drawing.Color.IndianRed))
{
    gPen = new Pen(System.Drawing.SystemColors.ControlLightLight;
}
else
{
    gPen = new Pen(System.Drawing.SystemColors.ControlText;
}

然后在我的 MouseEnter 和 Click 处理程序中,我使控件无效并刷新如下:

_BtnClose.Invalidate();
_BtnClose.Refresh();

这没有任何作用。我怎样才能实现我想要做的事情?如果我被卡住了,我总是可以创建另一个带有白色 X 的自定义按钮,并根据需要显示/隐藏此按钮,但如果可能的话,我想避免这样做

【问题讨论】:

  • MouseOverBackColor 在按钮渲染器中用于绘制按钮,它不会改变 BackColor。考虑一个简单的 bool 字段,在 OnMouseEnter() 中设置为 true,在 OnMouseLeave() 中设置为 false。

标签: c# .net winforms button


【解决方案1】:

我会这样写,那么:

public class CloseButton : Button
{

    GraphicsPath gPath;

    public CloseButton()
    {
        this.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
        this.FlatAppearance.BorderSize = 0;
        this.FlatAppearance.MouseDownBackColor = System.Drawing.Color.IndianRed;
        this.FlatAppearance.MouseOverBackColor = System.Drawing.Color.DarkRed;
        this.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        this.Size = new System.Drawing.Size(50, 30);
        this.UseVisualStyleBackColor = true;

        gPath = new GraphicsPath();
        gPath.AddLine(20, 10, 30, 20);
        gPath.CloseFigure();
        gPath.AddLine(20, 20, 30, 10);
        gPath.CloseFigure();
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        bool cursorInControl = this.ClientRectangle.Contains(this.PointToClient(Cursor.Position));
        using (Pen gPen = new Pen(cursorInControl ? System.Drawing.SystemColors.ControlLightLight : System.Drawing.SystemColors.ControlText))
        {
            e.Graphics.DrawPath(gPen, gPath);
        }                
    }
}

GraphicsPath 永远不会更改,因此它在控制级别声明并保留以供将来使用,而不是每次都重新创建它。此外,每当您创建 Pen 时,您还必须处理它,即 using 块。最后,我们将当前的Cursor.Position转换为client coordinates,这样我们就可以判断它是否在控制范围内。这用于在我们绘制 GraphicsPath 时切换颜色。

【讨论】:

  • gPath 需要设置在按钮的Dispose 中。
【解决方案2】:

绘制十字和更改十字颜色的另一个简单选项:

  • 您可以使用 字符来绘制十字。您可以通过字体大小轻松更改其大小。
  • 要改变的颜色,处理MouseEnterMouseLeave并分配ForeColor就足够了。它将重绘按钮。
  • 您可以将 字符用于最大化, 用于还原, 用于最小化:

using System;
using System.Drawing;
using System.Windows.Forms;
public class MyCloseButton : Button
{
    public MyCloseButton()
    {

        Anchor = AnchorStyles.Top | AnchorStyles.Right;
        FlatAppearance.BorderSize = 0;
        FlatAppearance.MouseDownBackColor = Color.IndianRed;
        FlatAppearance.MouseOverBackColor = Color.DarkRed;
        FlatStyle = FlatStyle.Flat;
        Font = new Font(Font.FontFamily, 13);
        Size = new Size(56, 36);
        UseVisualStyleBackColor = false;
        MouseLeave += (s, e) => ForeColor = Color.Black;
        MouseEnter += (s, e) => ForeColor = Color.White;
    }
    public override string Text { get => ""; set => base.Text = ""; }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        TextRenderer.DrawText(e.Graphics, "✕", Font, ClientRectangle, ForeColor);
    }
}

您可以通过在构造函数中添加以下行来使按钮不可选择,以防止被鼠标或键盘选中:

SetStyle(ControlStyles.Selectable, false);

您可以通过添加以下代码将关闭行为添加到按钮ForeColor

protected override void OnClick(EventArgs e)
{
    base.OnClick(e);
    FindForm()?.Close();
}

如果您想要一个更大的按钮和更大的十字,请更改按钮大小及其字体大小:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多