Microsoft KB Archive/198849

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 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.

  Start with an OLE control project created with ControlWizard.   Add the msdevdirectory as one of the directories that Developer Studio will search when looking for include files. This can be done as follows:   On the Tools menu, click Options.   Click the Directories tab.   With Show directories for set to Include files, add the msdev 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. </li>  Change the control base class from COleControl to CFormControl. Change all references in both the control’s declaration and implementation files. </li>  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: The actual path needed may be different depending on where the FormCtrl.h file is located relative to your project. </li>  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. </li>  Add the following line to your control’s InitInstance method: AfxEnableControlContainer; </li>  In steps 8, 9, 10, 13, and 14, replace all references to CMyFormControl with the name of your control class. </li>  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 } </li>  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 </li>  Add ClassWizard data initialization comments to the implementation of the control class’s constructor: </li></ol>
 * 1) include “FormCtrl.h”

//AFX_DATA_INIT

<ol start="11" style="list-style-type: decimal;">  Add a dialog box resource that contains the child controls you want to use and that has the following properties:   ID - IDD_FORM </li>  Style - Child </li>  More Styles - Control </li>  Extended Styles - Control parent </li>  Title bar - OFF </li>  Border - NONE </li></ul> </li> <li> Associate the dialog box resource with the control class: </li> <li> From the dialog resource open ClassWizard. </li> <li> 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. </li> <li> The Select Class dialog box will be displayed. Choose your control class and click Select. </li> <li> 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. </li> <li> Choose OK to close ClassWizard. </li> <li> Add the following to the constructor for the control class to initialize the base class. Use the following code: </li></ol>

CMyFormControl::CMyFormControl: CFormControl(CMyFormControl::IDD, TRUE)

<ol start="14" style="list-style-type: decimal;"> <li>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:</li></ol>

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

<ol start="15" style="list-style-type: decimal;"> <li>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:</li></ol>

<ol style="list-style-type: lower-alpha;"> <li> Go to ClassWizard. </li> <li> Click the OLE Automation tab. </li> <li> Click the Add Property button. </li> <li> Use the drop-down combo box to choose BackColor. </li> <li> Click OK. </li> <li> Repeat steps c..e for the ForeColor property. </li></ol>

<ol start="16" style="list-style-type: decimal;"> <li>Full ClassWizard functionality is available at this point for developing the control.</li></ol>

Steps to Build the DlgX2 Sample
<ol style="list-style-type: decimal;"> <li> 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. </li> <li> Load the DlgX2 project provided with the sample into Developer Studio. </li> <li> Add the msdevdirectory 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 msdevdirectory. 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. </li> <li> Build the DlgX2 project. This will build and register the DlgX2 control. To test the control’s functionality, use it in a control container. </li></ol>

= 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

<ol start="3" style="list-style-type: lower-alpha;"> <li>Microsoft Corporation 1999, All Rights Reserved. Contributions by Shawn W. Karr, Microsoft Corporation</li></ol>

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.