如何在C#中设置/更改/删除按钮的焦点样式

本文关键字:按钮 删除 焦点 样式 更改 设置 | 更新日期: 2023-09-27 17:48:51

我有几个按钮,我修改了它们的外观。我把它们设置为带背景和自定义边框的平面按钮,这样它们看起来就很漂亮,不再像普通按钮了(实际上,它们现在看起来像Office 2003按钮;-)。按钮的边框为一个像素。

然而,当按钮被选中时(通过点击或按下tab键等键盘动作来获得焦点),按钮周围突然出现了一个相同颜色的额外边框,因此使其成为一个两像素边框。此外,当我禁用一个像素边界时,按钮不会聚焦一个像素的边界。

在网上,这个问题被问得很像"我如何禁用按钮上的焦点",但这不是我想要的:焦点应该仍然存在,只是不像现在那样显示

有什么建议吗?:-)

如何在C#中设置/更改/删除按钮的焦点样式

这就是你想要的效果吗?

public class NoFocusCueButton : Button
{
    protected override bool ShowFocusCues
    {
        get
        {
            return false;
        }
    }
}

你可以像使用普通按钮一样使用这个自定义按钮类,但它不会给你一个额外的矩形焦点。

我也遇到了同样的问题,遇到了这个问题,正在寻找答案。。。

我解决这个问题的方法是将BorderSize设置为0,然后在OnPaint中绘制自己的边界

注意:不是整个按钮,只是边界

一个简单的例子是:

public class CustomButton : Button
{
    public CustomButton()
        : base()
    {
        // Prevent the button from drawing its own border
        FlatAppearance.BorderSize = 0;
        FlatStyle = System.Windows.Forms.FlatStyle.Flat;
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        // Draw Border using color specified in Flat Appearance
        Pen pen = new Pen(FlatAppearance.BorderColor, 1);
        Rectangle rectangle = new Rectangle(0, 0, Size.Width - 1, Size.Height - 1);
        e.Graphics.DrawRectangle(pen, rectangle);
        pen.Dispose();
    }
}

在我的例子中,这就是我如何制作一个模仿ToolStripButton的按钮,其中只有当你悬停在按钮上时,边框才可见:

public class ToolButton : Button
{
    private bool ShowBorder { get; set; }
    public ToolButton()
        : base()
    {
        // Prevent the button from drawing its own border
        FlatAppearance.BorderSize = 0;
        // Set up a blue border and back colors for the button
        FlatAppearance.BorderColor = Color.FromArgb(51, 153, 255);
        FlatAppearance.CheckedBackColor = Color.FromArgb(153, 204, 255);
        FlatAppearance.MouseDownBackColor = Color.FromArgb(153, 204, 255);
        FlatAppearance.MouseOverBackColor = Color.FromArgb(194, 224, 255);
        FlatStyle = System.Windows.Forms.FlatStyle.Flat;
        // Set the size for the button to be the same as a ToolStripButton
        Size = new System.Drawing.Size(23, 22);
    }
    protected override void OnMouseEnter(EventArgs e)
    {
        base.OnMouseEnter(e);
        // Show the border when you hover over the button
        ShowBorder = true;
    }
    protected override void OnMouseLeave(EventArgs e)
    {
        base.OnMouseLeave(e);
        // Hide the border when you leave the button
        ShowBorder = false;
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        // The DesignMode check here causes the border to always draw in the Designer
        // This makes it easier to place your button
        if (DesignMode || ShowBorder)
        {
            Pen pen = new Pen(FlatAppearance.BorderColor, 1);
            Rectangle rectangle = new Rectangle(0, 0, Size.Width - 1, Size.Height - 1);
            e.Graphics.DrawRectangle(pen, rectangle);
            pen.Dispose();
        }
    }

    // Prevent Text from being set on the button (since it will be an icon)
    [Browsable(false)]
    public override string Text { get { return ""; } set { base.Text = ""; } }
    [Browsable(false)]
    public override ContentAlignment TextAlign { get { return base.TextAlign; } set { base.TextAlign = value; } }
}

制作自定义按钮:

public partial class CustomButton: Button
{
    public ButtonPageButton()
    {
        InitializeComponent();
        this.SetStyle(ControlStyles.Selectable, false);
    }
}

这将消除令人讨厌的边界!;-)

另一个选项(尽管有点hacktastic)是将事件处理程序附加到按钮的GotFocus事件。在该事件处理程序中,将值False传递给按钮的NotifyDefault()方法。例如:

void myButton_GotFocus(object sender, EventArgs e)
{
  myButton.NotifyDefault(false);
}

我想这每次都会起作用,但我还没有对它进行广泛的测试。它目前对我有效,所以我对此感到满意。

还有另一种方法可以很好地用于平面样式的按钮。不要使用按钮,而是使用标签。由于您正在完全替换按钮的UI,因此无论您使用按钮控件还是标签都无关紧要。只需以相同的方式处理单击即可。

这对我来说很有效,虽然不是很好的实践,但这是一个很好的破解方法,只要你明显地命名按钮(并评论源代码),其他程序员就会接受这个想法。

Ryan

添加的第二个边框是Windows标准的"默认按钮"边框。您可能已经注意到,如果您在大多数带有多个按钮的对话框(如任何控制面板属性窗口)中进行制表,原始的"双边框"按钮将变为"正常",而对焦按钮则变为"双边框"

这不一定是专注于工作,而是通过按下Enter键来直观地指示所采取的行动。

在我看来,听起来你并不真正关心内部工作。您希望显示器没有两个边界——这完全可以理解。内部工作是解释你为什么会看到这种行为。现在尝试修复它。

我要尝试的第一件事——记住,我还没有验证这一点——就是破解。当按钮获得焦点(从而获得双边框)时,关闭单边框。你可能会得到你想要的效果,而且很简单。(勾入Focus事件。更好的是,将Button子类化并覆盖OnFocus,然后将该子类用于未来的按钮。)

然而,这可能会带来新的、尴尬的视觉副作用。本着这种精神——因为黑客很少是最好的答案——我必须"正式"推荐其他人所说的:自定义绘制按钮。尽管这里的代码可能有些过头了,但CodeProject的这个链接讨论了如何做到这一点(VB链接;您需要翻译)。在完全自定义模式下,您应该能够完全摆脱第二个边界。

当然你可以自己画按钮。其中一面州旗是重点。

因此,在draw事件上,如果标志是焦点,则继续按您喜欢的方式绘制按钮,否则只需将其传递给基本方法。

考虑为按钮实现自己的绘图代码。这样你就可以完全控制。在过去,我实现了自己的控件派生程序,该派生程序自定义绘制我的按钮,并为我的目的实现了所有按钮特性,但您应该能够覆盖按钮的绘制并自己完成,从而控制它在每个状态下的绘制方式,包括聚焦时的绘制方式。

如果您有一个文本框和一个按钮然后在textbox的textchange事件上写入button1.focus();

它会起作用的。

您还可以创建一个不可见的按钮,并在按下另一个按钮时将其激活。

在样式中将FocusVisualStyle依赖属性设置为null,虚线边框将消失。

来自MSDN:控件中焦点的样式和FocusVisualStyle

Windows Presentation Foundation(WPF)为更改的视觉外观控制何时接收键盘集中第一种机制是使用属性的属性设置器as IsKeyboardFocused in the style或应用于控制第二个机制是提供单独的样式作为值FocusVisualStyle属性的;这个"焦点视觉风格"创建装饰器的独立视觉树在控件顶部绘制,而不是更改视觉树控件或其他UI元素的替换它。本主题讨论每个场景机制是适当的。

您看到的额外边框是由FocusVisualStyle定义的,而不是在控件模板中,因此您需要删除或覆盖样式来删除边框。

我运气很好,只是将按钮的Focusable属性设置为false:

<Button HorizontalAlignment="Left" Margin="0,2" 
        Command="{Binding OpenSuspendedJobCommand, Mode=OneWay}"  
        Focusable="False"
        Style="{StaticResource ActionButton}" Content="Open Job..." />