Уменьшить отступ вокруг текста в кнопке WinForms - PullRequest
12 голосов
/ 24 мая 2011

У меня есть приложение, которое будет использоваться в системе с сенсорным экраном, и оно содержит несколько довольно больших кнопок (квадрат ~ 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.

Ответы [ 5 ]

7 голосов
/ 30 мая 2013

Вам не нужно рисовать всю кнопку самостоятельно.Просто оставьте свойство 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);
        }
    }
}
6 голосов
/ 24 мая 2011

Вы также просто переопределяете метод 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));
        }
    }
4 голосов
/ 24 мая 2011

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

fireplay image

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

2 голосов
/ 26 мая 2017

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

Смотрите мое предложение ниже. Я переопределяю свойство Text, чтобы иметь возможность использовать его закрытую часть _Text и прикрепить String.Empty непосредственно перед событием MyBase.OnPaint(e). Это делает эту кнопку рисовать без текста. Позже я переназначаю старый текст в частную собственность и сам рисую строку. Я добавляю Inflate к 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

C # версия:

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

    }

}
0 голосов
/ 07 июня 2019

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

По крайней мере, одним из недостатков этого подхода является кажущийся размер шрифта, который, как мне кажется, изменился (в моем случае уменьшился).: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.label.usecompatibletextrendering?view=netframework-4.8

...