Как установить / изменить / удалить стиль фокуса на кнопке в C #? - PullRequest
23 голосов
/ 29 сентября 2008

У меня есть пара кнопок, которые я изменил, как они выглядят. Я установил их в виде плоских кнопок с фоном и настраиваемой рамкой, чтобы они выглядели красиво и больше не походили на обычные кнопки (на самом деле они теперь выглядят как кнопки Office 2003 ;-). Кнопки имеют границу в один пиксель.

Однако, когда кнопка выбрана (фокусировка осуществляется нажатием кнопки или действия клавиатуры, например нажатия клавиши табуляции), кнопка внезапно получает дополнительную рамку вокруг нее того же цвета, поэтому она становится двухпиксельной рамкой. Более того, когда я отключаю однопиксельную границу, кнопка не получает однопиксельную границу в фокусе.

В сети этот вопрос часто задают, например, «Как отключить фокус на кнопке», но это не то, чего я хочу: фокус все еще должен существовать , просто не отображать как сейчас.

Есть предложения? : -)

Ответы [ 12 ]

37 голосов
/ 29 сентября 2008

Это тот эффект, который вы ищете?

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

Вы можете использовать этот класс пользовательских кнопок, как обычную кнопку, но он не даст вам дополнительный прямоугольник в фокусе.

21 голосов
/ 26 января 2011

У меня была та же проблема с раздражающей двойной рамкой, и я наткнулся на эту тему в поисках ответа ...

Я решил это, установив 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; } }
}
14 голосов
/ 02 декабря 2009

Сделать пользовательскую кнопку:

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

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

Это избавит от этой надоедливой границы! ; -)

6 голосов
/ 11 декабря 2008

Еще один вариант (хотя и немного неприятный) - присоединить обработчик событий к событию GotFocus кнопки. В этом обработчике событий передайте значение False методу NotifyDefault() кнопки. Так, например:

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

Я предполагаю, что это будет работать каждый раз, но я не проверял это подробно. Пока это работает для меня, поэтому я доволен этим.

2 голосов
/ 08 октября 2008

Есть еще один способ, который хорошо работает для кнопок с плоским стилем. Не используйте кнопки, но надписи. Поскольку вы полностью заменяете пользовательский интерфейс кнопки, не имеет значения, используете ли вы элемент управления кнопкой или метку. Просто обработайте щелчок таким же образом.

Это сработало для меня, хотя это не очень хорошая практика, это хороший взлом, и, пока вы явно называете кнопку (и комментируете источник), другие кодировщики поймут идею.

Ryan

1 голос
/ 02 октября 2008

Вторая добавляемая граница - это стандартная граница Windows «кнопка по умолчанию». Возможно, вы заметили, что если вы просматриваете большинство диалоговых окон с несколькими кнопками (например, в любом окне свойств панели управления), исходная «двойная» кнопка становится «нормальной», а кнопка в фокусе становится «двойной рамкой». «

Это не обязательно фокус на работе, а скорее визуальная индикация действия, предпринятого нажатием клавиши Enter.

Для меня это звучит так, как будто тебя не волнует эта внутренняя работа. Вы хотите, чтобы дисплей не имел двух границ - это вполне понятно. Внутренняя работа - объяснить, почему вы видите такое поведение. Теперь ... чтобы попытаться это исправить.

Первое, что я попробую - и имейте в виду, я не проверял это - это взлом. Когда кнопка получает фокус (получая двойную границу), отключите вашу единственную границу. Вы можете получить желаемый эффект, и это довольно просто. (Присоединитесь к событию Focus. Еще лучше, создайте подкласс Button и переопределите OnFocus, а затем используйте этот подкласс для своих будущих кнопок.)

Однако, это может привести к появлению новых, неуклюжих визуальных побочных эффектов. В том же духе - и поскольку хаки редко бывают лучшим ответом - я должен «официально» рекомендовать то, что сказали другие: пользовательская раскраска кнопки. Хотя код здесь может быть излишним, эта ссылка на CodeProject обсуждает, как это сделать (ссылка на VB; вам нужно будет перевести). В полностью настраиваемом режиме вы должны полностью избавиться от этой второй границы.

0 голосов
/ 17 января 2013

Вы также можете создать невидимую кнопку и сделать ее активной при каждом нажатии другой кнопки.

0 голосов
/ 02 декабря 2010

Мне повезло, просто установив для свойства Focusable кнопки значение false:

<Button HorizontalAlignment="Left" Margin="0,2" 
        Command="{Binding OpenSuspendedJobCommand, Mode=OneWay}"  
        Focusable="False"
        Style="{StaticResource ActionButton}" Content="Open Job..." />
0 голосов
/ 15 октября 2009

Если у вас есть текстовое поле и кнопка затем о событии textchange textbox написать button1.focus();

Это будет работать.

0 голосов
/ 18 ноября 2008

Установите для свойства зависимости FocusVisualStyle значение null в вашем стиле, и пунктирная граница исчезнет.

Из MSDN: Стилизация для фокуса в элементах управления и FocusVisualStyle

Windows Presentation Foundation (WPF) обеспечивает два параллельных механизма для изменяя внешний вид контролировать, когда он получает клавиатуру фокус. Первый механизм заключается в использовании установщики свойств для таких свойств как IsKeyboardFocused в пределах стиля или шаблон, который применяется к контроль. Т Второй механизм заключается в предоставить отдельный стиль в качестве значения свойства FocusVisualStyle; «Фокус визуального стиля» создает отдельное визуальное дерево для рекламодателя который рисует сверху элемента управления, вместо изменения визуального дерева элемента управления или другого элемента пользовательского интерфейса заменить его. В этой теме обсуждается сценарии, где каждый из них механизмы соответствующие.

дополнительная граница , которую вы видите, определяется FocusVisualStyle, а не в шаблоне элемента управления, поэтому вам нужно удалить или переопределить стиль, чтобы удалить границу.

...