繁体   English   中英

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

[英]Flat Button Style - Hide border and Focus Cue when the Button is active

我创建了一个带有透明边框的平面按钮,还设置FlatAppearance.BorderSize = 0
边框在鼠标单击时隐藏,并且按钮背景在按下鼠标按钮时使用自定义颜色。

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

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

有问题的图片

表单设计器中的 Button 属性:

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

 

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

▶ 标准 Focus Cue 渲染被禁用,覆盖Control.ShowFocusCues以始终返回false (除非尚未创建句柄)。

NotifyDefault方法也被覆盖,以避免在使用 Button 打开变为活动的 Windows 时出现类似的效果:在这种情况下,Button 被呈现为带有边框的视觉线索,表明它是该窗口的 ActiveControl。

▶ 使用自定义ControlDesigner从 PropertyGrid 中删除了一些定义 Button化的属性,以避免对特定定义属性进行不必要的篡改。

最后,在自定义控件的 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() {
        Cursor = Cursors.Hand;
        Image = new Bitmap(Properties.Resources.[SomeImage]);
        FlatAppearance.BorderSize = 0;
        FlatAppearance.MouseDownBackColor = Color.SteelBlue;
        FlatAppearance.MouseOverBackColor = Color.Transparent;
        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) {
            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);
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM