我正在创建一个自定义PictureBox。
如您所见,它是专为个人资料照片设计的PictureBox
嗯,这是CircularPictureBox的类
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Hector.Framework.Controls
{
public class CircularPictureBox : PictureBox
{
private Color _idlecolor = Color.White;
public CircularPictureBox()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.DoubleBuffer, true);
this.DoubleBuffered = true;
this.BackColor = Color.White;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.Size = new Size(100, 100);
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
using (var gpath = new GraphicsPath())
{
var brush = new SolidBrush(this.IdleBorderColor);
var pen = new Pen(brush, 5);
var outrect = new Rectangle(-1, -1, this.Width + 5, this.Height + 5);
gpath.AddEllipse(outrect);
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
pe.Graphics.DrawPath(pen, gpath);
brush.Dispose();
pen.Dispose();
gpath.Dispose();
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
using (var gpath = new GraphicsPath())
{
var rect = new Rectangle(1, 1, this.Width - 1, this.Height - 1);
gpath.AddEllipse(rect);
this.Region = new Region(gpath);
gpath.Dispose();
}
}
public Color IdleBorderColor
{
get => this._idlecolor;
set => this._idlecolor = value;
}
}
}
我的问题是,由于它是一个可以从设计师处使用的控件,我希望它具有边缘宽度或边框颜色等属性。
我开始测试颜色,但每当我改变颜色时, Visual Studio向我显示一条错误消息,指出该属性的值无效
答案 0 :(得分:1)
我对您的代码进行了一些修改,以突出显示在自定义控件设计中有用的一些功能。
我认为我所做的修改是不言自明的
但是,请查看OnPaint
事件。 e.Graphics.Clip
区域允许您隐藏不在所选区域中的所有图形部分。这意味着当您在设计模式下拖动控件时,图像将被剪裁,并且不会在区域区域外看到。
PixelOffsetMode.HighQuality
和SmoothingMode.AntiAlias
有助于渲染的整体质量(有注释掉的选项可以在其他情况下使用)。
Border偏移的计算必须引用BorderSize宽度,并相应地缩放。 Pen对象从其大小的中间开始绘制。如果笔的大小为3像素,则边框上绘制1个像素,区域外绘制1个像素,内部绘制一个像素(很奇怪?可能)。
这里的透明度设置只是一个“假”
它可能在其他情况下有效使用(它应该是“平台”)。
public class CircularPictureBox : PictureBox
{
private Bitmap bitmap;
private Color borderColor;
private int penSize;
private Color AlphaColor = Color.FromArgb(0, 255,255,255);
private bool enhancedBuffering;
public CircularPictureBox()
{
InitializeComponent();
this.SetStyle(ControlStyles.SupportsTransparentBackColor |
ControlStyles.ResizeRedraw |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
private void InitializeComponent()
{
this.enhancedBuffering = true;
this.bitmap = null;
this.borderColor = Color.Silver;
this.penSize = 7;
this.BackColor = AlphaColor;
this.SizeMode = PictureBoxSizeMode.StretchImage;
this.Size = new Size(100, 100);
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.CompositingMode = CompositingMode.SourceOver;
//pe.Graphics.CompositingQuality = CompositingQuality.HighQuality;
//pe.Graphics.InterpolationMode = InterpolationMode.Bicubic;
pe.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
pe.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
if (this.Region != null)
pe.Graphics.Clip = this.Region;
Rectangle rect = this.ClientRectangle;
if (this.bitmap != null)
pe.Graphics.DrawImage(this.bitmap, rect);
rect.Inflate(-this.penSize / 2 + 1, -this.penSize / 2 + 1);
pe.Graphics.DrawEllipse(new Pen(this.borderColor, this.penSize), rect);
}
protected override void OnResize(EventArgs e)
{
using (GraphicsPath gpath = new GraphicsPath())
{
gpath.AddEllipse(this.ClientRectangle);
gpath.CloseFigure();
using (Region region = new Region(gpath))
this.Region = region.Clone();
}
}
[Description("Gets or Sets the Image diplayed by the control."), Category("Appearance")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public Bitmap Bitmap
{
get { return this.bitmap; }
set { this.bitmap = value; this.Invalidate(); }
}
[Description("Gets or Sets the size of the Border"), Category("Behavior")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public int BorderSize
{
get { return this.penSize; }
set { this.penSize = value; this.Invalidate(); }
}
[Description("Gets or Sets the Color of Border drawn around the Image.")]
[Category("Appearance")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public Color BorderColor
{
get { return this.borderColor; }
set { this.borderColor = value; this.Invalidate(); }
}
[Description("Enables or disables the control OptimizedDoubleBuffering feature")]
[Category("Useful Features")] //<= "Useful feature" is a custom category
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
public bool EnhancedBuffering
{
get { return this.enhancedBuffering; }
set { this.enhancedBuffering = value;
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, value); }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public new Image ErrorImage
{
get { return null; }
set { base.ErrorImage = null; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public new Image InitialImage
{
get { return null; }
set { base.InitialImage = null; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
public new Image BackgroundImage
{
get { return null; }
set { base.BackgroundImage = null; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), BrowsableAttribute(false)]
public new Image Image {
get { return null; }
set { base.Image = null; }
}
}
一些System.ComponentModel
属性可以帮助塑造控件。
例如,[Description]和[Category]属性:
(这些已插入您控件的自定义属性BorderColor
中。)
[Description("Gets or Sets the Color of the Border drawn around the Image.")
[Category("Appearance")]
[EditorBrowsable(EditorBrowsableState.Always), Browsable(true)]
课程描述向用户解释了该物业的用途
类别用于在PropertyGrid内为属性提供有机配置。您可以使用标准名称(Appearance
,Behavior
等)或指定其他内容
在Category
视图正在使用时,为Categorized
提供自定义名称,并在其他名称中列出。
自定义控件的Image
属性已隐藏,并替换为Bitmap
属性:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never), BrowsableAttribute(false)]
[EditorBrowsable]属性是Intellisense的提示,可让您确定是否在弹出菜单中显示属性或方法。它可以是Never
,Always
或Advanced
(对于那些知道如何到达VS Options
的人)。部署自定义控件(作为dll)时,属性和方法将被隐藏,而不是在设计时隐藏。
[BrowsableAttribute]属性(或仅[Browsable]
)允许指定是否应在PropertyGrid中显示该属性。
[DesignerSerializationVisibility]
使用
DesignerSerializationVisibility
属性,您可以指出 属性的值是否为Visible
,并且应该保留 在初始化代码中,Hidden
,不应该保留 初始化代码,或由Content
组成,应该具有 为每个公共生成的初始化代码,而不是隐藏属性 分配给该属性的对象。
同样有趣并且:
[TypeConverterAttribute(typeof(System.ComponentModel.ExpandableObjectConverter))]
使用此属性,您可以指示在PropertyGrid中列出类对象的公共属性。
此类对象可以是序列化控件的复杂属性的内部类。
TypeConverter Class本身非常有趣。