CommandBars Articles and Tutorials

Add controls inheritance to your application

Author: Kirk Stowell
Platform: Visual C++ MFC

If you need to add new functionality to standard Command Bar controls (CXTPControlButton, CXTPControlPopup, CXTPControlComboBox, CXTPControlEdit) you must create a new class inherited from one of these and override some virtual methods. This tutorial describes how to create custom Combo Box.

Imagine that you need a combo box with uppercase letters only (When users enter a character it automatically becomes uppercase)

  1. Create a new class inherited from CXTPControlComboBox
    class CControlComboBoxEx: public CXTPControlComboBox
    {
        public:
    };
    
  2. To create custom edit we must override CreateEditControl method and add a new Edit Control inherited from CXTPControlComboBoxEditCtrl
    class CControlComboBoxEx: public CXTPControlComboBox
    {
    public:
        CXTPControlComboBoxEditCtrl* CreateEditControl()
        {
            return new CControlComboBoxEditEx();
        }
    };
    
    class CControlComboBoxEditEx : public CXTPControlComboBoxEditCtrl
    {
    };
    
  3. Add OnChar handler to automatically uppercase the characters that the user entered
    class CControlComboBoxEditEx : public CXTPControlComboBoxEditCtrl
    {
    public:
        afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
    
        DECLARE_MESSAGE_MAP()
    };
    
    BEGIN_MESSAGE_MAP(CControlComboBoxEditEx, CXTPControlComboBoxEditCtrl)
        ON_WM_CHAR()
    END_MESSAGE_MAP()
    
    void CControlComboBoxEditEx::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
    {
        CString strChar((TCHAR)nChar), strUpper((TCHAR)nChar);
        strUpper.MakeUpper();
    
        if (strChar != strUpper) ReplaceSel(strUpper, TRUE);
        else CXTPControlComboBoxEditCtrl::OnChar(nChar,
                                                nRepCnt, nFlags);
    
    }
    
  4. If your application uses customization you must add methods to restore your combo box after the program reloads.

    Add standard DECLARE and IMPLEMENT macros:
     class CControlComboBoxEx: public CXTPControlComboBox
     {
         DECLARE_XTP_CONTROL(CControlComboBoxEx)
     public:
         CXTPControlComboBoxEditCtrl* CreateEditControl()
         {
             return new CControlComboBoxEditEx();
         }
     };
     IMPLEMENT_XTP_CONTROL(CControlComboBoxEx, CXTPControlComboBox)
    
    If your control has its own variables that need to be stored/restored you must override Copy and Serialize methods:
    class CControlComboBoxEx: public CXTPControlComboBox
    {
        …
    
    protected:
        void Copy(CXTPControl* pControl, BOOL bRecursive = FALSE);
        virtual void Serialize(CArchive& ar);
    
    protected:
        CString m_strMask;
    };
    
    void CControlComboBoxEx::Copy(
            CXTPControl* pControl, BOOL bRecursive)
    {
        ASSERT_KINDOF(CControlComboBoxEx, pControl);
    
        m_strMask = ((CControlComboBoxEx*)pControl)->m_strMask;
    
        CXTPControlComboBox::Copy(pControl, bRecursive);
    }
    void CControlComboBoxEx::Serialize(CArchive& ar)
    {
        CXTPControlComboBox::Serialize(ar);
    
        if (ar.IsStoring())
        {
            ar << m_strMask;
        }
        else
        {
            ar >> m_strMask;
        }
    }
    
  5. Now you can create your control in the OnCreateControl handler
    BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
        ON_XTP_CREATECONTROL()
    END_MESSAGE_MAP()
    
    int CMainFrame::OnCreateControl(
                    LPCREATECONTROLSTRUCT lpCreateControl)
    {
        if (lpCreateControl->nID == ID_POPUP_COMBO)
        {
            CXTPControlComboBox* pComboFind =
            (CXTPControlComboBox*)CControlComboBoxEx::CreateObject();
            pComboFind->SetDropDownListStyle();
            pComboFind->SetFlags(xtpFlagManualUpdate);
    
            lpCreateControl->pControl = pComboFind;
            return TRUE;
        }
        return FALSE;
    }