Уменьшить отступы вокруг текста в кнопке WinForms

У меня есть приложение, которое будет использоваться в сенсорной системе, и оно содержит несколько кнопок, которые довольно велики (~ 100 пикселей).

Каждая кнопка будет иметь от 1 до 4 строк текста (обычно одно слово в строке).

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

Я попытался уменьшить заполнение элемента управления до нуля следующим образом, но это не помогает.

this.Text = _label;
this.Font = new Font(this.Font.FontFamily, (float) _size);
this.Padding = new Padding(0);

Ниже приведен пример проблемы:

Button with broken text

Как вы можете видеть, есть много места для слова "ОБЗОР", чтобы соответствовать одной строке, но как я могу достичь этого, не уменьшая размер шрифта? Мне не нравится мысль переписать код текстовой картины управления.

Изменить: я заметил, что увеличение отступов до различных значений до 300, не влияет на внутреннее заполнение элемента управления. Также для информации кнопка, которую я использую, - это элемент управления, который я унаследовал от класса Windows.Forms.Button, поскольку мне нужно добавить несколько свойств, однако я не вмешивался ни в один из собственных методов Button.

Ответ 1

Вы также просто переопределяете метод OnPaint() элемента управления Button, из которого вы наследуете, и опускаете вызов base.OnPaint() и заменяете его собственным кодом рисования.

    protected override void OnPaint(PaintEventArgs pevent)
    {
        //omit base.OnPaint completely...

        //base.OnPaint(pevent); 

        using (Pen p = new Pen(BackColor))
        {
            pevent.Graphics.FillRectangle(p.Brush, ClientRectangle);
        }

        //add code here to draw borders...

        using (Pen p = new Pen(ForeColor))
        {
            pevent.Graphics.DrawString("Hello World!", Font, p.Brush, new PointF(0, 0));
        }
    }

Ответ 2

Вам не нужно рисовать всю кнопку самостоятельно. Просто оставьте свойство Text пустым и присвойте свой текст OwnerDrawText

public class NoPaddingButton : Button
{
    private string ownerDrawText;
    public string OwnerDrawText
    {
        get { return ownerDrawText; }
        set { ownerDrawText = value; Invalidate(); }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        if (string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(ownerDrawText))
        {
            StringFormat stringFormat = new StringFormat();
            stringFormat.Alignment = StringAlignment.Center;
            stringFormat.LineAlignment = StringAlignment.Center;

            e.Graphics.DrawString(ownerDrawText, Font, new SolidBrush(ForeColor), ClientRectangle, stringFormat);
        }
    }
}

Ответ 3

Я создал успешное приложение для автоматизации радио, а затем в '98, используя MFC. Первое, что мы сделали, это то, что мы создали для него целый новый набор элементов управления графическим интерфейсом, поскольку, например, нажатие кнопки на экране с помощью пальца затушевывает его, а стандартные кнопки для него не столь приятны.

fireplay image

Мой совет заключался бы не в том, чтобы вывести вашу кнопку из стандартной кнопки WinForms, а из Control и сделать чертеж самостоятельно. Если это простая кнопка, как вы представили, вам нечего делать, просто DrawString, и если она несколько сложнее, вы получите полный контроль над ней.

Ответ 4

@Bryan - оба решения, предложенные @Henk Roux и @chiper, не идеальны. Первая кнопка генерируется без каких-либо визуальных атрибутов, а вторая заставляет нас добавить новый атрибут, такой как OwnerDrawText.

Смотрите мое предложение ниже. Я переопределяю свойство Text чтобы иметь возможность использовать его закрытую часть _Text и прикрепить String.Empty непосредственно перед MyBase.OnPaint(e). Это делает эту кнопку рисовать без текста. Позже я переназначаю старый текст в частную собственность и сам рисую строку. Я добавляю Inflate to Rectangle чтобы сделать текст более приятным, просто касаясь границы кнопки, не перекрывая ее. Мое предложение работает с любым flatstyle.

Вот сравнение стандартной кнопки без кнопки в двух плоских стилях: стандартная и плоская

Imports System.ComponentModel
Imports System.Drawing
Imports System.Windows.Forms

Public Class ButtonNoPadding
    Inherits Button

    Private _textCurrent As String
    Private _Text As String

    <Category("Appearance")>
    Public Overrides Property Text() As String
        Get
            Return _Text
        End Get
        Set(ByVal value As String)
            If value <> _Text Then
                _Text = value
                Invalidate()
            End If
        End Set
    End Property

    Protected Overrides Sub OnPaint(e As PaintEventArgs)

        _textCurrent = Text
        _Text = String.Empty
        MyBase.OnPaint(e)
        _Text = _textCurrent

        Using brush = New SolidBrush(ForeColor)
            Using stringFormat = New StringFormat() With {.Alignment = StringAlignment.Center, .LineAlignment = StringAlignment.Center}
                e.Graphics.DrawString(Text, Font, brush, Rectangle.Inflate(ClientRectangle, -2, -2), stringFormat)
            End Using
        End Using

    End Sub

End Class

С# версия:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

public class ButtonNoPadding : Button
{

    private string _textCurrent;

    private string _Text;
    [Category("Appearance")]
    public override string Text {
        get { return _Text; }
        set {
            if (value != _Text) {
                _Text = value;
                Invalidate();
            }
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        _textCurrent = Text;
        _Text = string.Empty;
        base.OnPaint(e);
        _Text = _textCurrent;

        using (var brush = new SolidBrush(ForeColor)) {
            using (var stringFormat = new StringFormat {Alignment = StringAlignment.Center,LineAlignment = StringAlignment.Center}) {
                e.Graphics.DrawString(Text, Font, brush, Rectangle.Inflate(ClientRectangle, -2, -2), stringFormat);
            }
        }

    }

}

Ответ 5

На совместимых элементах управления WinForms вы также можете попробовать установить для свойства UseCompatibleTextRendering значение true. Он использует класс Graphics вместо класса TextRenderer по умолчанию для визуализации текста. Хотя это работает для моего конкретного приложения, ваш пробег может отличаться.

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

Узнайте больше здесь: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.label.usecompatibletextrendering?view=netframework-4.8