带文本的半透明圆形控件 [英] Translucent circular Control with text

查看:26
本文介绍了带文本的半透明圆形控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个项目,我需要添加一个圆形控件,中间有一些文本.
我的问题是圆圈太小,当我调整它的大小时,它与其他控件重叠.我想画一个和正方形一样宽的圆.
除此以外.如何使控件的背景透明?

我正在使用以下代码:

protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);使用 (Bitmap bitmap = new Bitmap(this.Width, this.Height)){使用(图形图形 = Graphics.FromImage(位图)){graphics.SmoothingMode = SmoothingMode.HighQuality;graphics.Clear(this.BackColor);使用 (SolidBrush Brush = new SolidBrush(this._FillColor)){graphics.FillEllipse(brush, 0x18 - 6, 0x18 - 6, (this.Width - 0x30) + 12, (this.Height - 0x30) + 12);}Brush FontColor = new SolidBrush(this.ForeColor);SizeF MS = graphics.MeasureString(Convert.ToString(Convert.ToInt32((100/_Maximum) * _Value)), Font);graphics.DrawString(Convert.ToString(Convert.ToInt32((100/_Maximum) * _Value)), Font, FontColor, Convert.ToInt32((Width/2 - MS.Width/2) + 2), Convert.ToInt32((高度/2 - MS.Height/2) + 3));bitmap.MakeTransparent(this.BackColor);e.Graphics.DrawImage(位图, 0, 0);图形处理();bitmap.Dispose();}}}

解决方案

这是一个从Control派生出来的自定义控件,可以做成半透明的.
界面是一个彩色圆圈,可以包含几个数字.

控件公开这些自定义属性:

Opacity:控件的不透明度BackGround [0, 255]
InnerPadding:内部矩形之间的距离,它定义了圆形边界和控件边界.
FontPadding:Text 与内矩形之间的距离.

获得透明度覆盖

注意和免责声明:

  • 这是一个原型控件,缺少自定义的Designer(这里不能发了,代码太多,还连接了一个框架).
    如此处所示,它可用于完全重叠表单或其他容器中的其他控件.在这个简化的实现中没有处理部分重叠.
  • 字体被硬编码到 Segoe UI,因为这个字体有一个基线,简化了文本在圆形区域中间的位置.
    其他字体有不同的基线,需要更复杂的处理.
    请参阅:带虚线的文本框用于输入基础数学.

使用系统;使用 System.ComponentModel;使用 System.Drawing;使用 System.Drawing.Drawing2D;使用 System.Drawing.Text;使用 System.Globalization;使用 System.Runtime.CompilerServices;使用 System.Windows.Forms;[设计师类别(代码")]类 RoundCenterControl : Control、INotifyPropertyChanged、ISupportInitialize{私有常量 int WS_EX_TRANSPARENT = 0x00000020;私有只读 int internalFontPadding = 10;私有 bool 初始化 = false;私人字体 m_CustomFont = null;私有颜色 m_BackGroundColor;私有 int m_InnerPadding = 0;私有 int m_FontPadding = 20;私人 int m_Opacity = 128;公共事件 PropertyChangedEventHandler PropertyChanged;public RoundCenterControl() =>初始化组件();私有无效 InitializeComponent(){SetStyle(ControlStyles.Opaque |ControlStyles.SupportsTransparentBackColor |ControlStyles.ResizeRedraw, true);SetStyle(ControlStyles.OptimizedDoubleBuffer, false);BackColor = Color.LimeGreen;ForeColor = Color.White;}受保护的覆盖 CreateParams CreateParams {得到 {CreateParams cp = base.CreateParams;cp.ExStyle |= WS_EX_TRANSPARENT;返回cp;}}公共新字体字体{得到 =>m_自定义字体;放 {m_CustomFont = 值;如果(初始化)返回;FontAdapter(m_CustomFont, DeviceDpi);NotifyPropertyChanged();}}公共覆盖字符串文本{得到 =>基地.文本;设置 { base.Text = value;NotifyPropertyChanged();}}公共 int InnerPadding {得到 =>m_InnerPadding;放 {m_InnerPadding = 值;如果(初始化)返回;m_InnerPadding = (int)ValidateRange(value, 0, ClientRectangle.Height - internalFontPadding);NotifyPropertyChanged();}}公共 int FontPadding {得到 =>m_FontPadding;放 {m_FontPadding = 值;如果(初始化)返回;m_FontPadding = (int)ValidateRange(value, internalFontPadding, ClientRectangle.Height - internalFontPadding);FontAdapter(m_CustomFont, DeviceDpi);NotifyPropertyChanged();}}公共诠释不透明度{得到 =>m_不透明度;set { m_Opacity = (int)ValidateRange(value, 0, 255);UpdateBackColor(m_BackGroundColor);NotifyPropertyChanged();}}公共覆盖颜色背景颜色{得到 =>this.m_BackGroundColor;放 {更新背景颜色(值);NotifyPropertyChanged();}}private void NotifyPropertyChanged([CallerMemberName] string PropertyName = null){父?.无效(边界,真);PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));}protected override void OnPaint(PaintEventArgs e){使用 (var format = new StringFormat(StringFormatFlags.LineLimit |StringFormatFlags.NoWrap,CultureInfo.CurrentUICulture.LCID)){format.LineAlignment = StringAlignment.Center;format.Alignment = StringAlignment.Center;e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;使用 (var circleBrush = new SolidBrush(m_BackGroundColor))使用 (var foreBrush = new SolidBrush(ForeColor)){FontAdapter(m_CustomFont, e.Graphics.DpiY);RectangleF rect = InnerRectangle();e.Graphics.FillEllipse(circleBrush, rect);e.Graphics.DrawString(Text, m_CustomFont, foreBrush, rect, format);};};}私有 RectangleF InnerRectangle(){var minMax = GetMinMax(ClientRectangle.Height, ClientRectangle.Width);var size = new SizeF(minMax.min - m_InnerPadding,minMax.min - m_InnerPadding);var position = new PointF((ClientRectangle.Width - size.Width)/2,(ClientRectangle.Height - size.Height)/2);返回新的 RectangleF(位置,大小);}private void FontAdapter(字体字体,浮动 Dpi){RectangleF rect = InnerRectangle();浮动大小 = (rect.Height - m_FontPadding) * (72.0f/Dpi) - internalFontPadding;int fontSize = (int)ValidateRange(size, 6, size);m_CustomFont = new Font(font.FontFamily, fontSize, font.Style, GraphicsUnit.Pixel);}private void UpdateBackColor(颜色颜色){m_BackGroundColor = Color.FromArgb(m_Opacity, Color.FromArgb(color.R, color.G, color.B));base.BackColor = m_BackGroundColor;}私人浮点验证范围(浮点值,浮点最小值,浮点最大值)=>Math.Max(Math.Min(Value, Max), Min);//(值 <最小值) ?最小值:((值 > 最大值)?最大值:值);私人(浮动最小,浮动最大)GetMinMax(浮动值1,浮动值2)=>(Math.Min(value1, value2), Math.Max(value1, value2));public void BeginInit() =>初始化 = 真;公共无效 EndInit(){初始化 = 假;Font = new Font(Segoe UI", 50, FontStyle.Regular, GraphicsUnit.Pixel);FontPadding = m_FontPadding;InnerPadding = m_InnerPadding;}}

I am working on a project wherein I need to add a Control with the shape of a Circle with some text in the middle.
My problem is the circle is too small, when I resize it, it overlaps other controls. I want to draw the circle same width as the square.
Otherwise. how can I make the Control's background transparent?

I am using the code below:

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

    using (Bitmap bitmap = new Bitmap(this.Width, this.Height))
    {
        using (Graphics graphics = Graphics.FromImage(bitmap))
        {
            graphics.SmoothingMode = SmoothingMode.HighQuality;
            graphics.Clear(this.BackColor);

            using (SolidBrush brush = new SolidBrush(this._FillColor))
            {                      
                graphics.FillEllipse(brush, 0x18 - 6, 0x18 - 6, (this.Width - 0x30) + 12, (this.Height - 0x30) + 12);
            }

            Brush FontColor = new SolidBrush(this.ForeColor);
            SizeF MS = graphics.MeasureString(Convert.ToString(Convert.ToInt32((100 / _Maximum) * _Value)), Font);
            graphics.DrawString(Convert.ToString(Convert.ToInt32((100 / _Maximum) * _Value)), Font, FontColor, Convert.ToInt32((Width / 2 - MS.Width / 2) + 2), Convert.ToInt32((Height / 2 - MS.Height / 2) + 3));
            bitmap.MakeTransparent(this.BackColor);
            e.Graphics.DrawImage(bitmap, 0, 0);

            graphics.Dispose();
            bitmap.Dispose();
        }
    }
}

解决方案

This is a Custom Control derived from Control, which can be made translucent.
The interface is a colored circle which can contain a couple of numbers.

The Control exposes these custom properties:

Opacity: The level of opacity of the control BackGround [0, 255]
InnerPadding: The distance between the inner rectangle, which defines the circle bounds and the control bounds.
FontPadding: The distance between the Text and the Inner rectangle.

Transparency is obtained overriding CreateParams, then setting ExStyle |= WS_EX_TRANSPARENT;

The Control.SetStyle() method is used to modify the control behavior, adding these ControlStyles:

ControlStyles.Opaque: prevents the painting of a Control's BackGround, so it's not managed by the System. Combined with CreateParams to set the Control's Extended Style to WS_EX_TRANSPARENT, the Control becomes completely transparent.

ControlStyles.SupportsTransparentBackColor the control accepts Alpha values for it's BackGround color. Without also setting ControlStyles.UserPaint it won't be used to simulate transparency. We're doing that ourselves with other means.


To see it at work, create a new Class file, substitute all the code inside with this code preserving the NameSpace and build the Project/Solution.
The new Custom Control will appear in the ToolBox. Drop it on a Form. Modify its custom properties as needed.

A visual representation of the control:

Note and disclaimer:

  • This is a prototype Control, the custom Designer is missing (cannot post that here, too much code, also connected to a framework).
    As presented here, it can be used to completely overlap other Controls in a Form or other containers. Partial overlapping is not handled in this simplified implementation.
  • The Font is hard-coded to Segoe UI, since this Font has a base-line that simplifies the position of the text in the middle of the circular area.
    Other Fonts have a different base-line, which requires more complex handling.
    See: TextBox with dotted lines for typing for the base math.

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Windows.Forms;

[DesignerCategory("Code")]
class RoundCenterControl : Control, INotifyPropertyChanged, ISupportInitialize
{
    private const int WS_EX_TRANSPARENT = 0x00000020;
    private readonly int internalFontPadding = 10;
    private bool initializing = false;
    private Font m_CustomFont = null;
    private Color m_BackGroundColor;
    private int m_InnerPadding = 0;
    private int m_FontPadding = 20;
    private int m_Opacity = 128;

    public event PropertyChangedEventHandler PropertyChanged;

    public RoundCenterControl() => InitializeComponent();

    private void InitializeComponent()
    {
        SetStyle(ControlStyles.Opaque |
                 ControlStyles.SupportsTransparentBackColor |
                 ControlStyles.ResizeRedraw, true);
        SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
        BackColor = Color.LimeGreen;
        ForeColor = Color.White;
    }

    protected override CreateParams CreateParams {
        get {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= WS_EX_TRANSPARENT;
            return cp;
        }
    }

    public new Font Font
    {
        get => m_CustomFont;
        set {
            m_CustomFont = value;
            if (initializing) return;
            FontAdapter(m_CustomFont, DeviceDpi);
            NotifyPropertyChanged();
        }
    }

    public override string Text {
        get => base.Text;
        set { base.Text = value;
              NotifyPropertyChanged();
        }
    }

    public int InnerPadding {
        get => m_InnerPadding;
        set {
            m_InnerPadding = value;
            if (initializing) return;
            m_InnerPadding = (int)ValidateRange(value, 0, ClientRectangle.Height - internalFontPadding);
            NotifyPropertyChanged();
        }
    }

    public int FontPadding {
        get => m_FontPadding;
        set {
            m_FontPadding = value;
            if (initializing) return;
            m_FontPadding = (int)ValidateRange(value, internalFontPadding, ClientRectangle.Height - internalFontPadding);
            FontAdapter(m_CustomFont, DeviceDpi);
            NotifyPropertyChanged();
        }
    }

    public int Opacity {
        get => m_Opacity;
        set { m_Opacity = (int)ValidateRange(value, 0, 255);
              UpdateBackColor(m_BackGroundColor);
              NotifyPropertyChanged();
        }
    }

    public override Color BackColor {
        get => this.m_BackGroundColor;
        set {
            UpdateBackColor(value);
            NotifyPropertyChanged();
        }
    }

    private void NotifyPropertyChanged([CallerMemberName] string PropertyName = null)
    {
        Parent?.Invalidate(Bounds, true);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
    }


    protected override void OnPaint(PaintEventArgs e)
    {
        using (var format = new StringFormat(
            StringFormatFlags.LineLimit | StringFormatFlags.NoWrap, 
            CultureInfo.CurrentUICulture.LCID))
        {
            format.LineAlignment = StringAlignment.Center;
            format.Alignment = StringAlignment.Center;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;

            using (var circleBrush = new SolidBrush(m_BackGroundColor))
            using (var foreBrush = new SolidBrush(ForeColor))
            {
                FontAdapter(m_CustomFont, e.Graphics.DpiY);
                RectangleF rect = InnerRectangle();
                e.Graphics.FillEllipse(circleBrush, rect);
                e.Graphics.DrawString(Text, m_CustomFont, foreBrush, rect, format);
            };
        };
    }

    private RectangleF InnerRectangle()
    {
        var minMax = GetMinMax(ClientRectangle.Height, ClientRectangle.Width);
        var size = new SizeF(minMax.min - m_InnerPadding,
                             minMax.min - m_InnerPadding);
        var position = new PointF((ClientRectangle.Width - size.Width) / 2,
                                  (ClientRectangle.Height - size.Height) / 2);
        return new RectangleF(position, size);
    }

    private void FontAdapter(Font font, float Dpi)
    {
        RectangleF rect = InnerRectangle();
        float size = (rect.Height - m_FontPadding) * (72.0f / Dpi) - internalFontPadding;
        int fontSize = (int)ValidateRange(size, 6, size);

        m_CustomFont = new Font(font.FontFamily, fontSize, font.Style, GraphicsUnit.Pixel);
    }

    private void UpdateBackColor(Color color)
    {
        m_BackGroundColor = Color.FromArgb(m_Opacity, Color.FromArgb(color.R, color.G, color.B));
        base.BackColor = m_BackGroundColor;
    }

    private float ValidateRange(float Value, float Min, float Max)
        => Math.Max(Math.Min(Value, Max), Min); //(Value < Min) ? Min : ((Value > Max) ? Max : Value);

    private (float min, float max) GetMinMax(float value1, float value2) 
        => (Math.Min(value1, value2), Math.Max(value1, value2));

    public void BeginInit() => initializing = true;

    public void EndInit()
    {
        initializing = false;
        Font = new Font("Segoe UI", 50, FontStyle.Regular, GraphicsUnit.Pixel);
        FontPadding = m_FontPadding;
        InnerPadding = m_InnerPadding;
    }
}

这篇关于带文本的半透明圆形控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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