30

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

但是,当按钮被选中时(通过单击或键盘操作(如按 Tab 键)获得焦点),按钮会突然出现相同颜色的额外边框,因此使其成为两个像素的边框。此外,当我禁用一像素边框时,按钮不会获​​得一像素边框焦点。

在网上,这个问题很像“如何禁用按钮上的焦点”,但这不是我想要的:焦点应该仍然存在,只是不以现在的方式显示

有什么建议么?:-)

4

12 回答 12

44

这就是你想要的效果吗?

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

您可以像使用常规按钮一样使用此自定义按钮类,但它不会为您提供额外的焦点矩形。

于 2008-09-29T14:16:01.347 回答
23

我对烦人的双边框也有同样的问题,偶然发现了这个线程寻找答案......

我解决这个问题的方法是将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);
    }
}

就我而言,这就是我制作一个模仿 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);
        }
    }



    // 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; } }
}
于 2011-01-25T21:08:24.730 回答
19

制作一个自定义按钮:

public partial class CustomButton: Button
{
    public ButtonPageButton()
    {
        InitializeComponent();

        this.SetStyle(ControlStyles.Selectable, false);
    }
}

那将摆脱那个烦人的边界!;-)

于 2009-12-02T11:55:57.927 回答
6

另一种选择(虽然有点 hacktastic)是将事件处理程序附加到按钮的 GotFocus 事件。在该事件处理程序中,将 False 值传递给按钮的NotifyDefault()方法。因此,例如:

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

我假设这每次都会起作用,但我还没有对它进行广泛的测试。它现在对我有用,所以我对此感到满意。

于 2008-12-11T20:55:05.037 回答
2

还有另一种适用于平面样式按钮的方法。不要使用按钮,而是使用标签。当您完全替换按钮的 UI 时,使用按钮控件还是标签并不重要。只需以相同的方式处理点击。

这对我有用,虽然不是很好的做法,但它是一个很好的技巧,只要你清楚地命名按钮(并评论源)其他编码人员就会接受这个想法。

瑞安

于 2008-10-08T17:32:54.533 回答
1

添加的第二个边框是 Windows 标准的“默认按钮”边框。您可能已经注意到,如果您在大多数带有多个按钮的对话框(例如任何控制面板属性窗口)中切换,原来的“双边框”按钮变成“正常”,而焦点按钮变成“双边框”。 "

这不一定是工作重点,而是按 Enter 键所采取的行动的视觉指示。

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

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

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

于 2008-10-01T21:31:51.033 回答
0

当然,您可以自己绘制按钮。州旗之一是集中的。

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

于 2008-09-29T14:01:46.077 回答
0

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

于 2008-09-29T14:05:36.473 回答
0

如果你有一个文本框和一个按钮,那么在文本框的 textchange 事件上写button1.focus();

它会起作用的。

于 2009-10-15T04:47:49.253 回答
0

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

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

Windows Presentation Foundation (WPF) 提供了两种并行机制,用于在控件接收到键盘焦点时更改控件的视觉外观。第一种机制是对应用于控件的样式或模板中的 IsKeyboardFocused 等属性使用属性设置器。第二种机制是提供一个单独的样式作为 FocusVisualStyle 属性的值;“焦点视觉样式”为在控件顶部绘制的装饰器创建单独的视觉树, 而不是通过替换来更改控件或其他 UI 元素的视觉树。本主题讨论其中每种机制都适用的场景。

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

于 2008-11-18T12:56:43.247 回答
0

您还可以创建一个不可见的按钮,并在您按下另一个按钮时使其处于活动状态。

于 2013-01-17T15:11:44.657 回答
-4

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

<Button HorizontalAlignment="Left" Margin="0,2" 
        Command="{Binding OpenSuspendedJobCommand, Mode=OneWay}"  
        Focusable="False"
        Style="{StaticResource ActionButton}" Content="Open Job..." />
于 2010-12-02T20:40:03.350 回答