2

i am trying to Override OnPaint in WinForms Button controll. I want to align the Image and Text in the center, next to each other. As i am aware there is no way to do this with the default control. The idea was to inherit from Button, and "override" only the painting of image + text part. I have an almost working version, but if i set "Segoe UI Semibold; 9pt; style=Bold" on my ImgButton and Button, ImgButtons text is a lot more "Bold". Here is my class:

Imports System.Windows.Forms
Imports System.Drawing

Public Class ImgButton
Inherits Button

Public Sub New()
    MyBase.New()
End Sub

Private _text As String = "Text"
Private _img As Bitmap = Nothing

Private isOwnerPainting As Boolean = True

Overrides Property Text As String
    Get
        If isOwnerPainting = True Then
            Return _text
        Else
            Return ""
        End If
    End Get
    Set(value As String)
        _text = value
    End Set
End Property

Property CenteredImage As Bitmap
    Get
        If isOwnerPainting = True Then
            Return _img
        Else
            Return Nothing
        End If
    End Get
    Set(value As Bitmap)
        _img = value
    End Set
End Property

Private _font As Font = MyBase.Font
Overrides Property Font As Font
    Get
        Return _font
    End Get
    Set(value As Font)
        _font = value
    End Set
End Property

Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
    isOwnerPainting = True
    If Me.CenteredImage IsNot Nothing Then
        isOwnerPainting = False
        MyBase.OnPaint(pe)
        isOwnerPainting = True
        Dim textWidth As Integer = pe.Graphics.MeasureString(Me.Text, Me.Font).Width
        Dim textHeight As Integer = pe.Graphics.MeasureString(Me.Text, Me.Font).Height

        Dim imgPlusTextWidth As Integer = Me.CenteredImage.Width + textWidth
        Dim imgPlusTextHeight As Integer = Me.CenteredImage.Height + textHeight

        Dim imageLeft As Integer = (Me.Width / 2) - (imgPlusTextWidth / 2)

        pe.Graphics.DrawImage(Me.CenteredImage, New Point(imageLeft, (Me.Height / 2) - (Me.CenteredImage.Height / 2)))

        pe.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(MyBase.ForeColor), New Point(imageLeft + 5 + Me.CenteredImage.Width, (Me.Height / 2) - (textHeight / 2)))
    Else
        isOwnerPainting = True
        MyBase.OnPaint(pe)
    End If
    isOwnerPainting = True
End Sub

End Class

Thanks for any help.

Edit: Image of the differences: img (can't post img here)

narthir
  • 33
  • 5
  • 1
    If possible, a screenshot of the differences might help. Same font/style looking different can be caused by different AntiAlias/ClearType settings on your Graphics object – hometoast Jan 27 '15 at 18:10
  • Might be the [TextRenderingHint](https://msdn.microsoft.com/en-us/library/system.drawing.graphics.textrenderinghint(v=vs.110).aspx) – the_lotus Jan 27 '15 at 18:20
  • 1
    Use TextRenderer.DrawText instead of DrawString. That's what the button uses. – LarsTech Jan 27 '15 at 18:21
  • TextRenderer.DrawText solved this. Thank you very much. – narthir Jan 27 '15 at 18:26

1 Answers1

2

DrawString has a lot of issues, so it was replaced with the TextRenderer.DrawText method instead:

TextRenderer.DrawText(pe.Graphics, Me.Text, Me.Font, ...
LarsTech
  • 80,625
  • 14
  • 153
  • 225
  • It is only a small part of the problem. His Font property is messed up, it doesn't update InitializeComponent(). Probably because it doesn't set MyBase.Font. So it resets to Microsoft Sans, that's a lot thinner. – Hans Passant Jan 27 '15 at 18:45
  • True. I was searching for some workarounds. Overriding Font property is already removed and I am back to the inherited one. Text property is there to use the MyBase.OnPaint just without painting the text. – narthir Jan 27 '15 at 18:57