C#仿QQ皮肤-实现原理系列文章导航
http://www.cnblogs.com/sufei/archive/2010/03/10/1682847.html
这一次我们先要研究一下系统的是怎么完成的
我们使用Reflector反编译一下GroupBox一起来看看它的内部是怎么实现的。
从类的开始第一行我们可以看得出来它是继承Control这个类而来的,下面是所有引用的命名空间和继承的源
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms.Internal;
using System.Windows.Forms.Layout;
using System.Windows.Forms.VisualStyles;
[DefaultEvent(
"Enter"), Designer("System.Windows.Forms.Design.GroupBoxDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ClassInterface(ClassInterfaceType.AutoDispatch), DefaultProperty("Text"), ComVisible(true), System.Windows.Forms.SRDescription("DescriptionGroupBox")]public class GroupBox : Control
{
其实这里告诉我们这样几个问题
1.所有引用的命名空间
2.默认的事件 DefaultEvent("Enter"),
3.在实现设计时服务的类 System.Windows.Forms.Design.GroupBoxDesigner
4.为Com指定接口类型ClassInterface
5.默认的属性DefaultProperty("Text")
6.托管类型或是成员的Com可访问性ComVisible
7.继承自 public class GroupBox : Control
关于事件的注册
我们以一个AutoSizeChanged事件来说明
用上面的语句指定属性和方法是否在编辑器里的可见方式 在这里我们合作Always代表是编辑器里是始终可见的
然后让它显示在属性窗口中
看一下MS的实现方式吧
[EditorBrowsable(EditorBrowsableState.Always), System.Windows.Forms.SRCategory("CatPropertyChanged"), System.Windows.Forms.SRDescription("ControlOnAutoSizeChangedDescr"), Browsable(true)]
public event EventHandler AutoSizeChanged
{
add
{
base.AutoSizeChanged += value;
}
remove
{
base.AutoSizeChanged -= value;
}
}
我们现在再来看Click事件的实现就更为简单了
public event EventHandler Click
{
add
{
base.Click += value;
}
remove
{
base.Click -= value;
}
}
以后的事件基本上和这个差不多,就不再多说了
具体的实现
我们一起来看看他的构造方法
{
base.SetState2(0x800, true);
base.SetStyle(ControlStyles.ContainerControl, true);
base.SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, this.OwnerDraw);
base.SetStyle(ControlStyles.Selectable, false);
this.TabStop = false;
}
呵呵 ,其实这里跟我用来实现Combox控件时的情况差不了多少。
DrawGroupBox事件的实现方法如果你看过我的Combox的实现的话应该很容易能看明白,
{
Graphics graphics = e.Graphics;
Rectangle clientRectangle = base.ClientRectangle;
int num = 8;
Color disabledColor = base.DisabledColor;
Pen pen = new Pen(ControlPaint.Light(disabledColor, 1f));
Pen pen2 = new Pen(ControlPaint.Dark(disabledColor, 0f));
clientRectangle.X += num;
clientRectangle.Width -= 2 * num;
try
{
Size size;
int num2;
if (this.UseCompatibleTextRendering)
{
using (Brush brush = new SolidBrush(this.ForeColor))
{
using (StringFormat format = new StringFormat())
{
format.HotkeyPrefix = this.ShowKeyboardCues ? HotkeyPrefix.Show : HotkeyPrefix.Hide;
if (this.RightToLeft == RightToLeft.Yes)
{
format.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
}
size = Size.Ceiling(graphics.MeasureString(this.Text, this.Font, clientRectangle.Width, format));
if (base.Enabled)
{
graphics.DrawString(this.Text, this.Font, brush, clientRectangle, format);
}
else
{
ControlPaint.DrawStringDisabled(graphics, this.Text, this.Font, disabledColor, clientRectangle, format);
}
}
goto Label_01E7;
}
}
using (WindowsGraphics graphics2 = WindowsGraphics.FromGraphics(graphics))
{
IntTextFormatFlags flags = IntTextFormatFlags.TextBoxControl | IntTextFormatFlags.WordBreak;
if (!this.ShowKeyboardCues)
{
flags |= IntTextFormatFlags.HidePrefix;
}
if (this.RightToLeft == RightToLeft.Yes)
{
flags |= IntTextFormatFlags.RightToLeft;
flags |= IntTextFormatFlags.Right;
}
using (WindowsFont font = WindowsGraphicsCacheManager.GetWindowsFont(this.Font))
{
size = graphics2.MeasureText(this.Text, font, new Size(clientRectangle.Width, 0x7fffffff), flags);
if (base.Enabled)
{
graphics2.DrawText(this.Text, font, clientRectangle, this.ForeColor, flags);
}
else
{
ControlPaint.DrawStringDisabled(graphics2, this.Text, this.Font, disabledColor, clientRectangle, (TextFormatFlags) flags);
}
}
}
Label_01E7:
num2 = num;
if (this.RightToLeft == RightToLeft.Yes)
{
num2 += clientRectangle.Width - size.Width;
}
int num3 = Math.Min((int) (num2 + size.Width), (int) (base.Width - 6));
int num4 = base.FontHeight / 2;
graphics.DrawLine(pen, 1, num4, 1, base.Height - 1);
graphics.DrawLine(pen2, 0, num4, 0, base.Height - 2);
graphics.DrawLine(pen, 0, base.Height - 1, base.Width, base.Height - 1);
graphics.DrawLine(pen2, 0, base.Height - 2, base.Width - 1, base.Height - 2);
graphics.DrawLine(pen2, 0, num4 - 1, num2, num4 - 1);
graphics.DrawLine(pen, 1, num4, num2, num4);
graphics.DrawLine(pen2, num3, num4 - 1, base.Width - 2, num4 - 1);
graphics.DrawLine(pen, num3, num4, base.Width - 1, num4);
graphics.DrawLine(pen, (int) (base.Width - 1), (int) (num4 - 1), (int) (base.Width - 1), (int) (base.Height - 1));
graphics.DrawLine(pen2, base.Width - 2, num4, base.Width - 2, base.Height - 2);
}
finally
{
pen.Dispose();
pen2.Dispose();
}
}
在这里不得不说MS的方法没有多少高明之处啊,不过还是值得我敬佩的
我把所有的代码都放上来大家参考一下吧,然后再接着说我的控件是怎么实现的
{
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Text;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Windows.Forms.Internal;
using System.Windows.Forms.Layout;
using System.Windows.Forms.VisualStyles;
[DefaultEvent(
"Enter"), Designer("System.Windows.Forms.Design.GroupBoxDesigner, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"), ClassInterface(ClassInterfaceType.AutoDispatch), DefaultProperty("Text"), ComVisible(true), System.Windows.Forms.SRDescription("DescriptionGroupBox")]public class GroupBox : Control
{
private Font cachedFont;
private System.Windows.Forms.FlatStyle flatStyle = System.Windows.Forms.FlatStyle.Standard;
private int fontHeight = -1;
[EditorBrowsable(EditorBrowsableState.Always), System.Windows.Forms.SRCategory(
"CatPropertyChanged"), System.Windows.Forms.SRDescription("ControlOnAutoSizeChangedDescr"), Browsable(true)]public event EventHandler AutoSizeChanged
{
add
{
base.AutoSizeChanged += value;
}
remove
{
base.AutoSizeChanged -= value;
}
}
[Browsable(
false), EditorBrowsable(EditorBrowsableState.Advanced)]public event EventHandler Click
{
add
{
base.Click += value;
}
remove
{
base.Click -= value;
}
}
[Browsable(
false), EditorBrowsable(EditorBrowsableState.Advanced)]public event EventHandler DoubleClick
{
add
{
base.DoubleClick += value;
}
remove
{
base.DoubleClick -= value;
}
}
[Browsable(
false), EditorBrowsable(EditorBrowsableState.Advanced)]public event KeyEventHandler KeyDown
{
add
{
base.KeyDown += value;
}
remove
{
base.KeyDown -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event KeyPressEventHandler KeyPress
{
add
{
base.KeyPress += value;
}
remove
{
base.KeyPress -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event KeyEventHandler KeyUp
{
add
{
base.KeyUp += value;
}
remove
{
base.KeyUp -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event MouseEventHandler MouseClick
{
add
{
base.MouseClick += value;
}
remove
{
base.MouseClick -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event MouseEventHandler MouseDoubleClick
{
add
{
base.MouseDoubleClick += value;
}
remove
{
base.MouseDoubleClick -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event MouseEventHandler MouseDown
{
add
{
base.MouseDown += value;
}
remove
{
base.MouseDown -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event EventHandler MouseEnter
{
add
{
base.MouseEnter += value;
}
remove
{
base.MouseEnter -= value;
}
}
[Browsable(
false), EditorBrowsable(EditorBrowsableState.Advanced)]public event EventHandler MouseLeave
{
add
{
base.MouseLeave += value;
}
remove
{
base.MouseLeave -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event MouseEventHandler MouseMove
{
add
{
base.MouseMove += value;
}
remove
{
base.MouseMove -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event MouseEventHandler MouseUp
{
add
{
base.MouseUp += value;
}
remove
{
base.MouseUp -= value;
}
}
[EditorBrowsable(EditorBrowsableState.Advanced), Browsable(
false)]public event EventHandler TabStopChanged
{
add
{
base.TabStopChanged += value;
}
remove
{
base.TabStopChanged -= value;
}
}
public GroupBox()
{
base.SetState2(0x800, true);
base.SetStyle(ControlStyles.ContainerControl, true);
base.SetStyle(ControlStyles.SupportsTransparentBackColor | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, this.OwnerDraw);
base.SetStyle(ControlStyles.Selectable, false);
this.TabStop = false;
}
protected override AccessibleObject CreateAccessibilityInstance()
{
return new GroupBoxAccessibleObject(this);
}
private void DrawGroupBox(PaintEventArgs e)
{
Graphics graphics = e.Graphics;
Rectangle clientRectangle = base.ClientRectangle;
int num = 8;
Color disabledColor = base.DisabledColor;
Pen pen = new Pen(ControlPaint.Light(disabledColor, 1f));
Pen pen2 = new Pen(ControlPaint.Dark(disabledColor, 0f));
clientRectangle.X += num;
clientRectangle.Width -= 2 * num;
try
{
Size size;
int num2;
if (this.UseCompatibleTextRendering)
{
using (Brush brush = new SolidBrush(this.ForeColor))
{
using (StringFormat format = new StringFormat())
{
format.HotkeyPrefix = this.ShowKeyboardCues ? HotkeyPrefix.Show : HotkeyPrefix.Hide;
if (this.RightToLeft == RightToLeft.Yes)
{
format.FormatFlags |= StringFormatFlags.DirectionRightToLeft;
}
size = Size.Ceiling(graphics.MeasureString(this.Text, this.Font, clientRectangle.Width, format));
if (base.Enabled)
{
graphics.DrawString(this.Text, this.Font, brush, clientRectangle, format);
}
else
{
ControlPaint.DrawStringDisabled(graphics, this.Text, this.Font, disabledColor, clientRectangle, format);
}
}
goto Label_01E7;
}
}
using (WindowsGraphics graphics2 = WindowsGraphics.FromGraphics(graphics))
{
IntTextFormatFlags flags = IntTextFormatFlags.TextBoxControl | IntTextFormatFlags.WordBreak;
if (!this.ShowKeyboardCues)
{
flags |= IntTextFormatFlags.HidePrefix;
}
if (this.RightToLeft == RightToLeft.Yes)
{
flags |= IntTextFormatFlags.RightToLeft;
flags |= IntTextFormatFlags.Right;
}
using (WindowsFont font = WindowsGraphicsCacheManager.GetWindowsFont(this.Font))
{
size = graphics2.MeasureText(this.Text, font, new Size(clientRectangle.Width, 0x7fffffff), flags);
if (base.Enabled)
{
graphics2.DrawText(this.Text, font, clientRectangle, this.ForeColor, flags);
}
else
{
ControlPaint.DrawStringDisabled(graphics2, this.Text, this.Font, disabledColor, clientRectangle, (TextFormatFlags) flags);
}
}
}
Label_01E7:
num2 = num;