首先,创建设计期库,步骤如下:
1. “新建->项目->类库”,取名XxxDesigner,如图。注意将项目放在Xxx目录下。

2. 修改项目属性,将默认命名空间改为Xxx(当然也可以使用其他名字,只要与运行期库一致即可),如图

3. 打开AssemblyInfo.cs文件,改变程序集版本号,即将[assembly: AssemblyVersion("1.0.*")]改为某个特定的值,比如[assembly: AssemblyVersion("1.2.3.4")]
4. 修改引用:移除原来的所有引用,依次加入如下程序集。注意加入的次序很重要,必须按照以下顺序:
/r:"E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE/Designer/System.CF.Design.dll"
/r:"E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE/Designer/System.CF.Windows.Forms.dll"
/r:"E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE/Designer/System.CF.Drawing.DLL"
/r:System.Windows.Forms.dll
/r:System.Drawing.DLL
/r:System.dll
引用程序集添加完成后,项目解决方案如图(注意:“引用”中的显示的程序集依字母顺序排列,与添加顺序无关):

5. 修改“项目属性->配置属性->生成”,取消显示特定警告1595(当两个引用程序集中含有名字和命名空间都完全相同的类,且项目使用了这个类时,就会引起该警告,此时实际使用哪个类依引用程序集时的添加顺序为准,使用先添加的那一个),如图:

6. “添加->添加新项->用户界面->自定义控件”,删除原来的类文件。
7. 对VS.NET生成的自定义组件代码模板,删去using System.Data;,删去components变量,删去InitializeComponent方法中对components的初始化以及 Dispose方法中对components的使用(否则如果对组件添加了Timer这样的资源会引起编译错误,错误原因是在System.CF.Windows.Forms程序集中的Timer没有带参的构造函数,与System.Windows.Forms程序集中的Timer不同)。对Dispose方法,如果使用了像Timer这样的资源,则必须在其中调用Timer的Dispose方法(注意运行期库中不需要Dispose方法)。
8. 为组件添加一个图标,这个图标在组件被选择放入工具箱以备使用时显示。添加图标方法如下:首先,为XxxDesigner项目添加一个位图资源文件,注意该位图文件的取名要与相应组件完全一致(例如组件名为CustomControl1,则位图文件名为CustomControl1.bmp);然后改变其“属性->高级->生成操作”,改为“嵌入的资源”;再调整位图大小,改为16×16;最后,为组件所在类添加ToolboxBitmap特性,如下:
[ToolboxBitmap(typeof(ClassLibrary.CustomControl1), "CustomControl1.bmp")]
9. 通过Designer特性为组件添加一个设计器,如下:
[Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
如果组件仅需要一般的设计期行为,则使用ControlDesigner已足够,否则需要自定义设计器,大致方法是从ControlDesigner派生一个新的设计器然后通过Designer特性指派给相应组件,在此不详细叙述。
10. 重载组件相应的函数,完成自定义组件的相应要求(如重载OnPaint函数自定义组件的绘制行为,等等等等)。
11. 经过以上步骤,代码框架如下:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
[assembly: System.CF.Design.RuntimeAssembly("ClassLibraryRuntime, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null")]
namespace ClassLibrary
{
///<summary>
/// CustomControl1 的摘要说明。
///</summary>
[ToolboxBitmap(typeof(ClassLibrary.CustomControl1), "CustomControl1.bmp") , Designer(typeof(System.Windows.Forms.Design.ControlDesigner))]
public class CustomControl1 : System.Windows.Forms.Control
{
private System.Windows.Forms.Timer timer1;
public CustomControl1()
{
// 该调用是 Windows.Forms 窗体设计器所必需的。
InitializeComponent();
// TODO: 在 InitComponent 调用后添加任何初始化
}
///<summary>
///清理所有正在使用的资源。
///</summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
timer1.Dispose() ;
}
base.Dispose( disposing );
}
#region组件设计器生成的代码
///<summary>
///设计器支持所需的方法 - 不要使用代码编辑器
///修改此方法的内容。
///</summary>
private void InitializeComponent()
{
this.timer1 = new System.Windows.Forms.Timer();
}
#endregion
protected override void OnPaint(PaintEventArgs pe)
{
// TODO: 在此添加自定义绘画代码
// 调用基类 OnPaint
base.OnPaint(pe);
}
}
}
解决方案如图:

然后,创建运行期库,步骤如下:
1. 在同一个解决方案中,选择“添加->新建项目->智能设备应用程序”,取名为XxxRuntime,放置在Xxx目录下,如图

点击确定后,平台选择:WinCE,项目类型选择:类库。
2. 修改项目属性,将其默认命名空间改为与设计期库一致。
3. 打开AssemblyInfo.cs文件,修改程序集版本号,即将[assembly: AssemblyVersion("1.0.*")]改为某个特定的值,比如[assembly: AssemblyVersion("1.2.3.4")]。注意对于版本号,设计期库和运行期库最好保持一致的。
4. 为运行期项目添加引用,如下:
/r:"E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE /System.Windows.Forms.dll"
/r:"E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE /System.Drawing.DLL"
5. 修改设计期库,在它的命名空间之外为其加上RuntimeAssembly特性,如下:
[assembly: System.CF.Design.RuntimeAssembly("ClassLibraryRuntime, Version=1.2.3.4, Culture=neutral, PublicKeyToken=null")]
注意RuntimeAssembly特性是CF特有的,对于创建一个自定义组件库非常重要,正是通过这个特性将设计期库和运行期库联系起来。
6. 删除原有类文件,向运行期库添加新的类文件,作为设计期组件对应的运行期组件,注意文件取名要与设计期库中相应组件完全一致;然后将设计库的代码适当拷贝过来(注意是适当拷贝,不是完全拷贝,因为设计期和运行期毕竟会有一些不同,它们有一些行为并不完全一致,故代码有时也不是完全相同的,比如运行期组件就不需要Dispose方法等等;但注意应尽量保持两者的一致或者至少对应)
7. 经过以上步骤,代码框架如下:
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace ClassLibrary
{
///<summary>
/// CustomControl1 的摘要说明。
///</summary>
public class CustomControl1 : System.Windows.Forms.Control
{
private System.Windows.Forms.Timer timer1;
public CustomControl1()
{
// 该调用是 Windows.Forms 窗体设计器所必需的。
InitializeComponent();
// TODO: 在 InitComponent 调用后添加任何初始化
}
#region组件设计器生成的代码
///<summary>
///设计器支持所需的方法 - 不要使用代码编辑器
///修改此方法的内容。
///</summary>
private void InitializeComponent()
{
this.timer1 = new System.Windows.Forms.Timer();
}
#endregion
protected override void OnPaint(PaintEventArgs pe)
{
// TODO: 在此添加自定义绘画代码
// 调用基类 OnPaint
base.OnPaint(pe);
}
}
}
解决方案如图:

自定义控件的使用:
1. 将Designer目录最终生成的DLL文件拷贝到E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE/Designer目录下
2. 将Runtime目录下最终生成的DLL文件拷贝到E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE目录下
3. 新建一个智能设备引用程序,平台选择:WinCE,项目类型选择:Windows应用程序。
4. 在窗体设计器中,在“工具箱”的“设备控件”选项卡右击,选择“添加/移除项”,出现如图对话框,浏览到E:/Microsoft Visual Studio .NET 2003/CompactFrameworkSDK/v1.0.5000/Windows CE/Designer目录,选择XxxDesigner.dll文件。

5. 点击确定后,自定义控件就放在工具箱中,可以像标准控件一样使用了。