How to Initialize a Dynamically-Created .VBX Control

Last reviewed: July 22, 1997
Article ID: Q135885
1.00 1.50 1.51 1.52 WINDOWS kbprg kbcode

The information in this article applies to:

  • The Microsoft Foundation Classes (MFC) included with: Microsoft Visual C++ for Windows, versions 1.0, 1.5, 1.51, 1.52

SUMMARY

AppStudio provides support for placing .vbx controls on a dialog template at design time. AppStudio also gives you the ability to set the properties of a .vbx control that is placed on a dialog template. However, a dialog template will not work for creating a .vbx control on a window that is not based on a dialog, and if you don't know which .vbx control you will be creating until run time, a dialog template will not suffice. In these situations, you need to create the .vbx control at run time by using the CVBControl::Create function. This article discusses approaches to use in initializing a .vbx control that is created at run time.

MORE INFORMATION

Explicitly Setting the Properties

The simplest way to initialize the .vbx control is to explicitly set all of the properties of the .vbx control after it has been created. To do this, use the SetNumProperty, SetStringProperty, SetFloatProperty, and SetPictureProperty functions.

This approach can be laborious, but there are two big advantages. One advantage is that the initial values for the .vbx control will then be clearly documented at the point in code where the .vbx control has been created. Another advantage is portability to different versions of the .vbx control. While a .vbx control should always maintain backwards compatibility (and most do), a different version of a .vbx control might not be completely compatible with the binary initialization information used in the other initialization techniques.

Using a "Proxy" Dialog Template

Another way to initialize a dynamically-created .vbx control is to use a "proxy" dialog template. This is done by creating a dialog template to hold the .vbx control and its initial properties. The .vbx control on the template has the same ID as the nID parameter you use to create the .vbx control at run time using the CVBControl::Create function.

To have this proxy template behave just as the control would behave when it is created on a dialog, you have to actually create the control using the ::CreateWindow function. This is how a control is normally created. The use of this proxy template is made possible by the CWnd member function ExecuteDlgInit. This function can be called for any CWnd window not just dialogs, and it is this function that reads the initialization information from the dialog resource and initializes the .vbx control.

Here are the explicit steps necessary to use this technique:

  1. Create a new dialog template using AppStudio. For this example, give it the ID of IDD_VBX_PROXY1.

  2. Place the desired .vbx control on the dialog template and set the properties to the desired initial values. For this example, give the .vbx control the ID of IDC_MYVBX1.

  3. Create the .vbx control just as the dialog manager would. By examining any .RC file you will see that a .vbx control is first created as a custom control of class type VBControl. This is what the ::CreateWindow call would look like:

    ::CreateWindow("VBControl","GRID.VBX;Grid;Grid1",

          WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER |
          WS_TABSTOP,
    
               x, y, width, height,
          m_hWnd,  // This would be the parent window
          (HMENU) IDC_MYVBX1,
           AfxGetInstanceHandle(),
          NULL);
    
    

  4. After the call to create the .vbx control, call the ExecuteDlgInit function, passing it the ID of the proxy template (IDD_VBX_PROXY1). For example:

       // Create a .vbx control on a non-CFormView view
    
       void CMyView::OnInitialUpdate()
         {
           CView::OnInitialUpdate();
    
           ::CreateWindow("VBControl","GRID.VBX;Grid;Grid1",
        WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_BORDER | WS_TABSTOP,
             x, y, width, height,
             m_hWnd,  // This would be the parent window
             (HMENU) IDC_MYVBX1,
             AfxGetInstanceHandle(),
             NULL);
    
           ExecuteDlgInit(IDD_VBX_PROXY1);
         };
    
    

Using the CFile Parameter Of the Create Function

The last argument to the CVBControl::Create function is a pointer to a CFile object (CFile *). The documentation states that more information can be obtained about this parameter from MFC TechNote #27. While MFC TechNote #27 does contain valuable information about .vbx controls and .vbx initialization the specific format of this CFile object is not given.

The CFile object can be a pointer to a true file, but if you were to use this parameter, you would most likely use a CMemFile.

The format of the binary data contained in the CFile object is identical to the .vbx control information contained in the RT_DLGINIT binary resource created by AppStudio. The format of this resource is documented in MFC TechNote #24. The information that applies to a .vbx control is contained in this technote under the section titled "VBX Control Data."

So a proper use of the CFile pointer parameter would be to construct a CMemFile object, and fill it with the binary data as documented in the "VBX Control Data" section of the TechNote.

Examination of the control data format will reveal that you need to know the property index values of all your .vbx control's properties to initialize the .vbx control. If the property index values are documented for your .vbx control, you could use this format. If they are not documented, you can obtain them with a test program that uses the GetNumProps and GetPropName member functions of CVBControl.

Clearly this technique is not simple, and this is why the documentation for the CVBControl::Create function states that you will normally be passing NULL for the pFile parameter.

Note that because the binary initialization data is basically the same as that contained in the RT_DLGINIT resource, you could again create a proxy dialog template, load the binary resource (LoadResource), grab the portion that contains the .vbx initialization data, copy this data to a CMemFile object, and then use this CMemFile in your call to CVBControl::Create. However this would have the same effect as using the "proxy" template method listed above, and it would require a lot more work and code overhead than simply using CreateWindow and the ExecuteDlgInit function.

REFERENCES

For more information, please see:

  • MFC TechNote #24
  • MFC TechNote #27
  • MFC documentation for the CVBControl class


Additional reference words: kbinf 1.00 1.50 1.51 1.52 2.00 2.50 2.51 2.52
KBCategory: kbprg kbcode
KBSubcategory: MfcVBX
Keywords : kb16bitonly
Technology : kbMfc


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 22, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.