How to set/change/remove focus style on a Button i

2019-01-06 15:54发布

I have a couple of buttons of which I modified how they look. I have set them as flat buttons with a background and a custom border so they look all pretty and nothing like normal buttons anymore (actually, they look like Office 2003 buttons now ;-). The buttons have a border of one pixel.

However when the button gets selected (gets the focus through either a click or a keyboard action like pressing the tab key) the button suddenly gets and extra border around it of the same colour, so making it a two pixel border. Moreover when I disable the one pixel border, the button does not get a one pixel border on focus.

On the net this question is asked a lot like 'How can I disable focus on a Button', but that's not what I want: the focus should still exist, just not display in the way it does now.

Any suggestions? :-)

12条回答
爷的心禁止访问
2楼-- · 2019-01-06 16:16

I had the same issue with the annoying double border, and stumbled across this thread looking for an answer...

The way I solved this was to set the BorderSize to 0 then draw my own border in OnPaint

*Note: Not the entire button, just the border

A simple example would be:

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

In my case, this is how I made a button that mimics a ToolStripButton, where the border is only visible when you hover over the button:

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; } }
}
查看更多
一夜七次
3楼-- · 2019-01-06 16:16

Consider implementing your own drawing code for the button. That way you have full control. In the past, I've implemented my own Control derivative that custom paints my button and implements all the button characteristics for my purposes, but you should be able to override the button's painting and do it yourself, thereby controlling how it draws in every state, including when focused.

查看更多
你好瞎i
4楼-- · 2019-01-06 16:18

I've had good luck merely setting the Focusable property of the button to be false:

<Button HorizontalAlignment="Left" Margin="0,2" 
        Command="{Binding OpenSuspendedJobCommand, Mode=OneWay}"  
        Focusable="False"
        Style="{StaticResource ActionButton}" Content="Open Job..." />
查看更多
甜甜的少女心
5楼-- · 2019-01-06 16:20

Certainly you can draw the button yourself. One of the state flags is focused.

So on the draw event if the flag is focused go ahead and draw the button how you like, otherwise just pass it on to the base method.

查看更多
姐就是有狂的资本
6楼-- · 2019-01-06 16:20

Set the FocusVisualStyle dependency property to null in your style, and the dotted border will be gone.

From MSDN: Styling for Focus in Controls, and FocusVisualStyle

Windows Presentation Foundation (WPF) provides two parallel mechanisms for changing the visual appearance of a control when it receives keyboard focus. The first mechanism is to use property setters for properties such as IsKeyboardFocused within the style or template that is applied to the control. The second mechanism is to provide a separate style as the value of the FocusVisualStyle property; the "focus visual style" creates a separate visual tree for an adorner that draws on top of the control, rather than changing the visual tree of the control or other UI element by replacing it. This topic discusses the scenarios where each of these mechanisms is appropriate.

The extra border you see is defined by the FocusVisualStyle and not in the control template, so you need to remove or override the style to remove the border.

查看更多
啃猪蹄的小仙女
7楼-- · 2019-01-06 16:21

Make a custom button:

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

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

That'll get rid of that annoying border! ;-)

查看更多
登录 后发表回答