Reduce Padding Around Text in WinForms Button

荒凉一梦 提交于 2019-11-30 12:38:01

You also simply override the OnPaint() method of the Button control from which you're inheriting, and omit to call base.OnPaint(), and replace it with your own draw code.

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

You don't have to draw the whole button yourself. Just leave Text property empty and assign your text to 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);
        }
    }
}

I have created a successful radio automation application back then in '98 using MFC. First thing we did is that we created whole new set of GUI controls for it, since for example, pressing the button on the screen with the finger obscures it, and standard buttons aren't so fancy for it.

My advice would be not to go with deriving your button from standard WinForms button, but from the Control and do the drawing yourself. If it is the simple button like one you presented, you won't have much to do, just DrawString, and if it is somewhat more complicated, you'll have complete control over it.

yarecky

@Bryan - both solutions proposed by @Henk Roux and @chiper are not perfect. First generate button without any visual attributes and second forces us to add new attribute like OwnerDrawText.

See my proposition below. I override Text property to be able to use its private part _Text and attach String.Empty just before MyBase.OnPaint(e) event. This makes that button is draw without text. Later on I reassign back old text to the private property and draw string myself. I add Inflate to Rectangle to make text nicer just touching border of button, not overlapping it. My proposition works with any flatstyle.

Here is comparison of standard and no padding button in two flatstyles: standard and flat

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# version:

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

    }

}

On compatible WinForms controls you can also try setting the UseCompatibleTextRendering property to true. It uses the Graphics class instead of the default TextRenderer class for text rendering. While it worked for my specific application, your mileage may vary.

At least one con to this approach is the apparent font size seemed to change (reduced in my case).

Learn more here: https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.label.usecompatibletextrendering?view=netframework-4.8

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!