Click here to Skip to main content
15,881,687 members
Articles / Programming Languages / C#

Exposing Windows Forms Controls as ActiveX controls

Rate me:
Please Sign up or sign in to vote.
4.86/5 (33 votes)
27 Aug 20014 min read 781.9K   9.4K   180  
This article describes how to build a Windows Forms control in C# and expose it as an ActiveX control
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 Prisoner
{
	///	<summary>
	///	Summary	description	for	UserControl1.
	///	</summary>
	[ProgId("Prisoner.PrisonerControl")]
	[ClassInterface(ClassInterfaceType.AutoDual)]
	public class PrisonerControl : System.Windows.Forms.UserControl
	{
		private	System.Windows.Forms.PictureBox	pictureBox1;
		private	System.Windows.Forms.Label label1;
		///	<summary>
		///	Required designer variable.
		///	</summary>
		private	System.ComponentModel.Container	components = null;

		public PrisonerControl()
		{
			// This	call is	required by	the	Windows.Forms Form Designer.
			InitializeComponent();

			// TODO: Add any initialization	after the InitForm 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	);
		}

		#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(PrisonerControl));
			this.pictureBox1 = new System.Windows.Forms.PictureBox();
			this.label1	= new System.Windows.Forms.Label();
			this.SuspendLayout();
			// 
			// pictureBox1
			// 
			this.pictureBox1.Image = ((System.Drawing.Bitmap)(resources.GetObject("pictureBox1.Image")));
			this.pictureBox1.Location =	new	System.Drawing.Point(8,	8);
			this.pictureBox1.Name =	"pictureBox1";
			this.pictureBox1.Size =	new	System.Drawing.Size(112, 120);
			this.pictureBox1.TabIndex =	0;
			this.pictureBox1.TabStop = false;
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(8, 136);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(328,	40);
			this.label1.TabIndex = 1;
			this.label1.Text = "I am not a number, I am	a free man.";
			// 
			// PrisonerControl
			// 
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.label1,
																		  this.pictureBox1});
			this.Name =	"PrisonerControl";
			this.Size =	new	System.Drawing.Size(344, 184);
			this.ResumeLayout(false);

		}
		#endregion

		public void	Question ( )
		{
			MessageBox.Show	( "Who is number one?" ) ;
		}

		///	<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	( )	;
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Founder MS Application Development Consulting Ltd
United Kingdom United Kingdom
I started work in 1989 for LabSystems, based in Altrincham. I had originally expected to stay for six months, but the job was so good I stayed for 12.5 years.

In December 2001 I joined Microsoft as an Application Development Consultant, where I spent lots of time assisting customers with their use of Microsoft technologies.

I left in June 2011 to start my own business, and I do contract development, knowledge sharing and bespoke application development.

Comments and Discussions