在其他控件上方显示透明加载微调器

我在旋转控制器中工作。 我希望控件支持透明背景色。 绘制弧线时,中间有一个空白区域,我希望该空间真正透明,这样我就可以在其后面放置另一个控件,它不会被旋转器覆盖。

我试过覆盖CreateParams void。
另外我设置样式以支持TransparentColor。
尝试重写OnPaintBackground无效,但我无法实现真正​​透明的背景色。

那么,你能建议我做什么?

要创建透明图层,您应该覆盖控件的绘制并按此顺序绘制控件, 首先在位图上的同一容器中绘制所有控件(基于z-index)。 然后在控件的图形上绘制该位图。 最后绘制控件的内容。 您的控件的BackColor 应该是Color.Transparent

另外,作为制作透明图层的另一个选项,您可以在绘制时从控件中排除某些区域。

在以下示例中,我使用了第一种技术并创建了2个控件。 旋转圈旋转控制。 和透明的图片框控件。

在两个样本中,我在加载行之间使用延迟来显示旋转器有意义。

示例1 – 使用SpinningCircles控件

SpinningCircles控件绘制圆圈并支持透明度。 控件在设计时没有动画,但在运行时动画。 当它不可见时它也不消耗资源。

在此处输入图像描述

示例2 – 使用TransparentPictureBox控件和透明动画gif TransparentPictureBox控件支持透明度,因此我使用动画gif作为其图像,如您所见,gif正确显示。

在此处输入图像描述

样本1代码 – SpinningCircles

 using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Forms; public class SpinningCircles : Control { int increment = 1; int radius = 4; int n = 8; int next = 0; Timer timer; public SpinningCircles() { timer = new Timer(); this.Size = new Size(100, 100); timer.Tick += (s, e) => this.Invalidate(); if (!DesignMode) timer.Enabled = true; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true); BackColor = Color.Transparent; } protected override void OnPaint(PaintEventArgs e) { if (Parent != null && this.BackColor == Color.Transparent) { using (var bmp = new Bitmap(Parent.Width, Parent.Height)) { Parent.Controls.Cast() .Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this)) .Where(c => c.Bounds.IntersectsWith(this.Bounds)) .OrderByDescending(c => Parent.Controls.GetChildIndex(c)) .ToList() .ForEach(c => c.DrawToBitmap(bmp, c.Bounds)); e.Graphics.DrawImage(bmp, -Left, -Top); } } e.Graphics.SmoothingMode = SmoothingMode.HighQuality; int length = Math.Min(Width, Height); PointF center = new PointF(length / 2, length / 2); int bigRadius = length / 2 - radius - (n - 1) * increment; float unitAngle = 360 / n; if (!DesignMode) next++; next = next >= n ? 0 : next; int a = 0; for (int i = next; i < next + n; i++) { int factor = i % n; float c1X = center.X + (float)(bigRadius * Math.Cos(unitAngle * factor * Math.PI / 180)); float c1Y = center.Y + (float)(bigRadius * Math.Sin(unitAngle * factor * Math.PI / 180)); int currRad = radius + a * increment; PointF c1 = new PointF(c1X - currRad, c1Y - currRad); e.Graphics.FillEllipse(Brushes.Black, c1.X, c1.Y, 2 * currRad, 2 * currRad); using (Pen pen = new Pen(Color.White, 2)) e.Graphics.DrawEllipse(pen, c1.X, c1.Y, 2 * currRad, 2 * currRad); a++; } } protected override void OnVisibleChanged(EventArgs e) { timer.Enabled = Visible; base.OnVisibleChanged(e); } } 

示例2代码 - TransparentPictureBox代码

 using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Windows.Forms; class TransparentPictureBox : PictureBox { public TransparentPictureBox() { this.BackColor = Color.Transparent; } protected override void OnPaint(PaintEventArgs e) { if (Parent != null && this.BackColor == Color.Transparent) { using (var bmp = new Bitmap(Parent.Width, Parent.Height)) { Parent.Controls.Cast() .Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this)) .Where(c => c.Bounds.IntersectsWith(this.Bounds)) .OrderByDescending(c => Parent.Controls.GetChildIndex(c)) .ToList() .ForEach(c => c.DrawToBitmap(bmp, c.Bounds)); e.Graphics.DrawImage(bmp, -Left, -Top); } } base.OnPaint(e); } } 

我略微改变了Reza的代码(SpinningCircles)以添加半透明背景。 我想和你分享。 (注意:微调器长度固定为100,应作为组件属性添加)

 public partial class WorkingPanel : UserControl { #region Constants private static readonly Int32 kSpinnerLength = 100; #endregion #region Fields private Int32 increment = 1; private Int32 radius = 4; private Int32 n = 8; private Int32 next = 0; private Timer timer = null; #endregion #region Constructor public WorkingPanel() { this.Size = new Size(100, 100); timer = new Timer(); timer.Tick += (s, e) => this.Invalidate(); if (!DesignMode) timer.Enabled = true; SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint | ControlStyles.SupportsTransparentBackColor, true); BackColor = Color.Transparent; } #endregion #region Methods (Protected - Override) protected override void OnPaint(PaintEventArgs e) { if (null != Parent && (this.BackColor.A != 255 || this.BackColor == Color.Transparent)) { using (var bmp = new Bitmap(Parent.Width, Parent.Height)) { Parent.Controls.Cast() .Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this)) .Where(c => c.Bounds.IntersectsWith(this.Bounds)) .OrderByDescending(c => Parent.Controls.GetChildIndex(c)) .ToList() .ForEach(c => c.DrawToBitmap(bmp, c.Bounds)); e.Graphics.DrawImage(bmp, -Left, -Top); if (this.BackColor != Color.Transparent) e.Graphics.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(0, 0, Width, Height)); } } e.Graphics.SmoothingMode = SmoothingMode.HighQuality; Int32 length = kSpinnerLength; PointF center = new PointF(Width / 2, Height / 2); Int32 bigRadius = length / 2 - radius - (n - 1) * increment; float unitAngle = 360 / n; if (!DesignMode) next++; next = next >= n ? 0 : next; Int32 a = 0; for (Int32 i = next; i < next + n; i++) { Int32 factor = i % n; float c1X = center.X + (float)(bigRadius * Math.Cos(unitAngle * factor * Math.PI / 180)); float c1Y = center.Y + (float)(bigRadius * Math.Sin(unitAngle * factor * Math.PI / 180)); Int32 currRad = radius + a * increment; PointF c1 = new PointF(c1X - currRad, c1Y - currRad); e.Graphics.FillEllipse(Brushes.White, c1.X, c1.Y, 2 * currRad, 2 * currRad); using (Pen pen = new Pen(Color.White, 2)) e.Graphics.DrawEllipse(pen, c1.X, c1.Y, 2 * currRad, 2 * currRad); a++; } } protected override void OnVisibleChanged(EventArgs e) { timer.Enabled = Visible; base.OnVisibleChanged(e); } #endregion }