首页 / 财经 / 股票 / 正文

gditransparentblt(C# WinForms 自定义圆形图片控件实现详解)

放大字体  缩小字体 来源:名牌女装 2026-04-17 17:28  浏览次数:3

在Windows窗体应用程序开发中,我们经常需要展示圆形的图片,比如用户头像等。本文将详细介绍如何通过继承PictureBox控件,使用GDI+技术来实现一个支持渐变边框的圆形图片控件。

控件特性

  • 支持圆形显示图片
  • 可自定义边框粗细
  • 支持双色渐变边框
  • 可调整渐变角度
  • 支持多种边框线型
  • 具有抗锯齿效果

完整代码实现

using System;using System.Collections.Generic;using System.Drawing.Drawing2D;using System.Linq;using System.Text;using System.Threading.Tasks;namespace AppControls{    public class CircularPictureBox : PictureBox    {        private int borderSize = 2;        private Color borderColor = Color.RoyalBlue;        private Color borderColor2 = Color.HotPink;        private DashStyle borderLineStyle = DashStyle.Solid;        private DashCap borderCapStyle = DashCap.Flat;        private float gradientAngle = 50F;        public CircularPictureBox()        {            this.Size = new Size(100, 100);            this.SizeMode = PictureBoxSizeMode.StretchImage;            this.BackColor = Color.Transparent;        }        // 优化双缓冲设置          protected override void onHandleCreated(EventArgs e)        {            base.onHandleCreated(e);            this.SetStyle(ControlStyles.AllPaintingInWmPaint |                         ControlStyles.UserPaint |                         ControlStyles.OptimizedDoubleBuffer |                         ControlStyles.ResizeRedraw, true);        }        public int BorderSize        {            get            {                return borderSize;            }            set            {                borderSize = value;                this.Invalidate();            }        }        public Color BorderColor        {            get            {                return borderColor;            }            set            {                borderColor = value;                this.Invalidate();            }        }        public Color BorderColor2        {            get            {                return borderColor2;            }            set            {                borderColor2 = value;                this.Invalidate();            }        }        public DashStyle BorderLineStyle        {            get            {                return borderLineStyle;            }            set            {                borderLineStyle = value;                this.Invalidate();            }        }        public DashCap BorderCapStyle        {            get            {                return borderCapStyle;            }            set            {                borderCapStyle = value;                this.Invalidate();            }        }        public float GradientAngle        {            get            {                return gradientAngle;            }            set            {                gradientAngle = value;                this.Invalidate();            }        }        protected override void onResize(EventArgs e)        {            base.onResize(e);            this.Size = new Size(this.Width, this.Height);        }        protected override void onPaint(PaintEventArgs pe)        {            base.onPaint(pe);            Rectangle rectSurface = this.ClientRectangle;            Rectangle rectBorder = Rectangle.Inflate(rectSurface, -borderSize, -borderSize);            int smoothSize = 2;            if (borderSize > 0)                smoothSize = borderSize;            using (GraphicsPath pathSurface = GetCirclePath(rectSurface))            using (GraphicsPath pathBorder = GetCirclePath(rectBorder))            using (Pen penSurface = new Pen(this.Parent.BackColor, smoothSize))            {                // 设置绘图品质                  pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;                // 设置区域                  this.Region = new Region(pathSurface);                // 绘制图片                  if (this.Image != null)                {                    using (TextureBrush textureBrush = new TextureBrush(this.Image))                    {                        textureBrush.WrapMode = WrapMode.Clamp;                        // 配置图片缩放                          Matrix matrix = new Matrix();                        if (this.SizeMode == PictureBoxSizeMode.Zoom)                        {                            float scale = Math.Min((float)this.Width / this.Image.Width,                                                 (float)this.Height / this.Image.Height);                            float x = (this.Width - (this.Image.Width * scale)) / 2;                            float y = (this.Height - (this.Image.Height * scale)) / 2;                            matrix.Translate(x, y);                            matrix.Scale(scale, scale);                        }                        else                        {                            matrix.Scale((float)this.Width / this.Image.Width,                                       (float)this.Height / this.Image.Height);                        }                        textureBrush.Transform = matrix;                        pe.Graphics.FillPath(textureBrush, pathSurface);                    }                }                // 绘制表面边缘                  pe.Graphics.DrawPath(penSurface, pathSurface);                // 绘制边框                  if (borderSize >= 1)                {                    using (LinearGradientBrush borderGColor = new LinearGradientBrush(                        rectBorder, borderColor, borderColor2, gradientAngle))                    using (Pen penBorder = new Pen(borderGColor, borderSize))                    {                        penBorder.DashStyle = borderLineStyle;                        penBorder.DashCap = borderCapStyle;                        penBorder.Alignment = PenAlignment.Center;                        pe.Graphics.DrawPath(penBorder, pathBorder);                    }                }            }        }        private GraphicsPath GetCirclePath(Rectangle rect)        {            GraphicsPath path = new GraphicsPath();            path.AddEllipse(rect);            return path;        }    }}
C# WinForms 自定义圆形图片控件实现详解nerror="javascript:errorimg.call(this);">

增加悬停动画

using System;using System.Collections.Generic;using System.Drawing.Drawing2D;using System.Linq;using System.Text;using System.Threading.Tasks;namespace AppControls{    public class CircularPictureBox : PictureBox    {        private int borderSize = 2;        private Color borderColor = Color.RoyalBlue;        private Color borderColor2 = Color.HotPink;        private DashStyle borderLineStyle = DashStyle.Solid;        private DashCap borderCapStyle = DashCap.Flat;        private float gradientAngle = 50F;        // 添加动画相关字段          private bool isHovered = false;        private float currentScale = 1.0f;        private float targetScale = 1.0f;        private float hoverScale = 1.1f; // 悬停时的放大比例          private Color hoverBorderColor;        private Color hoverBorderColor2;        private System.Windows.Forms.Timer animationTimer;        private float glowOpacity = 0f;        private bool enableHoverEffect = true;        public CircularPictureBox()        {            this.Size = new Size(100, 100);            this.SizeMode = PictureBoxSizeMode.StretchImage;            this.BackColor = Color.Transparent;            // 初始化悬停颜色              hoverBorderColor = Color.FromArgb(255, 0, 174, 255);  // 明亮的蓝色              hoverBorderColor2 = Color.FromArgb(255, 255, 0, 128); // 明亮的粉色              // 初始化动画计时器              animationTimer = new System.Windows.Forms.Timer();            animationTimer.Interval = 16; // 约60fps              animationTimer.Tick += AnimationTimer_Tick;            // 添加鼠标事件              this.MouseEnter += CircularPictureBox_MouseEnter;            this.MouseLeave += CircularPictureBox_MouseLeave;        }        private void CircularPictureBox_MouseEnter(object sender, EventArgs e)        {            if (!enableHoverEffect) return;            isHovered = true;            targetScale = hoverScale;            if (!animationTimer.Enabled)                animationTimer.Start();        }        private void CircularPictureBox_MouseLeave(object sender, EventArgs e)        {            if (!enableHoverEffect) return;            isHovered = false;            targetScale = 1.0f;            if (!animationTimer.Enabled)                animationTimer.Start();        }        private void AnimationTimer_Tick(object sender, EventArgs e)        {            bool needsUpdate = false;            // 更新缩放动画              if (Math.Abs(currentScale - targetScale) > 0.001f)            {                currentScale += (targetScale - currentScale) * 0.2f;                needsUpdate = true;            }            // 更新发光效果              float targetGlow = isHovered ? 1f : 0f;            if (Math.Abs(glowOpacity - targetGlow) > 0.001f)            {                glowOpacity += (targetGlow - glowOpacity) * 0.2f;                needsUpdate = true;            }            if (needsUpdate)            {                this.Invalidate();            }            else            {                animationTimer.Stop();            }        }        // 优化双缓冲设置          protected override void onHandleCreated(EventArgs e)        {            base.onHandleCreated(e);            this.SetStyle(ControlStyles.AllPaintingInWmPaint |                         ControlStyles.UserPaint |                         ControlStyles.OptimizedDoubleBuffer |                         ControlStyles.ResizeRedraw, true);        }        public bool EnableHoverEffect        {            get => enableHoverEffect;            set => enableHoverEffect = value;        }        public float HoverScale        {            get => hoverScale;            set => hoverScale = value;        }        public int BorderSize        {            get            {                return borderSize;            }            set            {                borderSize = value;                this.Invalidate();            }        }        public Color BorderColor        {            get            {                return borderColor;            }            set            {                borderColor = value;                this.Invalidate();            }        }        public Color BorderColor2        {            get            {                return borderColor2;            }            set            {                borderColor2 = value;                this.Invalidate();            }        }        public DashStyle BorderLineStyle        {            get            {                return borderLineStyle;            }            set            {                borderLineStyle = value;                this.Invalidate();            }        }        public DashCap BorderCapStyle        {            get            {                return borderCapStyle;            }            set            {                borderCapStyle = value;                this.Invalidate();            }        }        public float GradientAngle        {            get            {                return gradientAngle;            }            set            {                gradientAngle = value;                this.Invalidate();            }        }        protected override void onResize(EventArgs e)        {            base.onResize(e);            this.Size = new Size(this.Width, this.Height);        }        protected override void onPaint(PaintEventArgs pe)        {            base.onPaint(pe);            // 计算缩放后的矩形              float scaleFactor = currentScale;            int widthDiff = (int)((this.Width * scaleFactor) - this.Width) / 2;            int heightDiff = (int)((this.Height * scaleFactor) - this.Height) / 2;            Rectangle scaledRect = new Rectangle(                -widthDiff,                -heightDiff,                (int)(this.Width * scaleFactor),                (int)(this.Height * scaleFactor)            );            Rectangle rectSurface = scaledRect;            Rectangle rectBorder = Rectangle.Inflate(rectSurface, -borderSize, -borderSize);            int smoothSize = 2;            if (borderSize > 0)                smoothSize = borderSize;            using (GraphicsPath pathSurface = GetCirclePath(rectSurface))            using (GraphicsPath pathBorder = GetCirclePath(rectBorder))            using (Pen penSurface = new Pen(this.Parent.BackColor, smoothSize))            {                pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;                this.Region = new Region(pathSurface);                // 绘制发光效果                  if (glowOpacity > 0)                {                    using (GraphicsPath glowPath = GetCirclePath(Rectangle.Inflate(rectSurface, 5, 5)))                    using (PathGradientBrush glowBrush = new PathGradientBrush(glowPath))                    {                        Color glowColor = Color.FromArgb(                            (int)(100 * glowOpacity),                            hoverBorderColor                        );                        glowBrush.CenterColor = glowColor;                        glowBrush.SurroundColors = new Color[] { Color.FromArgb(0, glowColor) };                        pe.Graphics.FillPath(glowBrush, glowPath);                    }                }                // 绘制图片                  if (this.Image != null)                {                    using (TextureBrush textureBrush = new TextureBrush(this.Image))                    {                        textureBrush.WrapMode = WrapMode.Clamp;                        Matrix matrix = new Matrix();                        if (this.SizeMode == PictureBoxSizeMode.Zoom)                        {                            float scale = Math.Min((float)scaledRect.Width / this.Image.Width,                                                 (float)scaledRect.Height / this.Image.Height);                            float x = (scaledRect.Width - (this.Image.Width * scale)) / 2 + scaledRect.X;                            float y = (scaledRect.Height - (this.Image.Height * scale)) / 2 + scaledRect.Y;                            matrix.Translate(x, y);                            matrix.Scale(scale, scale);                        }                        else                        {                            matrix.Scale((float)scaledRect.Width / this.Image.Width,                                       (float)scaledRect.Height / this.Image.Height);                            matrix.Translate(scaledRect.X, scaledRect.Y);                        }                        textureBrush.Transform = matrix;                        pe.Graphics.FillPath(textureBrush, pathSurface);                    }                }                // 绘制表面边缘                  pe.Graphics.DrawPath(penSurface, pathSurface);                // 绘制边框                  if (borderSize >= 1)                {                    Color currentBorderColor = isHovered ? hoverBorderColor : borderColor;                    Color currentBorderColor2 = isHovered ? hoverBorderColor2 : borderColor2;                    using (LinearGradientBrush borderGColor = new LinearGradientBrush(                        rectBorder, currentBorderColor, currentBorderColor2, gradientAngle))                    using (Pen penBorder = new Pen(borderGColor, borderSize))                    {                        penBorder.DashStyle = borderLineStyle;                        penBorder.DashCap = borderCapStyle;                        penBorder.Alignment = PenAlignment.Center;                        pe.Graphics.DrawPath(penBorder, pathBorder);                    }                }            }        }        private GraphicsPath GetCirclePath(Rectangle rect)        {            GraphicsPath path = new GraphicsPath();            path.AddEllipse(rect);            return path;        }        // 确保在控件销毁时释放资源          protected override void Dispose(bool disposing)        {            if (disposing)            {                animationTimer.Dispose();            }            base.Dispose(disposing);        }    }}

性能优化建议

  1. 在不需要重绘时避免调用Invalidate()
  2. 合理设置图片的SizeMode
  3. 使用using语句确保及时释放GDI+资源
  4. 可以考虑添加双缓冲以提升显示效果

这个自定义控件为WinForms应用程序提供了一个美观的圆形图片显示解决方案,特别适合用于显示用户头像、圆形标志等场景。通过调整各种属性,可以实现丰富的视觉效果。

打赏
0相关评论
热门搜索排行
精彩图片
友情链接
声明:本站信息均由用户注册后自行发布,本站不承担任何法律责任。如有侵权请告知立立即做删除处理。
违法不良信息举报邮箱:115904045
头条快讯网 版权所有
中国互联网举报中心