SAMPLE: DlgX2.exe Creates a Composite ActiveX Control with MFC
  
PSS ID Number: Q198849
Article last modified on 05-26-1999
 
winnt:5.0,6.0
 
winnt
 

======================================================================
-------------------------------------------------------------------------------
The information in this article applies to:
 
 - Microsoft Visual C++, 32-bit Editions, versions 5.0, 6.0 
-------------------------------------------------------------------------------
 
SUMMARY
=======
 
DlgX2.exe is a sample that shows how to create a composite ActiveX control; that
is, an ActiveX control that uses a dialog box template to create its main window
and all of its child windows.
 
Within this sample you will find two project files:
 
    - DlgX2.VC5.dsw
 - DlgX2.VC6.dsw
 
As the names imply, the first project file is a Visual C++ 5.0 project and the
second is a Visual C++ 6.0 project. Also note that these projects contain the
dependent project, Circ3, for completeness.
 
DlgX2 is an ActiveX control that uses a dialog box template resource to place
other controls within it.
 
Please see the MORE INFORMATION section for the following:
 
 - A description of the functionality in the class CFormControl, which
   implements creating the ActiveX control from a dialog box template and also
   handles most of the default button processing. DlgX2 then uses CFormControl
   and Class Wizard to add functionality.
 
 - A step-by-step procedure to convert an AppWizard-generated OLE control to one
   that uses CFormControl. Once the conversion is completed, you can USE Class
   Wizard to add functionality in much the same way you would for a dialog box.
 
MORE INFORMATION
================
 
The following file is available for download from the Microsoft Software
Library:
 
   DlgX2.exe (http://support.microsoft.com/download/support/mslfiles/DlgX2.exe)
 
Release Date: May-14-1999
 
For more information about downloading files from the Microsoft Software Library,
please see the following article in the Microsoft Knowledge Base:
 
   Q119591 How to Obtain Microsoft Support Files from Online Services
 
The DlgX2 Sample
----------------
 
The DlgX2 sample is a CFormControl-based ActiveX control. Using a dialog box
resource, it contains a slightly modified version of the Circ3 ActiveX control
that is part of the MFC/OLE control tutorial. On the dialog box resource are
three buttons: two edit buttons and a ComboBox control button. The buttons are
labeled Left, Center, and Right and affect the offset of the circle in the Circ3
control.
 
The "Caption" edit control is read-only and contains the text "Left," "Center,"
or "Right" depending on the actual offset of the circle in the Circ3 control.
The "Note" edit control allows the user to modify the value of the Circ3 Note
property at run time. Also notice that the modification of the Note property
occurs in real time; that is, as each character is typed.
 
The final control, which is a drop-down list, contains several phrases that when
chosen, place the phrase in the Note edit control and in the Note field of the
Circ3 control.
 
The CDlgX2Ctrl class contains the code specific to the sample. This sample also
shows some techniques for inner/outer ActiveX control property management.
 
The following classes contain all of the changes specific to the CFormControl
project:
 
Default Plus Minor Changes:
 
   CDlgX2App
   CDlgX2PropPage
   CWnd2
   CCirc3
 
Key Classes Containing the Majority of the Sample Code:
 
   CDlgX2Ctrl
   CFormControl
 
Disclaimer:
 
This sample can be used as a basis for developing your own form-based ActiveX
control. The limitations known at this time are listed below. Due to the nature
of the interaction between controls and containers, further issues may arise
that are beyond the scope of this sample.
 
Warnings and Known Limitations:
 
 - The CFormControl class uses header files located in the msdev\mfc\src
   directory, which are considered private to MFC. This sample may need to be
   modified to enable it to work with future versions of Visual C++.
 
 - Placing a form control inside a form control causes default-button processing
   to fail in some containers. This is due to the way some containers handle
   activation and deactivation of controls.
 
Information About the Implementation--A brief Description of the CFormControl Methods:
 
 - CFormControl::CFormControl initializes member variables, calling
   MAKEINTRESOURCE if necessary. The dialog box template size in pixels is also
   initialized so that it can be used in OnSetExtent.
 
 - OnSetExtent can initialize the control to the size of the dialog box template
   it was created from. This functionality is typically determined by a
   parameter in the constructor, which defaults to Auto Size. This parameter
   sets the m_bAutoSize member variable of CFormControl, which can be changed
   programmatically.
 
 - CFormControl::CreateControlWindow creates m_hWnd using CreateDlg, which
   creates the window using the dialog box resource parameter in the
   constructor. COleControl::CreateControlWindow became virtual in Visual C++
   4.2.
 
 - CFormControl::PreTranslateMessage first checks to see if the child with the
   focus is an ActiveX control and if so, gives it the first choice at the
   message. If the message is handled, check whether you are dealing with a
   dialog box navigation key (TAB, SHIFT+TAB, and the LEFT, RIGHT, UP, and DOWN
   arrow keys); if so, check and deal with dialog box boundary conditions.
   Otherwise, call PreTanslateInput letting MFC and Windows try to process the
   message.
 
 - CFormControl::OnSetFocus handles the situation when tabbing into the form
   control.
 
 - CFormControl::OnInitialUpdate is called by CreateControlWindow only when
   m_hWnd is being created for the OLE Control. The function is virtual to allow
   overriding the initial update code.
 
 - CFormControl::HandleInitDialog and CFormControl::SetOccDialogInfo were copied
   from CFormView to enable OLE Control containment.
 
 - CFormControl::OnDraw draws a default design-time representation of the
   control's border to help in the placement of the control on a form.
   CFormControl::OnDraw also displays a name for the control using the Extended
   Name property if available or the contents of m_sFormName.
 
 - Stop mouse messages sent to the form control and ignore them. This removes
   the form from actively participating in the UI, therefore making it appear to
   be part of the container.
 
Changes Needed to Convert a ControlWizard OLE Control Project to
Use the CFormControl Class:
 
The class names shown in the following sample code, such as "CMyFormControl"
(without the quotation marks) and "CMyButton" (without the quotation marks),
should be changed to the actual names used in your code. Please refer to the
DlgX2 sample for a complete example that uses the CFormControl class.
 
1. Start with an OLE control project created with ControlWizard.
 
2. Add the msdev\mfc\src directory as one of the directories that Developer
   Studio will search when looking for include files. This can be done as
   follows:
 
   1. On the Tools menu, click Options.
 
   2. Click the Directories tab.
 
   3. With Show directories for set to Include files, add the msdev\mfc\src
      directory. Note that the actual directory path may be different depending
      on where you installed Visual C++ to.
 
   If the MFC source code was not copied to the hard disk when Visual C++ was
   initially installed, it can be copied at a later time. To do this, run the
   setup program, select the Custom installation option, and under the Microsoft
   Foundation Class Libraries component make sure the Source Code component is
   selected.
 
   WARNING: There are two files being included from this directory: AfxImpl.h and
   CtlImpl.h. These files are subject to change in later versions of MFC and as
   such may break a project in the future.
 
3. Change the control base class from COleControl to CFormControl. Change all
   references in both the control's declaration and implementation files.
 
4. Add a #include statement for the FormCtrl.h file provided with the DlgX2
   sample to the beginning of the header file for the CFormControl derived
   class. For example:
 
   #include "FormCtrl\FormCtrl.h"
 
   The actual path needed may be different depending on where the FormCtrl.h file
   is located relative to your project.
 
5. Insert the FormCtrl.cpp and Wnd2.cpp files provided with the DlgX2 sample
   into the project. In Developer Studio, on the Project menu, click Add to
   Project, and then Files. The Insert Files into Project dialog box is
   displayed and can be used to browse for these files.
 
6. Add the following line to your control's InitInstance method:
 
   AfxEnableControlContainer();
 
7. In steps 8, 9, 10, 13, and 14, replace all references to CMyFormControl with
   the name of your control class.
 
8. Add the declaration of the DoDataExchange function to your control class's
   header and implementation files. For example:
 
   // header file
   virtual void DoDataExchange (CDataExchange* pDX);
 
   // implementation file
   void CMyFormControl::DoDataExchange (CDataExchange* pDX)
   {
     //{{AFX_DATA_MAP(CMyFormControl)
     //}}AFX_DATA_MAP
   }
 
9. Add ClassWizard data comments to the control class declaration where IDD_FORM
   is the ID of the dialog box template we will create in step 12:
 
   //{{AFX_DATA(CMyFormControl)
      enum { IDD = IDD_FORM };
   //}}AFX_DATA
 
10. Add ClassWizard data initialization comments to the implementation of the
   control class's constructor:
 
   //{{AFX_DATA_INIT(CMyFormControl)
   //}}AFX_DATA_INIT
 
11. Add a dialog box resource that contains the child controls you want to use
   and that has the following properties:
 
    - ID - IDD_FORM
 
    - Style - Child
 
    - More Styles - Control
 
    - Extended Styles - Control parent
 
    - Title bar - OFF
 
    - Border - NONE
 
12. Associate the dialog box resource with the control class:
 
   1. From the dialog resource open ClassWizard.
 
   2. ClassWizard will display a dialog box asking what you want to do with the
      new resource. Choose the option to Select an Existing Class. Click OK.
 
   3. The Select Class dialog box will be displayed. Choose your control class
      and click Select.
 
   4. ClassWizard will ask if you are sure you want to do this even though the
      selected class is not a dialog box class. Choose Yes.
 
   5. Choose OK to close ClassWizard.
 
13. Add the following to the constructor for the control class to initialize the
   base class. Use the following code:
 
   CMyFormControl::CMyFormControl():
       CFormControl(CMyFormControl::IDD, TRUE)
 
14. You may want to give some feedback to the developer using your control at
   design time. Edit your control's OnDraw method to call CFormControl::OnDraw
   if (m_hWnd == NULL). For example:
 
   void CMyFormControl::OnDraw(CDC* pdc,
                               const CRect& rcBounds,
                               const CRect& rcInvalid)
   {
      if (!m_hWnd) {
         CFormControl::OnDraw (pdc, rcBounds, rcInvalid);
      }else{
         CBrush* pOldBrush;
         CBrush bkBrush;
         bkBrush.CreateSolidBrush(TranslateColor(GetBackColor()));
 
         // Set the ForeColor property color and transparent background
         // mode into the device context
         pdc->SetTextColor(TranslateColor(GetForeColor()));
         pOldBrush = pdc->SelectObject(&bkBrush);
         pdc->SetBkMode(TRANSPARENT);
 
         // Paint the background using the BackColor property
         pdc->FillRect(rcBounds, &bkBrush);
 
         CRect rc(rcBounds);
         CPen* pOldPen = (CPen*)pdc->SelectStockObject(BLACK_PEN);
         pdc->DrawEdge(rc, EDGE_ETCHED, BF_RECT);
         pdc->SelectObject(pOldPen);
         pdc->SelectObject(pOldBrush);
      }
   }
 
15. If you are using the drawing code above, note that it is using the Stock
   properties BackColor and ForeColor. To add these to your control, follow
   these steps:
 
   a. Go to ClassWizard.
 
   b. Click the OLE Automation tab.
 
   c. Click the Add Property button.
 
   d. Use the drop-down combo box to choose BackColor.
 
   e. Click OK.
 
   f. Repeat steps c..e for the ForeColor property.
 
16. Full ClassWizard functionality is available at this point for developing the
   control.
 
Steps to Build the DlgX2 Sample
-------------------------------
 
1. Load the Circ3 project provided with the sample into Developer Studio and
   build the project. This will build and register the modified Circ3 control
   used by the DlgX2 sample.
 
2. Load the DlgX2 project provided with the sample into Developer Studio.
 
3. Add the msdev\mfc\src directory as one of the directories that Developer
   Studio will search for include files. This can be done by clicking Options on
   the Tools menu, clicking the Directories tab, and with Show directories for
   set to Include files, adding the msdev\mfc\src directory.
 
   If the MFC source code was not copied to the hard disk when Visual C++ was
   initially installed, it can be copied at a later time. To do this, run the
   setup program, select the Custom installation option, and under the Microsoft
   Foundation Class Libraries component, make sure the Source Code component is
   selected.
 
4. Build the DlgX2 project. This will build and register the DlgX2 control. To
   test the control's functionality, use it in a control container.
 
REFERENCES
==========
 
For additional information, please see the following article in the Microsoft
Knowledge Base:
 
   Q155973 SAMPLE: DlgX.exe Creates Composite ActiveX Control with MFC and VC
   4.2
 
(c) Microsoft Corporation 1999, All Rights Reserved.
Contributions by Shawn W. Karr, Microsoft Corporation
 
Additional query words: kbDSupport
 
======================================================================
Keywords          : kbfile kbsample kbActiveX kbCtrl kbCtrlCreate kbMFC kbVC500 kbVC600 
Version           : winnt:5.0,6.0
Platform          : winnt
Issue type        : kbhowto
=============================================================================
Copyright Microsoft Corporation 1999.