Draw Charakter in der Mitte der benutzerdefinierten Steuerung - Font Awesome Glyph

Ich versuche, eine benutzerdefinierte Benutzersteuerung zu erstellen, mit der Font Awesome Glyphs in winforms Button angezeigt werden.
Ich fand GitHub Repo mit ähnlicher Steuerung, aber ich möchte Button als Basis für meine Steuerung verwenden.
Ich kann Glyphen anzeigen, aber ich kann sie nicht richtig ausrichten:

Grüne gepunktete Linie zeigt die Tastengröße an, blaue Linien zeigen die Mitte der Steuerung an und rote Linien zeigen das Rechteck, dasgraphics.MeasureString kehrt zurück.

MyOnPaint Methode sieht so aus:

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

        var graphics = e.Graphics;
        // Set best quality
        graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
        graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;

        if(!DesignMode)
        {
            graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            graphics.SmoothingMode = SmoothingMode.HighQuality;
        }

        var letter = char.ConvertFromUtf32((int)_icon);

        Brush b;
        if (!Enabled)
        {
            b = Brushes.LightGray;
        }
        else if (_mouseDown)
        {
            b = new SolidBrush(_clickColor);
        }
        else if (_mouseOver)
        {
            b = new SolidBrush(_hoverColor);
        }
        else
        {
            b = new SolidBrush(ForeColor);
        }

        SizeF s = graphics.MeasureString(letter, new Font(Fonts.Families[0], _iconSize, GraphicsUnit.Point), Width);

        float w = s.Width;
        float h = s.Height;

        // center icon
        float left = Padding.Left + (Width - w)/2;
        float top = Padding.Top + (Height - h)/2;

        if (DesignMode)
        {
            graphics.DrawRectangle(Pens.Red, top, left, w, h);
        }

        graphics.DrawString(letter, new Font(Fonts.Families[0], _iconSize, GraphicsUnit.Point), b, new PointF(left, top));

        if (DesignMode)
        {
            var pen = new Pen(_hoverColor, 1) { DashStyle = DashStyle.Dash, Alignment = PenAlignment.Inset };
            graphics.DrawRectangle(pen, Padding.Left, Padding.Top, Width - Padding.Left - Padding.Right - 1, Height - Padding.Top - Padding.Bottom - 1);
            graphics.DrawLine(Pens.Blue, Padding.Left, Padding.Top, Width - Padding.Left, Height - Padding.Top);
            graphics.DrawLine(Pens.Blue, Width - Padding.Left, Padding.Top, Padding.Left, Height - Padding.Top);
        }
    }

Ich habe versucht, die Lösung von @ zu verwendediese Frag aber ohne glück.

Wie kann ich ein einzelnes Zeichen (Glyphe) in der exakten Mitte meines Steuerelements zeichnen (Steuerelementmitte und Glyphenmitte sollten übereinstimmen)?

Hier ist der Code für meine Kontrolle:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MyControls
{
    class FontButton:Button
    {
        #region Public

        public FontButton()
        {
            base.FlatStyle = FlatStyle.Flat;
            base.FlatAppearance.BorderSize = 0;
            base.FlatAppearance.MouseOverBackColor = Color.Transparent;
            base.FlatAppearance.MouseDownBackColor = Color.Transparent;
            base.Text = "";
            base.MinimumSize = new Size(32,32);
            Size = new Size(32,32);

            _hoverColor = Color.FromArgb(144, 188, 0);
            _clickColor = Color.Green;
            _icon=IconType.Android;
            _iconSize = 40;
        }

        private int _iconSize;

        [DefaultValue(typeof(int), "40"), Category("Appearance"), Description("Icon size in points")]
        public int IconSize
        {
            get { return _iconSize; }
            set
            {
                _iconSize = value;
                Invalidate();
            }
        }


        private Color _hoverColor;

        [DefaultValue(typeof(Color), "144, 188, 0"), Category("Appearance"), Description("Color when mouse over")]
        public Color HoverColor
        {
            get { return _hoverColor; }
            set
            {
                _hoverColor = value;
                Invalidate();
            }
        }

        private Color _clickColor;

        [DefaultValue(typeof(Color), "Green"), Category("Appearance"), Description("Color when mouse click")]
        public Color ClickColor
        {
            get { return _clickColor; }
            set
            {
                _clickColor = value;
                Invalidate();
            }
        }

        private IconType _icon;

        [DefaultValue(typeof(IconType), "Android"), Category("Appearance"), Description("Icon")]
        public IconType Icon
        {
            get { return _icon; }
            set
            {
                _icon = value;
                Invalidate();
            }
        }

        #endregion

        #region Static

        static FontButton()
        {
            InitialiseFont();
        }

        #region NATIVE

        [DllImport("gdi32.dll")]
        private static extern IntPtr AddFontMemResourceEx(byte[] pbFont, int cbFont, IntPtr pdv, out uint pcFonts);

        #endregion

        private static readonly PrivateFontCollection Fonts = new PrivateFontCollection();

        private static void InitialiseFont()
        {
            try
            {
                byte[] fontdata = ImageButtonTest.Properties.Resources.fontawesome_webfont;
                IntPtr ptrFont = Marshal.AllocCoTaskMem(fontdata.Length);
                uint cFonts;
                AddFontMemResourceEx(fontdata, fontdata.Length, IntPtr.Zero, out cFonts);
                Marshal.Copy(fontdata, 0, ptrFont, fontdata.Length);
                Fonts.AddMemoryFont(ptrFont, fontdata.Length);
                Marshal.FreeCoTaskMem(ptrFont);
            }
            catch (Exception)
            {
                Debug.WriteLine("Error");
                throw;
            }
        }

        #endregion

        #region Overrides

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

            var graphics = e.Graphics;
            // Set best quality
            graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
            graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;


            if(!DesignMode)
            {
                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
                graphics.SmoothingMode = SmoothingMode.HighQuality;
            }

            var letter = char.ConvertFromUtf32((int)_icon);//char.ConvertFromUtf32(0xf190);

            Brush b;
            if (!Enabled)
            {
                b = Brushes.LightGray;
            }
            else if (_mouseDown)
            {
                b = new SolidBrush(_clickColor);
            }
            else if (_mouseOver)
            {
                b = new SolidBrush(_hoverColor);
            }
            else
            {
        ,        b = new SolidBrush(ForeColor);
            }

            SizeF s = graphics.MeasureString(letter, new Font(Fonts.Families[0], _iconSize, GraphicsUnit.Point), Width);

            //SizeF s = TextRenderer.MeasureText(letter, new Font(Fonts.Families[0], _iconSize, GraphicsUnit.Point), new Size(20, 20), TextFormatFlags.NoPadding);

            //Debug.WriteLine(stringSize);
            //Debug.WriteLine(s);

            float w = s.Width;
            float h = s.Height;

            // center icon
            float left = Padding.Left + (Width - w)/2;
            float top = Padding.Top + (Height - h)/2;

            if (DesignMode)
            {
                graphics.DrawRectangle(Pens.Red, top, left, w, h);
            }

            graphics.DrawString(letter, new Font(Fonts.Families[0], _iconSize, GraphicsUnit.Point), b, new PointF(left, top));

            if (DesignMode)//Process.GetCurrentProcess().ProcessName == "devenv")
            {
                var pen = new Pen(_hoverColor, 1) { DashStyle = DashStyle.Dash, Alignment = PenAlignment.Inset };
                graphics.DrawRectangle(pen, Padding.Left, Padding.Top, Width - Padding.Left - Padding.Right - 1, Height - Padding.Top - Padding.Bottom - 1);
                graphics.DrawLine(Pens.Blue, Padding.Left, Padding.Top, Width - Padding.Left, Height - Padding.Top);
                graphics.DrawLine(Pens.Blue, Width - Padding.Left, Padding.Top, Padding.Left, Height - Padding.Top);
            }
        }

        private bool _mouseOver;

        protected override void OnMouseEnter(EventArgs e)
        {
            _mouseOver = true;
            base.OnMouseEnter(e);

        }

        protected override void OnMouseLeave(EventArgs e)
        {
            _mouseOver = false;
            base.OnMouseLeave(e);
        }

        private bool _mouseDown;

        protected override void OnMouseDown(MouseEventArgs e)
        {
            _mouseDown = true;
            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            _mouseDown = false;
            base.OnMouseUp(e);
        }


        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new FlatStyle FlatStyle { get; set; }

        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new FlatButtonAppearance FlatAppearance { get; set; }

        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new string Text { get; set; }

        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Size MinimumSize { get; set; }

        #endregion
    }
}

undIconType enum:

namespace MyControls
{
    public enum IconType
    {
        Adjust = 0xf042,
        Adn = 0xf170,
        AlignCenter = 0xf037,
        AlignJustify = 0xf039,
        AlignLeft = 0xf036,
        AlignRight = 0xf038,
        Ambulance = 0xf0f9,
        Anchor = 0xf13d,
        Android = 0xf17b,
        ArrowCircleDown = 0xf0ab,
        ArrowCircleLeft = 0xf0a8,
        ArrowCircleODown = 0xf01a,
        ArrowCircleOLeft = 0xf190,
        ArrowCircleORight = 0xf18e,
        ArrowCircleOUp = 0xf01b,
        ArrowCircleRight = 0xf0a9,
        ArrowCircleUp = 0xf0aa,
        ArrowDown = 0xf063,
        ArrowLeft = 0xf060,
        ArrowRight = 0xf061,
        ArrowUp = 0xf062,
        Arrows = 0xf047,
        ArrowsAlt = 0xf0b2,
        ArrowsH = 0xf07e,
        ArrowsV = 0xf07d,
        User = 0xf007,
        UserMd = 0xf0f0,
        Users = 0xf0c0,
        Stop = 0xf04d
    }
}

Es muss lediglich fontawesome_webfont.ttf in die Ressourcen aufgenommen werden.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage