using System;

using System.Collections;

using System.ComponentModel;

using System.Drawing;

using System.Data;

using System.Windows.Forms;


// Add in these using clauses for this example

using System.Runtime.InteropServices;

using System.Text;

using System.Reflection;

using Microsoft.Win32;



namespace Webb.PublicCOM.TestCOM01



{


/**//// <summary>

/// Summary description for TestActiveX03.

/// </summary>

[ProgId("Webb.PublicCOM.TestActiveX03")]

[ClassInterface(ClassInterfaceType.AutoDual)]

public class TestActiveX03 : System.Windows.Forms.UserControl


{

private System.Windows.Forms.PictureBox pictureBox1;


/**//// <summary>

/// Required designer variable.

/// </summary>

private System.ComponentModel.Container components = null;


public TestActiveX03()


{

// This call is required by the Windows.Forms Form Designer.

InitializeComponent();

// TODO: Add any initialization after the InitializeComponent call

}



/**//// <summary>

/// Clean up any resources being used.

/// </summary>

protected override void Dispose( bool disposing )


{

if( disposing )


{

if(components != null)


{

components.Dispose();

}

}

base.Dispose( disposing );

}



Component Designer generated code#region Component Designer generated code


/**//// <summary>

/// Required method for Designer support - do not modify

/// the contents of this method with the code editor.

/// </summary>

private void InitializeComponent()


{

System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(TestActiveX03));

this.pictureBox1 = new System.Windows.Forms.PictureBox();

this.SuspendLayout();

//

// pictureBox1

//

this.pictureBox1.Image = ((System.Drawing.Image)(resources.GetObject("pictureBox1.Image")));

this.pictureBox1.Location = new System.Drawing.Point(0, 0);

this.pictureBox1.Name = "pictureBox1";

this.pictureBox1.Size = new System.Drawing.Size(128, 40);

this.pictureBox1.TabIndex = 0;

this.pictureBox1.TabStop = false;

//

// TestActiveX03

//

this.Controls.Add(this.pictureBox1);

this.Name = "TestActiveX03";

this.Size = new System.Drawing.Size(200, 152);

this.ResumeLayout(false);


}

#endregion



/**////
<summary>

/// Register the class as a control and set it's CodeBase entry

///
</summary>

///
<param name="key">The registry key of the control</param>

[ComRegisterFunction()]

public static void RegisterClass ( string key )


{

// Strip off HKEY_CLASSES_ROOT\ from the passed key as I don't need it

StringBuilder sb = new StringBuilder ( key ) ;

sb.Replace(@"HKEY_CLASSES_ROOT\","") ;

// Open the CLSID\{guid} key for write access

RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);

// And create the 'Control' key - this allows it to show up in

// the ActiveX control container

RegistryKey ctrl = k.CreateSubKey ( "Control" ) ;

ctrl.Close ( ) ;

// Next create the CodeBase entry - needed if not string named and GACced.

RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;

inprocServer32.SetValue ( "CodeBase" , Assembly.GetExecutingAssembly().CodeBase ) ;

inprocServer32.Close ( ) ;

// Finally close the main key

k.Close ( ) ;

}



/**////
<summary>

/// Called to unregister the control

///
</summary>

///
<param name="key">Tke registry key</param>

[ComUnregisterFunction()]

public static void UnregisterClass ( string key )


{

StringBuilder sb = new StringBuilder ( key ) ;

sb.Replace(@"HKEY_CLASSES_ROOT\","") ;

// Open HKCR\CLSID\{guid} for write access

RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(),true);

// Delete the 'Control' key, but don't throw an exception if it does not exist

k.DeleteSubKey ( "Control" , false ) ;

// Next open up InprocServer32

RegistryKey inprocServer32 = k.OpenSubKey ( "InprocServer32" , true ) ;

// And delete the CodeBase key, again not throwing if missing

k.DeleteSubKey ( "CodeBase" , false ) ;

// Finally close the main key

k.Close ( ) ;

}

}

}

编译,然而用
Active Control Test Container 来测试和查看我们的
ActiveX:
可以看到,经过特殊方法实现后的对象可以在
ActiveX中查看的到,而且可以添加到容器中:

接下来的工作就是一些功能的实现细节问题了,本文暂时不讨论这些内容。
最后一个问题就是在其它语言中通过
COM来访问我们的
.net对象,我们在
C++下经过测试并实现了一些细节问题,事件等。但源代码不在示例中。
总结:
.net开发
COM或者
ActiveX,其实是把写好的
.net对象(当然是准备暴露给
OS的),实现一些特殊的接口,通过工具把元数据导出成
COM可用的组件库数据,然后注册给
OS。运行时,通过
CCW来动态的管理与维护
.net对象。而对于用户来说,他就像访问
COM一样访问
.net对象。
MSDN参考:
http://msdn2.microsoft.com/zh-cn/library/8bwh56xe(VS.80).aspx http://msdn2.microsoft.com/zh-cn/library/e753eftz(vs.80).aspx 下载文档:
1、VS2003COM开发插件。
http://www.cnblogs.com/Files/WuCountry/CSComSetup.zip 2、示例项目代码。
http://www.cnblogs.com/Files/WuCountry/Webb.PublicCOM.zip 3、本文
doc文档。
http://www.cnblogs.com/Files/WuCountry/TempDoc.zip from:
http://www.cnblogs.com/topboy/archive/2007/01/22/627152.html