Standard Library Functions (STDLIB.H)

Chapter 26 - Getting Started with ActiveX Controls

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

Creating a Simple ActiveX Control with the MFC
In this section, you will learn the step-by-step approach to creating a simple ActiveX control template. Then we will modify the template to create a unique control for our use.
Remember that all of Microsoft’s wizards generate MFC library code. If you need to review object-oriented coding techniques using the MFC, study the material in Chapters 22 through 25.
From this point on, the MFC ActiveX ControlWizard will be referred to simply as the ControlWizard.
Creating a Basic ActiveX Control
From the Microsoft Visual C++ menu bar, select the File | New menu item. From the New dialog box, select the MFC ActiveX ControlWizard, as shown in Figure 26-1. Name this project TDCtrl.
Figure 26-1: Use the New dialog box to select the MFC ActiveX ControlWizard
Step 1, in the two-step process, allows you to select a variety of options including the number of controls, source code comments, and so on. Accept the default settings, as shown in Figure 26-2.
Figure 26-2: Step 1—Accept the ActiveX control design defaults for this initial control
Step 2 allows additional design features to be added to the control. Again, accept the default settings as shown in Figure 26-3.
Figure 26-3: Step #2—Accept the default settings
Figure 26-4 shows a summary of the new control’s specifications just prior to generating the code.
Figure 26-4: A summary of specifications for the new control
When the OK button is clicked in the New Project Information dialog box, the ControlWizard will generate the files necessary to create the basic control. Figure 26-5 shows a list of classes and global values for this control.
Figure 26-5: A list of classes and globals for the TDCtrl ActiveX control
The TDCtrl control can now be built using the Build | Build or Build | Rebuild All menu selection. When this operation is complete, a new control with the filename TDCTRL.OCX will be located in the appropriate subdirectory.
ActiveX controls are small DLL files that can be tested in the appropriate container. Until the control is complete, it is best to use a test container to examine your control’s operation. Microsoft provides the ActiveX Control Test Container. This container is accessed from the Tools menu, as shown in Figure 26-6.
Figure 26-6: The new control can be tested in the ActiveX Control Test Container
When you start the test container, you will have to select the TDCtrl control from the test container’s Edit | Insert New Control menu. When this selection is made, the Insert Control dialog box will display a list of registered controls. Scroll down the list till you find the TDCtrl control, as shown in Figure 26-7.
Figure 26-7: The new TDCtrl is found in the list of registered controls
The registered control list will vary as you increase and decrease registered controls on your system. You should be able to find the TDCtrl, however.
When you click the mouse on the OK button in the Insert Control dialog box, the control will be brought into the test container, as you can see in Figure 26-8.
Figure 26-8: The new TDCtrl ActiveX control is displayed in the ActiveX Control Test Container
The actual control is graphically just the ellipse shape that you see surrounded by a design frame. At this point the control is not really functional. We will have to add some code to this template to create a unique control for our purposes.
Before we modify the template code, let’s look at the code generated by the ControlWizard. We’ll examine the code specifically related to the changes we’re about to make to the template.
A Look at Important Code
A detailed analysis of the code for the whole TDCtrl project is beyond the scope of this book. Actually, it would probably require a whole book itself. However, you don’t have to be an automobile mechanic to drive a car, and you certainly don’t have to understand every nuance of program code to build effective ActiveX controls. You have learned the basics of how the MFC combines object-oriented objects into complete applications.
The ControlWizard generates four C++ files for most ActiveX controls. In this example they are named STDAFX.CPP, TDCTRL.CPP, TDCTRLCTL.CPP, and TDCTRLPPG.CPP. These files are supported with their appropriate support header files.
The STDAFX.CPP file is used to include all the standard header files that your ActiveX control will need. The TDCTRL.CPP file is responsible for the implementation of the CTDCtrlApp class and the registration of the subsequent DLL file.
In the following sections we examine the role of the TDCTRLCTL.CPP and TDCTRLPPG.CPP files in more detail.
The TDCTRLCTL.CPP File
The TDCTRLCTL.CPP file provides the actual implementation of the ActiveX control’s OLE class. In this example, that class is CTDCtrlCtrl. This is the file you will most likely spend most of your time editing. In this file, you will be able to create unique implementations of your ActiveX control from the default ActiveX control created by the ControlWizard.
Let’s examine the specific code allotted to the default ActiveX control. Study the following listing:
// TDCtrlCtl.cpp : the CTDCtrlCtrl ActiveX Control class.

#include “stdafx.h”
#include “TDCtrl.h”
#include “TDCtrlCtl.h”
#include “TDCtrlPpg.h”


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNCREATE(CTDCtrlCtrl, COleControl)


//////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CTDCtrlCtrl, COleControl)
 //{{AFX_MSG_MAP(CTDCtrlCtrl)
 // NOTE - ClassWizard will add/remove message map entries
 //    DO NOT EDIT these blocks of generated code !
 //}}AFX_MSG_MAP
 ON_OLEVERB(AFX_IDS_VERB_PROPERTIES, OnProperties)
END_MESSAGE_MAP()


//////////////////////////////////////////////////////////////
// Dispatch map
BEGIN_DISPATCH_MAP(CTDCtrlCtrl, COleControl)
 //{{AFX_DISPATCH_MAP(CTDCtrlCtrl)
 // NOTE - ClassWizard will add/remove dispatch map entries
 //    DO NOT EDIT these blocks of generated code !
 //}}AFX_DISPATCH_MAP
 DISP_FUNCTION_ID(CTDCtrlCtrl, “AboutBox”, DISPID_ABOUTBOX,
                  AboutBox, VT_EMPTY, VTS_NONE)
END_DISPATCH_MAP()

//////////////////////////////////////////////////////////////
// Event map

BEGIN_EVENT_MAP(CTDCtrlCtrl, COleControl)
 //{{AFX_EVENT_MAP(CTDCtrlCtrl)
 // NOTE - ClassWizard will add/remove event map entries
 //    DO NOT EDIT these blocks of generated code !
 //}}AFX_EVENT_MAP
END_EVENT_MAP()


//////////////////////////////////////////////////////////////
// Property pages

// TODO: Add more property pages as needed.
// Also increase the count!
BEGIN_PROPPAGEIDS(CTDCtrlCtrl, 1)
 PROPPAGEID(CTDCtrlPropPage::guid)
END_PROPPAGEIDS(CTDCtrlCtrl)

//////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CTDCtrlCtrl, “TDCTRL.TDCtrlCtrl.1",
                      0xc0377506, 0xb276, 0x11d1, 0xba, 0xe9,
                      0, 0xa0, 0xc9, 0x8c, 0xc4, 0x6e)


//////////////////////////////////////////////////////////////
// Type library ID and version

IMPLEMENT_OLETYPELIB(CTDCtrlCtrl,_tlid,_wVerMajor,_wVerMinor)

//////////////////////////////////////////////////////////////
// Interface IDs

const IID BASED_CODE IID_DTDCtrl =
   { 0xc0377504, 0xb276, 0x11d1, { 0xba, 0xe9, 0, 0xa0, 0xc9,
                                   0x8c, 0xc4, 0x6e } };
const IID BASED_CODE IID_DTDCtrlEvents =
   { 0xc0377505, 0xb276, 0x11d1, { 0xba, 0xe9, 0, 0xa0, 0xc9,
                                   0x8c, 0xc4, 0x6e } };

//////////////////////////////////////////////////////////////
// Control type information

static const DWORD BASED_CODE _dwTDCtrlOleMisc =
 OLEMISC_ACTIVATEWHENVISIBLE |
 OLEMISC_SETCLIENTSITEFIRST |
 OLEMISC_INSIDEOUT |
 OLEMISC_CANTLINKINSIDE |
 OLEMISC_RECOMPOSEONRESIZE;

IMPLEMENT_OLECTLTYPE(CTDCtrlCtrl,IDS_TDCTRL,_dwTDCtrlOleMisc)

//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::CTDCtrlCtrlFactory::UpdateRegistry -
// Adds or removes system registry entries for CTDCtrlCtrl

BOOL CTDCtrlCtrl::CTDCtrlCtrlFactory::UpdateRegistry \
    (BOOL bRegister)
{
 // TODO: Verify control follows apartment-model threading
 // rules.
 // Refer to MFC TechNote 64 for more information.
 // If your control does not conform to the apartment-model
 // rules, then modify the code below, changing the 6th
 // parameter from afxRegApartmentThreading to 0.
 if (bRegister)
   return AfxOleRegisterControlClass(
     AfxGetInstanceHandle(),
     m_clsid,
     m_lpszProgID,
     IDS_TDCTRL,
     IDB_TDCTRL,
     afxRegApartmentThreading,
     _dwTDCtrlOleMisc,
     _tlid,
     _wVerMajor,
     _wVerMinor);
 else
   return AfxOleUnregisterClass(m_clsid, m_lpszProgID);
}

//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::CTDCtrlCtrl - Constructor

CTDCtrlCtrl::CTDCtrlCtrl()
{
 InitializeIIDs(&IID_DTDCtrl, &IID_DTDCtrlEvents);

 // TODO: Initialize your control’s instance data here.
}

//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::~CTDCtrlCtrl - Destructor

CTDCtrlCtrl::~CTDCtrlCtrl()
{
 // TODO: Cleanup your control’s instance data here.
}


//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::OnDraw - Drawing function

void CTDCtrlCtrl::OnDraw(
     CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
   // TODO: Replace following code with your own drawing code.
   pdc->FillRect(rcBounds,
  CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));

   pdc->Ellipse(rcBounds);
}

//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::DoPropExchange - Persistence support

void CTDCtrlCtrl::DoPropExchange(CPropExchange* pPX)
{
 ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
 COleControl::DoPropExchange(pPX);

 // TODO: Call PX_ functions for persistent custom property.
}

//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::OnResetState - Reset control to default state

void CTDCtrlCtrl::OnResetState()
{
 COleControl::OnResetState();

 // TODO: Reset any other control state here.
}


//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::AboutBox - Display an ”About" box to the user
void CTDCtrlCtrl::AboutBox()
{
 CDialog dlgAbout(IDD_ABOUTBOX_TDCTRL);
 dlgAbout.DoModal();
}


//////////////////////////////////////////////////////////////
// CTDCtrlCtrl message handlers
The message map, dispatch map, and event map are automatically created and edited by the Microsoft wizards. Under most circumstances, you will not edit these maps directly.
Recall that message maps are important because they provide an alternative to the switch statement used in procedure-oriented programs to handle messages. Automation includes techniques to call methods and access properties across several applications. These requests are dispatched via the dispatch map. The event map helps process ActiveX control events.
Examine the listing and notice the section of code used to implement the type library. In general, ActiveX controls need to exchange information concerning various properties and methods. The best way to provide this information is through a type library.
As you continue reading down the listing, you will see code for updating the system registry as well as constructor code for initializing instances of the control.
The OnDraw( ) member function is going to be of immediate interest to us, because it is this section of code that draws the graphics for the control. In the default control provided by the ControlWizard, the default shape is an Ellipse( ).
/////////////////////////////////////////////////////////////
// CTDCtrlCtrl::OnDraw - Drawing function

void CTDCtrlCtrl::OnDraw(
     CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
 // TODO: Replace following code with your own drawing code.
 pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
 pdc->Ellipse(rcBounds);
}
The ControlWizard also designed a default About box for this project. The contents of this simple dialog box can be edited to suit your project’s needs or used as is. You’ll find the resource information in the TDCTRL.RC resource file. The About dialog box is brought to the screen with the following portion of code:
//////////////////////////////////////////////////////////////
// CTDCtrlCtrl::AboutBox - Display an “About” box to the user

void CTDCtrlCtrl::AboutBox()
{
 CDialog dlgAbout(IDD_ABOUTBOX_TDCTRL);
 dlgAbout.DoModal();
}
Notice that the default About box is a standard modal dialog box of the type we have been using since Chapter 22.
The TDCTRLPPG.CPP File
This file derives the CTDCtrlPropPage class from Microsoft’s COlePropertyPage class. Examine the following listing:
// TDCtrlPpg.cpp : the CTDCtrlPropPage property page class.

#include “stdafx.h”
#include “TDCtrl.h”
#include “TDCtrlPpg.h”

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


IMPLEMENT_DYNCREATE(CTDCtrlPropPage, COlePropertyPage)


//////////////////////////////////////////////////////////////
// Message map

BEGIN_MESSAGE_MAP(CTDCtrlPropPage, COlePropertyPage)
 //{{AFX_MSG_MAP(CTDCtrlPropPage)
 // NOTE - ClassWizard will add/remove message map entries
 //    DO NOT EDIT these blocks of generated code !
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////
// Initialize class factory and guid

IMPLEMENT_OLECREATE_EX(CTDCtrlPropPage,
                      “TDCTRL.TDCtrlPropPage.1",
                      0xc0377507, 0xb276, 0x11d1, 0xba, 0xe9,
                      0, 0xa0, 0xc9, 0x8c, 0xc4, 0x6e)


//////////////////////////////////////////////////////////////
// CTDCtrlPropPage::CTDCtrlPropPageFactory::UpdateRegistry -
// Adds or removes system registry entries for CTDCtrlPropPage

BOOL CTDCtrlPropPage::CTDCtrlPropPageFactory::UpdateRegistry \
    (BOOL bRegister)
{
 if (bRegister)
   return AfxOleRegisterPropertyPageClass \
         (AfxGetInstanceHandle(),
         m_clsid, IDS_TDCTRL_PPG);
 else
   return AfxOleUnregisterClass(m_clsid, NULL);
}

//////////////////////////////////////////////////////////////
// CTDCtrlPropPage::CTDCtrlPropPage - Constructor

CTDCtrlPropPage::CTDCtrlPropPage() :
 COlePropertyPage(IDD, IDS_TDCTRL_PPG_CAPTION)
{
 //{{AFX_DATA_INIT(CTDCtrlPropPage)
 // NOTE: ClassWizard will add member initialization here
 //    DO NOT EDIT these blocks of generated code !
 //}}AFX_DATA_INIT
}

//////////////////////////////////////////////////////////////
// CTDCtrlPropPage::DoDataExchange - Moves data between
// page and properties

void CTDCtrlPropPage::DoDataExchange(CDataExchange* pDX)
{
 //{{AFX_DATA_MAP(CTDCtrlPropPage)
 // NOTE: ClassWizard will add DDP, DDX, and DDV calls here
 //    DO NOT EDIT these blocks of generated code !
 //}}AFX_DATA_MAP
 DDP_PostProcessing(pDX);
}


//////////////////////////////////////////////////////////////
// CTDCtrlPropPage message handlers
The AfxOleRegisterPropertyPageClass( ) function is used to register the property page class with the registration database. This permits the property page to be used by other containers that are made aware of ActiveX controls. The registry, with the property page name and its location on the system, will be updated after this function is called.
Notice in this file that COlePropertyPage, from which our CTDCtrlPropPage class is derived, can use the constructor to identify the dialog-template resource on which the property page is based and also the string resource containing the caption.
The DoDataExchange( ) function is generally used by the framework to exchange and validate dialog data. Here, the specific job is to move data between the page and properties of the control.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net