web-dev-qa-db-fra.com

Comment définir/modifier/supprimer un style de focus sur un bouton en C #?

J'ai quelques boutons dont j'ai modifié l'apparence. Je les ai définis comme des boutons plats avec un arrière-plan et une bordure personnalisée afin qu'ils aient l'air tous jolis et qu'ils ne ressemblent plus à des boutons normaux (en fait, ils ressemblent maintenant aux boutons d'Office 2003 ;-). Les boutons ont une bordure d'un pixel.

Cependant, lorsque le bouton est sélectionné (le focus est obtenu par un clic ou une action au clavier, comme si vous appuyiez sur la touche de tabulation), le bouton devient soudainement entouré d'une bordure supplémentaire de la même couleur, ce qui en fait une bordure de deux pixels. De plus, lorsque je désactive la bordure d'un pixel, le bouton n'obtient pas de bordure d'un pixel.

Sur le net, cette question se pose souvent comme "Comment puis-je désactiver le focus sur un bouton", mais ce n'est pas ce que je veux: le focus doit toujours exister , mais pas afficher comme il le fait à présent.

Aucune suggestion? :-)

22
pbean

Est-ce l'effet que vous recherchez?

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

Vous pouvez utiliser cette classe de boutons personnalisée comme un bouton standard, mais cela ne vous donnera pas un rectangle supplémentaire à la mise au point.

37
Michael L Perry

J'ai eu le même problème avec la double frontière agaçante, et suis tombé sur ce fil à la recherche d'une réponse ...

La façon dont j'ai résolu ce problème a été de régler le BorderSize sur 0 puis de dessiner ma propre frontière dans OnPaint

* Remarque: Pas tout le bouton, seulement la bordure

Un exemple simple serait:

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

Dans mon cas, voici comment j'ai créé un bouton imitant un ToolStripButton, où la bordure n'est visible que lorsque vous survolez le bouton:

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; } }
}
21
Josh Stribling

Faire un bouton personnalisé:

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

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

Ça va se débarrasser de cette frontière agaçante! ;-)

14
Marcus Rex

Une autre option (bien qu'un peu hacktastique) consiste à attacher un gestionnaire d'événements à l'événement GotFocus du bouton. Dans ce gestionnaire d'événements, transmettez une valeur False à la méthode NotifyDefault() du bouton. Donc, par exemple:

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

Je suppose que cela fonctionnera à chaque fois, mais je ne l'ai pas testé de manière approfondie. Cela fonctionne pour moi pour l'instant, donc je suis satisfait de cela.

6
Blake

Il existe une autre méthode qui fonctionne bien pour les boutons plats. N'utilisez pas de boutons mais des étiquettes. Comme vous remplacez complètement l'interface utilisateur du bouton, peu importe si vous utilisez un contrôle de bouton ou une étiquette. Il suffit de gérer le clic de la même manière.

Cela a fonctionné pour moi, même si ce n’est pas très pratique, c’est un bon bidouillage et tant que vous nommez le bouton de façon évidente (et commentez la source), les autres codeurs reprendront l’idée.

Ryan

2
Ryan O'Neill

La deuxième bordure ajoutée est la bordure standard "bouton par défaut" de Windows. Vous avez peut-être remarqué que si vous parcourez la plupart des boîtes de dialogue avec plusieurs boutons (telles que toute fenêtre de propriétés du Panneau de configuration), le bouton "double bordure" d'origine devient "normal" et le bouton de mise au point devient "double-bordure". "

Ce n’est pas forcément le focus au travail, mais plutôt une indication visuelle de l’action entreprise en appuyant sur la touche Entrée. 

Il me semble que vous ne vous souciez pas vraiment de ce travail interne. Vous voulez que l'affichage ne comporte pas deux frontières, ce qui est parfaitement compréhensible. Le fonctionnement interne consiste à expliquer pourquoi vous observez ce comportement. Maintenant ... pour essayer de le réparer.

La première chose que je voudrais essayer - et garder à l'esprit, je n'ai pas validé cela - est un bidouillage. Lorsqu'un bouton reçoit le focus (obtenant ainsi la double bordure), désactivez votre bordure simple. Vous pouvez obtenir l'effet que vous voulez, et c'est assez simple. (Accrochez-vous à l'événement Focus. Encore mieux, sous-classe Button et substituez OnFocus, puis utilisez cette sous-classe pour vos futurs boutons.)

Cependant, cela pourrait introduire de nouveaux effets secondaires visuels maladroits. Dans cette optique, et parce que les hacks sont rarement la meilleure solution, je dois recommander "officiellement" ce que d'autres ont dit: Personnaliser Peignez le bouton. Bien que le code ici soit peut-être excessif, ce lien dans CodeProject explique comment procéder (lien VB; vous aurez besoin de la traduction). En mode personnalisé, vous devriez pouvoir vous débarrasser complètement de cette seconde bordure.

1
John Rudy

Vous pouvez également créer un bouton invisible et le rendre actif chaque fois que vous appuyez sur un autre bouton.

0
Tim Kathete Stadler

Si vous avez une zone de texte et un bouton , L'événement textchange de la zone de texte Write button1.focus();

Ça va marcher.

0
Amit

Vous pouvez certainement dessiner le bouton vous-même. L'un des drapeaux de l'État est ciblé.

Donc, si le drapeau est activé, dessinez le bouton comme bon vous semble, sinon transmettez-le à la méthode de base.

0
Orion Adrian

Pensez à implémenter votre propre code de dessin pour le bouton. De cette façon, vous avez le plein contrôle. Dans le passé, j’ai implémenté mon propre dérivé Control, à savoir que Custom peint mon bouton et applique toutes les caractéristiques du bouton à mes fins, mais vous devriez pouvoir remplacer le dessin du bouton et le faire vous-même, en contrôlant ainsi la manière dont il est dessiné , y compris lorsque ciblé.

0
Jeff Yates

Définissez la propriété FocusVisualStyle dependency sur la valeur null dans votre style et la bordure en pointillés disparaîtra.

De MSDN: Styling for Focus in Controls et FocusVisualStyle

Windows Presentation Foundation (WPF) fournit deux mécanismes parallèles pour changer l'apparence visuelle d'un contrôler quand il reçoit le clavier concentrer. Le premier mécanisme consiste à utiliser les maîtres d'ouvrage pour des propriétés telles comme IsKeyboardFocused dans le style ou un modèle qui est appliqué au contrôle. Tle deuxième mécanisme consiste à fournissez un style séparé en tant que valeur de la propriété FocusVisualStyle; la "style visuel de focus" crée un arbre visuel séparé pour un adorateur qui s’appuie sur le contrôle, plutôt que de changer l'arborescence visuelle du contrôle ou autre élément de l'interface utilisateur par le remplacer. Ce sujet traite du scénarios où chacun de ceux-ci mécanismes est approprié.

La bordure supplémentaire que vous voyez est définie par FocusVisualStyle et non dans le modèle de contrôle. Vous devez donc supprimer ou remplacer le style pour supprimer la bordure.

0
Pop Catalin