C#.Net组件开发(高级篇) - 设计时在窗体设计器文件内生成组件的代码
C#.Net组件开发(高级篇) - 设计时在窗体设计器文件内生成组件的代码
在设计环境下设计组件和窗体设计器是很底层东西,技术非常复杂,水很深!刚学了点皮毛感觉入了门,特别将代码分享出来.在动手实验过程中遇到很多麻烦,因为没搞清这个实时设计的概念,还有这个窗体设计器会自动生成XXX.Designer.cs文件的代码,非常神奇的技术,也许将来对框架改进有帮助,所以想一探究竟.因为我不理解这个代码生成的机制,于是到处找文章,百度搜索关键字太烂了,基本上找不着我想要的,用Google勉强能找到一些文章,也不对口,东拼西凑,认真动手做实验,坚持了几天写了不少代码.
先讲下如何在窗体设计器文件内生成组件的代码,如要生成设计时的代码,参与的对象必须实现IComponent接口,比如往窗体上拖个Button, 打开XXX.Designer.cs文件查看代码:
可见自动生成了button1相关代码,最重要的是这句:this.Controls.Add(this.button1),将button1对象加入到窗体的控制列表中.在Controls.Add方法上点右键弹出菜单,选择Go to Definition查看源码:
可见Add方法接受Control参数,而Control类继承了实现IComponent接口的Component类.
好了,下面看我是如何自动生成button2的代码.
首先建立一个用于测试的组件,命名CSFrameworkComponent,类定义了一组属性(Attribute).给组件指定一个自定义的设计器CSFrameworkDesigner.我们使用CSFrameworkDesigner设计器生成按钮的代码.
自定义设计器CSFrameworkDesigner
完成组件和设计器的代码后重新编译程序,新建一个窗体,往窗体上拖一个CSFrameworkComponent组件,在组件上点右键如下图:
frmTester.Designer.cs文件
扫一扫加作者微信
在设计环境下设计组件和窗体设计器是很底层东西,技术非常复杂,水很深!刚学了点皮毛感觉入了门,特别将代码分享出来.在动手实验过程中遇到很多麻烦,因为没搞清这个实时设计的概念,还有这个窗体设计器会自动生成XXX.Designer.cs文件的代码,非常神奇的技术,也许将来对框架改进有帮助,所以想一探究竟.因为我不理解这个代码生成的机制,于是到处找文章,百度搜索关键字太烂了,基本上找不着我想要的,用Google勉强能找到一些文章,也不对口,东拼西凑,认真动手做实验,坚持了几天写了不少代码.
先讲下如何在窗体设计器文件内生成组件的代码,如要生成设计时的代码,参与的对象必须实现IComponent接口,比如往窗体上拖个Button, 打开XXX.Designer.cs文件查看代码:
C# Code:
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(87, 75);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// frmTester
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.button1);
this.Name = "frmTester";
this.Text = "frmTester";
this.ResumeLayout(false);
}
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(87, 75);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
//
// frmTester
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.Add(this.button1);
this.Name = "frmTester";
this.Text = "frmTester";
this.ResumeLayout(false);
}
可见自动生成了button1相关代码,最重要的是这句:this.Controls.Add(this.button1),将button1对象加入到窗体的控制列表中.在Controls.Add方法上点右键弹出菜单,选择Go to Definition查看源码:
C# Code:
public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IBindableComponent, IComponent, IDisposable
{
...略...
public class Control : Component, IDropTarget, ISynchronizeInvoke, IWin32Window, IBindableComponent, IComponent, IDisposable
{
...略...
// Summary:}
// Adds the specified control to the control collection.
//
// Parameters:
// value:
// The System.Windows.Forms.Control to add to the control collection.
//
// Exceptions:
// System.Exception:
// The specified control is a top-level control, or a circular control reference
// would result if this control were added to the control collection.
//
// System.ArgumentException:
// The object assigned to the value parameter is not a System.Windows.Forms.Control.
public virtual void Add(Control value);
...略...
可见Add方法接受Control参数,而Control类继承了实现IComponent接口的Component类.
好了,下面看我是如何自动生成button2的代码.
首先建立一个用于测试的组件,命名CSFrameworkComponent,类定义了一组属性(Attribute).给组件指定一个自定义的设计器CSFrameworkDesigner.我们使用CSFrameworkDesigner设计器生成按钮的代码.
C# Code:
[ToolboxBitmap(typeof(CSFrameworkComponent), "ComponentTest.bmp")]
[DesignTimeVisible(true)]
[Designer(typeof(CSFrameworkDesigner), typeof(IDesigner))]
public partial class CSFrameworkComponent : Component
{
//窗体设计器的接口引用,当拖拉组件到窗体上,值由构造器传入.
private IContainer _Designer;
public CSFrameworkComponent()
{
}
public CSFrameworkComponent(IContainer container)
{
_Designer = container;
container.Add(this);
}
}
//来源:C/S框架网(www.csframework.com) QQ:1980854898
[ToolboxBitmap(typeof(CSFrameworkComponent), "ComponentTest.bmp")]
[DesignTimeVisible(true)]
[Designer(typeof(CSFrameworkDesigner), typeof(IDesigner))]
public partial class CSFrameworkComponent : Component
{
//窗体设计器的接口引用,当拖拉组件到窗体上,值由构造器传入.
private IContainer _Designer;
public CSFrameworkComponent()
{
}
public CSFrameworkComponent(IContainer container)
{
_Designer = container;
container.Add(this);
}
}
//来源:C/S框架网(www.csframework.com) QQ:1980854898
自定义设计器CSFrameworkDesigner
C# Code:
public class CSFrameworkComponentDesigner : ComponentDesigner
{
private CSFrameworkComponent _CurrentComponent;
public CSFrameworkComponentDesigner()
: base()
{
// 添加菜单到右键菜单和智能标记中。
DesignerVerb V1 = new DesignerVerb("生成MyNodeComponent的设计时代码", new EventHandler(OnGenerateMyNodeComponentCode));
DesignerVerb V2 = new DesignerVerb("生成Button的设计时代码", new EventHandler(OnGenerateButtonCode));
DesignerVerb V3 = new DesignerVerb("www.CSFramework.com C/S框架网", new EventHandler(OnAbout));
this.Verbs.Add(V1);
this.Verbs.Add(V2);
this.Verbs.Add(V3);
}
private void OnAbout(object sender, EventArgs e)
{
MessageBox.Show("程序:Jonny Sun \r\n版权:www.CSFramework.com C/S框架网");
}
private void OnGenerateMyNodeComponentCode(object sender, EventArgs e)
{
//
//在窗体设计器代码中生成自定义MyNodeComponent组件的代码
//
//取出窗体设计器
IDesignerHost host = (IDesignerHost)this.Component.Site.GetService(typeof(IDesignerHost));
//创建一个组件
MyNodeComponent node = (MyNodeComponent)host.CreateComponent(typeof(MyNodeComponent));
node.NodeName = "www.CSFramework.com";
node.ID = DateTime.Now.Millisecond;
host.Container.Add(node);//在窗体设计器代码中生成代码
MessageBox.Show("已生成" node.NodeName "的代码!请打开frmTester.Designer.cs文件查看.");
}
public override void Initialize(IComponent component)
{
base.Initialize(component);
_CurrentComponent = (CSFrameworkComponent)component;
}
private void OnGenerateButtonCode(object sender, EventArgs e)
{
//
//在窗体上加入一个Button组件,host.RootComponent=Form
//
//取出窗体设计器
IDesignerHost host = (IDesignerHost)this.GetService(typeof(IDesignerHost));
IComponentChangeService c = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
Form form = (Form)host.RootComponent;//RootComponent: 根组件,指Form
DesignerTransaction tran = host.CreateTransaction();//创建事务
//创建按钮组件
Button button = (Button)host.CreateComponent(typeof(Button));
button.Text = "www.CSFramework.com";
button.Location = new Point(50, 50);
button.Size = new Size(150, 30);
c.OnComponentChanging(form, null);//通知窗体正在新增控件服务
form.Controls.Add(button);//Form.Controls.Add, 生成持久化代码
c.OnComponentChanged(form, null, null, null);//通知窗体修改服务已完成
tran.Commit();//提交事务
MessageBox.Show("已生成" button.Name "的代码!请打开frmTester.Designer.cs文件查看.");
}
}
//来源:C/S框架网(www.csframework.com) QQ:1980854898
public class CSFrameworkComponentDesigner : ComponentDesigner
{
private CSFrameworkComponent _CurrentComponent;
public CSFrameworkComponentDesigner()
: base()
{
// 添加菜单到右键菜单和智能标记中。
DesignerVerb V1 = new DesignerVerb("生成MyNodeComponent的设计时代码", new EventHandler(OnGenerateMyNodeComponentCode));
DesignerVerb V2 = new DesignerVerb("生成Button的设计时代码", new EventHandler(OnGenerateButtonCode));
DesignerVerb V3 = new DesignerVerb("www.CSFramework.com C/S框架网", new EventHandler(OnAbout));
this.Verbs.Add(V1);
this.Verbs.Add(V2);
this.Verbs.Add(V3);
}
private void OnAbout(object sender, EventArgs e)
{
MessageBox.Show("程序:Jonny Sun \r\n版权:www.CSFramework.com C/S框架网");
}
private void OnGenerateMyNodeComponentCode(object sender, EventArgs e)
{
//
//在窗体设计器代码中生成自定义MyNodeComponent组件的代码
//
//取出窗体设计器
IDesignerHost host = (IDesignerHost)this.Component.Site.GetService(typeof(IDesignerHost));
//创建一个组件
MyNodeComponent node = (MyNodeComponent)host.CreateComponent(typeof(MyNodeComponent));
node.NodeName = "www.CSFramework.com";
node.ID = DateTime.Now.Millisecond;
host.Container.Add(node);//在窗体设计器代码中生成代码
MessageBox.Show("已生成" node.NodeName "的代码!请打开frmTester.Designer.cs文件查看.");
}
public override void Initialize(IComponent component)
{
base.Initialize(component);
_CurrentComponent = (CSFrameworkComponent)component;
}
private void OnGenerateButtonCode(object sender, EventArgs e)
{
//
//在窗体上加入一个Button组件,host.RootComponent=Form
//
//取出窗体设计器
IDesignerHost host = (IDesignerHost)this.GetService(typeof(IDesignerHost));
IComponentChangeService c = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
Form form = (Form)host.RootComponent;//RootComponent: 根组件,指Form
DesignerTransaction tran = host.CreateTransaction();//创建事务
//创建按钮组件
Button button = (Button)host.CreateComponent(typeof(Button));
button.Text = "www.CSFramework.com";
button.Location = new Point(50, 50);
button.Size = new Size(150, 30);
c.OnComponentChanging(form, null);//通知窗体正在新增控件服务
form.Controls.Add(button);//Form.Controls.Add, 生成持久化代码
c.OnComponentChanged(form, null, null, null);//通知窗体修改服务已完成
tran.Commit();//提交事务
MessageBox.Show("已生成" button.Name "的代码!请打开frmTester.Designer.cs文件查看.");
}
}
//来源:C/S框架网(www.csframework.com) QQ:1980854898
完成组件和设计器的代码后重新编译程序,新建一个窗体,往窗体上拖一个CSFrameworkComponent组件,在组件上点右键如下图:
frmTester.Designer.cs文件
扫一扫加作者微信
版权声明:本文为开发框架文库发布内容,转载请附上原文出处连接
NewDoc C/S框架网