PRB: VBX Controls Automatically Disabled in MFC Dialog Bar

ID: Q119766


The information in this article applies to:


SYMPTOMS

After adding VBX controls to an MFC dialog bar object, they are automatically disabled when the program is executed.


CAUSE

Many VBX controls are implemented by subclassing the standard Windows button class. MFC CDialogBar objects automatically disable button controls which do not implement a WM_COMMAND or ON_UPDATE_COMMAND_UI message handler.

This is by design, but since ClassWizard does not provide support for adding these handlers for VBX controls, it can sometimes be undesirable.


RESOLUTION

There are two methods which can be used to work around this problem.

Method #1:

This solution requires you to manually add an ON_COMMAND_UPDATE_UI handler for each VBX control that subclasses the standard Windows button class. This handler will simply enable the control whenever it is called.

As mentioned above, ClassWizard does not provide support for adding ON_UPDATE_COMMAND_UI handlers for VBX controls. It only allows you to create VBX event notification functions.

NOTE: The ON_UPDATE_COMMAND_UI handler, in case of a CDialogBar would be added to the parent of CDialogBar, which usually is the CMainFrame class created by AppWizard.

To manually add an ON_UPDATE_COMMAND_UI handler, follow these steps:

  1. In the header (.h) file for the parent, go to the section marked with the special //{{AFX_MSG comments. Outside this block, add a handler prototype for each VBX that subclasses the standard Windows button class. For two VBX controls, the results should be similar to the following:
    
    // Generated message map functions 
    protected:
         //{{AFX_MSG(CMainFrame)
         ...
         //}}AFX_MSG
         afx_msg void OnUpdateVBXControl1(CCmdUI* pCmdUI);
         afx_msg void OnUpdateVBXControl2(CCmdUI* pCmdUI); 


  2. In the implementation (.cpp) file for the parent, go to the message map section and add entries for each ON_UPDATE_COMMAND_UI handler. The results should look like this:
    
    BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
         //{{AFX_MSG_MAP(CMainFrame)
         ...
         //}}AFX_MSG_MAP
         ON_UPDATE_COMMAND_UI(IDC_VBXCONTROL1, OnUpdateVBXControl1)
         ON_UPDATE_COMMAND_UI(IDC_VBXCONTROL2, OnUpdateVBXControl2)
    END_MESSAGE_MAP() 
    In this example, IDC_VBXCONTROL1 and IDC_VBXCONTROL2 are the resource identifiers for the two VBX controls.


  3. In the implementation (.cpp) file for the parent, write the functions which will handle updating the UI for these controls. The functions should look like:
    
    void CMainFrame::OnUpdateVBXControl1(CCmdUI* pCmdUI)
    {
         pCmdUI->Enable(TRUE);
    }
    void CMainFrame::OnUpdateVBXControl2(CCmdUI* pCmdUI)
    {
         pCmdUI->Enable(TRUE);
    } 


  4. Rebuild the project. You should now see that the VBX controls are enabled.


Method #2:

This solution is much easier to implement, although it has the drawback of preventing automatic disabling of non-VBX button controls on a dialog bar. Thus, no button control will ever be disabled even if it doesn't implement a WM_COMMAND or ON_UPDATE_COMMAND_UI handler.

The CControlBar class defines the OnUpdateCmdUI() pure virtual function, which is overridden in the CDialogBar class to call CWnd::UpdateDialogControls. This function is presented below:

void CDialogBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL
bDisableIfNoHndler)
{
     UpdateDialogControls(pTarget, bDisableIfNoHndler);
} 
This is the function which is responsible for automatically disabling button controls on a dialog bar.

You can prevent this function from being called by deriving a class from CDialogBar and overriding this function so that it resembles the following:


void CMyDerivedDialogBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL
bDisableIfNoHndler)
{
     UpdateDialogControls(pTarget, FALSE);
} 


MORE INFORMATION

To reproduce the problem add a VBX control to the dialog bar in the CTRLBARS sample included as a MFC sample with Visual C++. To add the VBX do the following:

  1. Edit the .rc file for the sample (ctrlbars.rc) using AppStudio.


  2. Edit the IDD_VIEWSELECT dialog resource.


  3. Add a Command3D button on to the dialog bar. If the Command3D control is not in the AppStudio control palette, the threed.vbx file needs to be installed in AppStudio. For more information on adding VBX controls to AppStudio, please refer to the section "To add a VBX control to the AppStudio control palette" in the AppStudio User's Guide.


  4. Add EnableVBX() to CCtrlbarsApp::InitInstance() in ctrlbars.cpp.


Build and run the sample. The Command3D button shows up on the dialog bar but is disabled. After adding the workarounds mentioned above, the button is enabled.


REFERENCES

Technical Note 31: Control Bars, under MFC Technotes included with Visual C++.

Additional query words: 1.00 1.50 2.00 2.50 disabled gray grey dialog bar


Keywords          : kb16bitonly 
Version           : 
Platform          : 
Issue type        : 

Last Reviewed: July 22, 1999