C# 平面按钮样式-当按钮处于活动状态时隐藏边框和焦点提示

C# 平面按钮样式-当按钮处于活动状态时隐藏边框和焦点提示,c#,winforms,button,flatbutton,C#,Winforms,Button,Flatbutton,我创建了一个带有透明边框的平面按钮,还设置了FlatAppearance.BorderSize=0 鼠标单击时边框隐藏,按下鼠标按钮时按钮背景使用自定义颜色 我的问题是无法删除按钮激活时绘制的边框,例如按Tab键。 我不能使用TabStop属性(将其设置为false),因为我需要我设计的功能 我只想绘制背景色并隐藏边框(与鼠标单击颜色相同) 表单设计器中的按钮属性: this.importBtn.BackgroundImage = global::CompetitionManager.Prop

我创建了一个带有透明边框的平面按钮,还设置了
FlatAppearance.BorderSize=0

鼠标单击时边框隐藏,按下鼠标按钮时按钮背景使用自定义颜色

我的问题是无法删除按钮激活时绘制的边框,例如按Tab键。
我不能使用
TabStop
属性(将其设置为false),因为我需要我设计的功能

我只想绘制背景色并隐藏边框(与鼠标单击颜色相同)

表单设计器中的按钮属性:

this.importBtn.BackgroundImage = global::CompetitionManager.Properties.Resources.Open;
this.importBtn.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
this.importBtn.Cursor = System.Windows.Forms.Cursors.Hand;
this.importBtn.Delta = 5;
this.importBtn.Dock = System.Windows.Forms.DockStyle.Fill;
this.importBtn.FlatAppearance.BorderSize = 0;
this.importBtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.SteelBlue;
this.importBtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Transparent;
this.importBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.importBtn.ForeColor = System.Drawing.Color.Transparent;
this.importBtn.Location = new System.Drawing.Point(3, 50);
this.importBtn.MoveXDirection = false;
this.importBtn.MoveYDirection = true;
this.importBtn.Name = "importBtn";
this.importBtn.Size = new System.Drawing.Size(183, 162);
this.importBtn.TabIndex = 0;
this.ToolTip.SetToolTip(this.importBtn, "Import Competitors (Excel/XML)");
this.importBtn.UseMargin = true;
this.importBtn.UseVisualStyleBackColor = true;
this.importBtn.Click += new System.EventHandler(this.ImportFile_Click);

 

如问题中所述,自定义控件(此处为按钮)在成为焦点时显示其标准焦点提示。默认渲染似乎不适合,因为背景颜色在特定上下文中呈现为透明,导致标准焦点提示变得令人讨厌

► 标准焦点提示渲染被禁用,以始终返回
false
(句柄尚未创建时除外)

► 该方法也被重写,以避免在使用按钮打开处于活动状态的窗口时出现类似效果:在这种情况下,按钮渲染时带有边框,表示它是该窗口的活动控件

► 定义按钮专门化的某些属性将使用自定义从PropertyGrid中删除,以避免对特定定义属性进行不必要的篡改

最后,在自定义控件的ClientRectangle底部绘制一个自定义焦点提示,以提供一些反馈,否则用户将不知道当前按钮/控件是什么。
鼠标悬停或单击按钮时,不显示自定义提示

这是一个可能的自定义渲染示例。当然,你现在可以画任何你想要的东西:一个不同的边框,背景,半透明覆盖等等

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

[ToolboxItem(true)]
[DesignerCategory("code")]
[Designer(typeof(CustomDesigner))]
public class ImportButton : Button
{
    private Color m_FocusColor = Color.LightBlue;
    private bool m_DrawFocusCue = false;

    public ImportButton() {
        this.Cursor = Cursors.Hand;
        this.Image = new Bitmap(Properties.Resources.[SomeImage]);
        this.FlatAppearance.BorderSize = 0;
        this.FlatAppearance.MouseDownBackColor = Color.SteelBlue;
        this.FlatAppearance.MouseOverBackColor = Color.Transparent;
        this.FlatStyle = FlatStyle.Flat;
    }

    protected override bool ShowFocusCues {
        get {
            m_DrawFocusCue = !ClientRectangle.Contains(PointToClient(MousePosition));
            return !IsHandleCreated;
        }
    }

    public override void NotifyDefault(bool value) => base.NotifyDefault(false);

    // Make it public if this value should be customizable
    private int FocusBorderSize { get; set; } = 2;

    protected override void OnPaint(PaintEventArgs e) {
        base.OnPaint(e);
        
        if (Focused && m_DrawFocusCue) {
            var rect = ClientRectangle;
            rect.Inflate(-FocusBorderSize, -FocusBorderSize);
            using (var pen = new Pen(FlatAppearance.MouseDownBackColor, FocusBorderSize)) {
                e.Graphics.DrawLine(pen, 0, rect.Bottom, rect.Right, rect.Bottom);
            }
        }
    }

    protected override void Dispose(bool disposing) {
        if (disposing) {
            this.Image?.Dispose();
        }
        base.Dispose(disposing);
    }

    public class CustomDesigner : ControlDesigner
    {
        private static string[] RemovedProperties = new[] {
            "AutoEllipsis", "AutoSize", "AutoSizeMode",
            "BackColor", "Cursor", "FlatAppearance", "FlatStyle",
            "ForeColor", "Text", "TextAlign", "TextImageRelation"
        };

        public CustomDesigner() { }

        protected override void PreFilterProperties(IDictionary properties) {
            foreach (string prop in RemovedProperties) {
                properties.Remove(prop);
            }
            base.PreFilterProperties(properties);
        }
    }
}

你的意思是说你正在一个按钮上运行同步代码。单击处理程序,按钮的呈现仍然被卡住?尝试
BeginInvoke()
该代码(如果事件处理程序中有所有代码,请将其移动到专用方法)。但是,由于处理程序名为
ImportFile
,您可能正在处理磁盘上的文件吗?如果是这样,您可以调用异步方法,因此您可能可以使处理程序异步。如果您不想要这些,请在调用任何同步代码之前,尝试按一下按钮。@Jimi我不知道您在说什么。忘记单击操作。我有10个这样设计的按钮,每次点击都会做不同的操作,但这与主题无关。当我按下tab按钮更新活动控件时,焦点将更新为新按钮。然后,我看到按钮周围有一个黑色边框。这与单击无关event@Jimi请看附件中的图片……好吧,这个:当我长按一下按钮时,如何删除边框并不能真正描述当按钮接收到焦点时您看到的简单聚焦矩形。由于它是一个自定义类,只需添加
protectedoverride boolshowfocuscues=>false
公共覆盖void NotifyDefault(bool值)=>base.NotifyDefault(false)。如果您已经覆盖了OnPaint,则可以在其上进行绘制。很抱歉,我不明白,当按下tab按钮时,我需要粘贴代码的哪一部分来删除边框?这是一个完整的自定义控件。只需向项目中添加一个新的类对象,将类文件命名为
ImportButton
。当VisualStudio向您展示新的类对象时,请粘贴在其中找到的所有内容。构建项目。现在,您将在工具箱中找到新的自定义控件,与任何其他控件一样(位于列表顶部)。把它写在表格上,你就可以走了。