Blue Theme Orange Theme Green Theme Red Theme
 
6 Months Free & No Setup Fees ASP.NET Hosting!
Home | Forums | ASP.NET 2.0 Tutorials | Web Services | How Do I...? | Class Browser | WPF Quick Starts | Advertise with Us
 | Consulting  
Submit an Article Submit a Blog 
 Jump to
Skip Navigation Links
TechnologyExpand Technology
WebsiteExpand Website
6 Months Free & No Setup Fees ASP.NET Hosting!
Search :       Advanced Search »
Home » DLL/ActiveX » ActiveX using MFC : Inside/Out

ActiveX using MFC : Inside/Out

A tutorial that explains how to create an activeX using ControlWizard and how control wizard works under the hood.

Author Rank :
Page Views : 20255
Downloads : 149
Rating :
 Rate it
Level : Intermediate
   Print Read/Post comments Post a comment  Similar Articles  
   Email to a friend  Bookmark  Author's other articles  
Download Files:
mcfirstx.zip
 
 
6 Months Free & No Setup Fees ASP.NET Hosting!
Become a Sponsor
 Tag Cloud
 Latest Jobs
More ... 
 Latest Interview Questions
More ... 

There are different ways to develop ActiveX controls for VC++ developers.

  • Using MFC
  • Using ATL
  • Using BaseCtl framework

This tutorial guides you towards how to create your activeX control using MFC ActiveX ControlWizard. This
article also explains how ControlWizard works under the hood.

1. Creating and Understand Skeleton

First step is to create skeleton using MFC ActiveX ControlWizard. Create new project and select MFC ActiveX
ControlWizard.



Leave default settings on second page of the wizard. Click Next and Finish.

Now if you go to ClassView of your project, It looks like this:

Few clicks and skeleton of your control is ready. Great. But do you know how much work ControlWizard did for you?

Under the hood

Now let's see what ControlWizard does under the hood. Let's see classes one by one.

CMFCFirstXApp is the application class. This class is derived from COleControlModule which is derived from
CWinApp. COleControlModule class provides member functions for initializing your control module. Each OLE
control module that uses MFC can only contain one object derived from COleControlModule. This class has two
member functions InitInstance and ExitInstance. InitInstance calls COleControlModule::InitInstance() and
ExitInstance calls COleControlModule::ExitInstance(). See WinApp's InitInstance and ExitInstance for more
details.

// CMcFirstXApp::InitInstance - DLL initialization
BOOL CMcFirstXApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();
if (bInit)
{
// TODO: Add your own module initialization code here.
}
return bInit;
}
// CMcFirstXApp::ExitInstance - DLL termination
int CMcFirstXApp::ExitInstance()
{
// TODO: Add your own module termination code here.
return COleControlModule::ExitInstance();
}

CMFCFirstXCtrl is the control class. This class is derived from COleControl which is derived from CWnd. So we
do anything similar to CWnd. This class is responsible for creating a window and an ellipse on it. This class will
have implementation for your control including all functions implementing methods, properties and events.

When you see this cpp class, it starts with IMPLEMENT_DYNACREATE. After that it has three maps, a message
map, dispatch map and event map. CMFCFirstXCtrl's message map is similar to MFC's message map, the
dispatch map contains entries for all the properties and methods you implement, and the event map contains
entries for all the events you fire.

Now, here are some macros for adding property page.

// TODO: Add more property pages as needed. Remember to increase the count!
BEGIN_PROPPAGEIDS(CMcFirstXCtrl, 1)
PROPPAGEID(CMcFirstXPropPage::guid)
END_PROPPAGEIDS(CMcFirstXCtrl)

Next lines are for class factory, type library and interface ids.

// Initialize class factory and guid
IMPLEMENT_OLECREATE_EX(CMcFirstXCtrl, "MCFIRSTX.McFirstXCtrl.1",
0x669df27e, 0x985e, 0x11d4, 0xb2, 0x4b, 0, 0x60, 0xb0, 0xee, 0x76, 0x7)
// Type library ID and version
IMPLEMENT_OLETYPELIB(CMcFirstXCtrl, _tlid, _wVerMajor, _wVerMinor)
// Interface IDs
const IID BASED_CODE IID_DMcFirstX =
{ 0x669df27c, 0x985e, 0x11d4, { 0xb2, 0x4b, 0, 0x60, 0xb0, 0xee, 0x76, 0x7 } };
const IID BASED_CODE IID_DMcFirstXEvents =
{ 0x669df27d, 0x985e, 0x11d4, { 0xb2, 0x4b, 0, 0x60, 0xb0, 0xee, 0x76, 0x7 } };
// Control type information
static const DWORD BASED_CODE _dwMcFirstXOleMisc =
OLEMISC_ACTIVATEWHENVISIBLE | OLEMISC_SETCLIENTSITEFIRST | OLEMISC_INSIDEOUT |
OLEMISC_CANTLINKINSIDE | OLEMISC_RECOMPOSEONRESIZE;
IMPLEMENT_OLECTLTYPE(CMcFirstXCtrl, IDS_MCFIRSTX, _dwMcFirstXOleMisc)

_dwMcFirstXOleMisc tells what kind of control is it. This variable is passed to AfxOLERegisterControlClass as
a parameter. BOOL CMcFirstXCtrl::CMcFirstXCtrlFactory::UpdateRegistry(BOOL bRegister), registers and
unregisters the control's OLE class. Next code lines are two constructors. Calling COleControl's InitializeIIDs
&IID_DMcFirstX, &IID_DMcFirstXEvents); function informs that the base class of the interface IDs your control
will be using.

// CMcFirstXCtrl::CMcFirstXCtrl - Constructor
CMcFirstXCtrl::CMcFirstXCtrl()
{
InitializeIIDs(&IID_DMcFirstX, &IID_DMcFirstXEvents);
// TODO: Initialize your control's instance data here.
}
// CMcFirstXCtrl::~CMcFirstXCtrl - Destructor
CMcFirstXCtrl::~CMcFirstXCtrl()
{
// TODO: Cleanup your control's instance data here.
}

Next function is Overridden OnDraw which just draws an ellipse on the window. Similar to CWnd's OnDraw.
void CMcFirstXCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
// TODO: Replace the following code with your own drawing code.
pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
pdc->Ellipse(rcBounds);
}

Next DoPropExchange is used when saving the control's properties to the container or loading them from the
container.

void CMcFirstXCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
// TODO: Call PX_ functions for each persistent custom property.
}

OnResetState is called when the control should reset its state to the default initial state.

void CMcFirstXCtrl::OnResetState()
{
COleControl::OnResetState();  // Resets defaults found in DoPropExchange
// TODO: Reset any other control state here.
}

Last, and perhaps least, is OnAbout, which displays your control's About box.

void CMcFirstXCtrl::AboutBox()
{
CDialog dlgAbout(IDD_ABOUTBOX_MCFIRSTX);
dlgAbout.DoModal();
}

CMFCFirstXPropPage is the your control's property page class. This class is derived from COlePropertyPage.
This class will have implementation for your control's property page. It has the message map and
DoDataExchange function that all MFC dialog boxes use. In addition to that, it's declared for dynamic and OLE
creation via the IMPLEMENT_DYNCREATE and IMPLEMENT_OLECREATE_EX macros (and their corresponding
DECLARE_ variants in the header file). There is one more function BOOL
McFirstXPropPage::CMcFirstXPropPageFactory::UpdateRegistry( BOOL bRegister), which registers and
unregisters the property page with OLE. This function will be called by MFC when the control is being initialized
and destroyed.

Global Members There are four global members. DllRegisterServer, DllUnregisterServer, the interface ID
IID_DMcFirstX, and CMcFirstXApp global instance theApp.

Let's see DllRegisterServer and DllUnregisterServer functions:

// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
return ResultFromScode(SELFREG_E_CLASS);
return NOERROR;
}
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
AFX_MANAGE_STATE(_afxModuleAddrThis);
if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
return ResultFromScode(SELFREG_E_TYPELIB);
if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
return ResultFromScode(SELFREG_E_CLASS);
return NOERROR;
}

Other Files

Let's see what ActiveX ControlWizard writes under the hood.

It has generated a .rc resource file, an .ODL file, a .DEF file, and a .CPP and .H file for each class we have
discussed earlier and stdafx.h and cpp files. The mcfirst.rc and mcfirst.def files are the standard resource and
linker definition files. The mcfirst.odl file contains type information for OLE.

2. ActiveX Control and Its Components

ActiveX has are four basic components. Before adding any functionality to our control, let's see its components.

  • Methods
  • Properties
  • PropertyPages
  • Events

Methods

Methods are functions implemented inside an activeX. They are accessible via control's wrapper class from a
client program. There are two types of methods, stock and custom. MFC provides two stock methods, DoClick
and Refresh.

Adding an Method

You don't have to write any code for stock methods. Right click on your interface and select Add Method from
Menu will display this dialog box.

If you add DoClick method, ControlWizard writes a single line of code in your dispatch map section and your odl
file's method's section looks like this:

methods:

// NOTE - ClassWizard will maintain method information here.
// Use extreme caution when editing this section.
//{{AFX_ODL_METHOD(CMcFirstXCtrl)
[id(DISPID_DOCLICK)] void DoClick();
//}}AFX_ODL_METHOD

and dispatch map looks like this:

And here is dispatch map. Bold line is added after adding the method.

// Dispatch map
BEGIN_DISPATCH_MAP(CMcFirstXCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CMcFirstXCtrl)
DISP_STOCKFUNC_DOCLICK()
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CMcFirstXCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()

Custom methods are the functions added by you. Here is how I add TestMessage method.

After adding TestMessage, odl file and massage map looks like this:

methods:

// NOTE - ClassWizard will maintain method information here.
//    Use extreme caution when editing this section.
//{{AFX_ODL_METHOD(CMcFirstXCtrl)
[id(DISPID_DOCLICK)] void DoClick();
[id(1)] void TestMessage();
//}}AFX_ODL_METHOD

And here is dispatch map. Bold line is added after adding the method.

// Dispatch map
BEGIN_DISPATCH_MAP(CMcFirstXCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CMcFirstXCtrl)
DISP_FUNCTION(CMcFirstXCtrl, "TestMessage", TestMessage, VT_EMPTY, VTS_NONE)
DISP_STOCKFUNC_DOCLICK()
//}}AFX_DISPATCH_MAP
DISP_FUNCTION_ID(CMcFirstXCtrl, "AboutBox", DISPID_ABOUTBOX, AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()

Here VT_EMPTY means that the return type of the Next method is void, and VTS_NONE means that the
TestMessage method takes no parameters. If the method had a return value, its return type constant
(VT_xxx) would replace VT_EMPTY. If it took parameters, the types of the parameters would be represented
by a comma-separated list of parameter type constants (VTS_xxx) instead of VTS_NONE. The list of
constants is in the MFC documentation for DISP_FUNCTION. Besides these two changes, ControlWizard adds
TestMessage function to your CMcFirstXCtrl class. Here is how it it looks like now:

Properties

An activeX control exposes its variables through it properties. There are two types of control properties: Stock
and Custom. Custom properties are implemented by you. ClassWizard offers two ways to implement a custom
property: as a pair of Get/Set methods, or as a member variable.  Stock Properties is a set of properties
implemented by MFC. To use them, just add them to your control with ClassWizard—the code is already there to
implement the properties. You can add these properties using ControlWizard. Select Add Property from your
interface's right click, you will get this dialog:

Here you can add your property or add an existing one. If you select Stock option, wizard write code for you. If
your property is a custom then you have two choices i.e., either member variable or get/set method. First
option adds one variable to your code. This variable is accessible from clients. Clients can sent its value.


Other option is to use Get/Set pair. This option adds two functions to your control class. Say if you add a
property Color by using Get/Set method then Wizard will add GetColor and SetColor functions to your control
class. How to add these we will see in our next step.


ProperyPages

We have already seen that ControlWizards adds a COlePropertyPage derived class to every activex. This class
COlePropertyPage is derived from CDialog. So you can use your property page class as a dialog. Property pages
are used to allow visual implementation of control's properties. By using these pages, you can set control's
properties.

Events

Events are the notifications your control sends to its container when something has happened. Controls have
two types of events, custom and stock. MFC provides about a dozen stock events, mainly having to do with
mouse clicks and key presses.

Adding an Event

You can add an event by right clicking on your control's event interface. Its _DMcFirstXEvents in this picture.

Now let's add Click event by selecting Add Event on Right mouse click.

This action updates odl file's CMcFirstXCtrl interface section. See bold line here.

//  Event dispatch interface for CMcFirstXCtrl
[ uuid(669DF27D-985E-11D4-B24B-0060B0EE7607), helpstring("Event interface for McFirstX Control") ]
dispinterface _DMcFirstXEvents
{
properties:
//  Event interface has no properties methods:
// NOTE - ClassWizard will maintain event information here.
//    Use extreme caution when editing this section.
//{{AFX_ODL_EVENT(CMcFirstXCtrl)
[id(DISPID_CLICK)] void Click();
//}}AFX_ODL_EVENT
};

as well as event map. Bold line is added after adding the event.

// Event map
BEGIN_EVENT_MAP(CMcFirstXCtrl, COleControl)
//{{AFX_EVENT_MAP(CMcFirstXCtrl)
EVENT_STOCK_CLICK()
//}}AFX_EVENT_MAP
END_EVENT_MAP()

You can add your custom events too. You can pass your parameters to provide more information about the
situation. We don't have any custom event in our sample example.

3. Implementation

Ok, now let's see actual implementation of an ActiveX Control. This activeX will display AVI files. Add one
method to this activeX called ViewAVI. This function takes avi file name as an input parameter.


Go to your project's setting's Link option and link with vfw32.lib and winmm.lib files #include "vfw.h".

Now add this below code to ViewAvi finction of your control class:

void CMcFirstXCtrl::ViewAVi(LPCTSTR szFileName)
{
HWND mciHWnd;
if(m_mciHWnd)
{
MCIWndDestroy(m_mciHWnd);
m_mciHWnd = NULL;
Invalidate();
}
mciHWnd = MCIWndCreateA((HWND)this->m_hWnd,AfxGetInstanceHandle(), MCIWNDF_NOTIFYPOS|MCIWNDF_NOTIFYALL|MCIWNDF_NOMENU ,FileName);
if ( mciHWnd )
{
MCI_SET_PARMS setParam;
setParam.dwCallback = (DWORD)this->m_hWnd;
setParam.dwTimeFormat = MCI_SET_TIME_FORMAT|MCI_FORMAT_FRAMES;
setParam.dwAudio = MCI_SET_OFF;
mciSendCommand(MCIWndGetDeviceID(mciHWnd), MCI_SET, MCI_NOTIFY, (DWORD) (LPMCI_SET_PARMS)setParam);
m_mciHWnd = mciHWnd;

Build your project. Your ocx is ready to use now. Now you can insert this control in a dialog based application
and call its ViewAvi method to view avi files.
}

How to Use the ActiveX?

Create a dialog based application.

Insert the ActiveX

Insert your AviOcx1.ocx ActiveX by using Project->Add To Project->Components and Controls menu item.
This action adds one control to your controls list and one wrapper class to your project. Say my class is
CAviOcx1. Now drag the ActiveX on your dialog.

Add a Variable corresponding to the control by using ClassWizard.

Now call ViewDoc of activeX on OnInitDialog with an AVI file name as a parameter.

m_ctrl.ViewAVi("C:\\Winnt\\clock.avi");

Here is the result.

Comment Request!
Thank you for reading this post. Please post your feedback, question, or comments about this post Here.
Login to add your contents and source code to this article
 [Top] Rate this article
 
 About the author
 
Mahesh Chand
Mahesh is the founder of C# Corner and Mindcracker Network, an author of several .NET programming books and a Microsoft MVP for 6 consecutive years. In his day to day work, Mahesh is a Senior Software Consultant with over 14 years of IT industry experience building systems for Financial and Banking, Engineering & Architectural, Imaging, Construction, Biological & Pharmaceuticals, Healthcare and Education industries. His expertise is Windows Forms, ASP.NET, Silverlight, WPF, WCF, Visual Studio 2010, SQL Server, and Oracle.  If you are looking for a Sharepoint, Windows Forms, ASP.NET, WPF, Silverlight, C#, VB.NET, Oracle, and SQL Server Consultant in Philadelphia area or remote location, drop me a line at MAHESH [AT] C-SHARPCORNER [DOT] COM.
Looking for C# Consulting?
C# Consulting is founded in 2002 by the founders of C# Corner. Unlike a traditional consulting company, our consultants are well-known experts in .NET and many of them are MVPs, authors, and trainers. We specialize in Microsoft .NET development and utilize Agile Development and Extreme Programming practices to provide fast pace quick turnaround results. Our software development model is a mix of Agile Development, traditional SDLC, and Waterfall models.
Click here to learn more about C# Consulting.
 
Introducing MaxV - one click. infinite control. Hyper-V Hosting from MaximumASP.
Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
Dynamic PDF
ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications.
Nevron Chart for .NET 2010.1 Now Available
The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
ASP.NET 4 Hosting
Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites – Click Here!
 
 Post a Feedback, Comment, or Question about this article
Subject:
Comment:
Nevron Gauge for SharePoint
Become a Sponsor
 Comments
m_mciHWnd declaration! by khalfi On January 2, 2010
m_mciHWnd
i don't know where to declare this variable
Reply | Email | Modify 
6 Months Free & No Setup Fees ASP.NET Hosting!
 © 2012  contents copyright of their authors. Rest everything copyright Mindcracker. All rights reserved.