在自定义控件的中心绘制字符 - Font Awesome Glyph [英] Draw character in center of custom control - Font Awesome Glyph

查看:22
本文介绍了在自定义控件的中心绘制字符 - Font Awesome Glyph的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建自定义用户控件,该控件将在 winforms 按钮内显示 Font Awesome Glyphs.
我找到了具有类似控件的 GitHub 存储库,但我想使用 Button 作为控件的基础.
我可以显示字形,但无法正确对齐:

I'm trying to build custom user control that will display Font Awesome Glyphs inside winforms Button.
I found GitHub repo with similar control, but I would like to use Button as base of my control.
I'm able to show glyph, but I can't align it correctly:

绿色虚线表示按钮大小,蓝色线表示控件中心,红色线表示graphics.MeasureString 返回的矩形.

Green dotted line shows button size, blue lines indicates center of control and red lines show rectangle that graphics.MeasureString is returning.

我的 OnPaint 方法如下所示:

My OnPaint method looks like this:

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

我尝试使用来自这个问题的解决方案,但没有任何运气.

I tried using solution from this question but without any luck.

如何在我的控制中心精确绘制单个字符(字形)(控制中心和字形中心应对齐)

这是我的控件的代码:

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

IconType 枚举:

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

它所需要的只是在资源中包含 fontawesome_webfont.ttf.

All it needs is to include fontawesome_webfont.ttf in resources.

推荐答案

我使用 GraphicsPath 得到了最好的结果:

I've got best result using GraphicsPath:

var path = new GraphicsPath()
path.AddString(_letter, font.FontFamily, (int) font.Style, font.Size, new Point(0, 0), StringFormat.GenericTypographic);
Rectangle area = Rectangle.Round(path.GetBounds());

这篇关于在自定义控件的中心绘制字符 - Font Awesome Glyph的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆