Professional UI Solutions
Site Map   /  Register
 
 

Forum

Please Log In to post a new message or reply to an existing one. If you are not registered, please register.

NOTE: Some forums may be read-only if you are not currently subscribed to our technical support services.

Forums » Prof-UIS General Discussion » Command Manager, Toolbar items and dialog windows Collapse All
Subject Author Date
Douglas Hoppes Jul 8, 2005 - 11:32 AM

Hi all,

Okay... fairly new to Prof-UI and am really liking it (the samples are pretty good and easy to follow.... considering that I’ve just started learning MFC!).

I’m trying to figure out how to do this one method, though. I have a combo box on my tool bar showing me a list of users. I would like to have the same combo box on a totally separate dialog window that contains the same information. The trick of the system is that, when a user selects an entry on the toolbar’s combo box or add an item to it, I would like the dialog window’s combo box to have the new item automatically (and change to the new selection automatically).

Is this possible using the Command Manager? Or do I specifically have to code the changes myself?

Any help is greatly appreciated.

Doug

Technical Support Jul 9, 2005 - 10:39 AM

The combo box control sends the CBN_SELENDOK notification (in WM_COMMAND) to the parent window when the selection has finally changed. You can handle this event both in your CExtComboBox-derived class or in its parent window. We recommend you to handle this event in your combo box class. Handling messages sent to parent windows in source windows is called reflection. It is handy to create a CExtComboBox-derived class which reflects selection change and get access to all other combo boxes of the same type in your application. When this combo box catches the selection change, it can change selection in all other combo boxes.

Here it is the class declaration:

 
class CComboBoxForMrDouglas : public CExtComboBox
{
    static CTypedPtrList < CPtrList, CComboBoxForMrDouglas * >
        g_listAllComboBoxesForMrDouglas;
    static bool g_bSynchronizingCurSel;
public:
    DECLARE_DYNAMIC( CComboBoxForMrDouglas );
    CComboBoxForMrDouglas();
    virtual ~CComboBoxForMrDouglas();
    void SynchronizeCurSel();
#ifdef _DEBUG
    virtual void AssertValid() const;
    virtual void Dump( CDumpContext & dc ) const;
#endif
public:
    // Overrides
    //{{AFX_VIRTUAL(CComboBoxForMrDouglas)
    virtual void PostNcDestroy();
protected:
    virtual void PreSubclassWindow();
    //}}AFX_VIRTUAL
public:
    //{{AFX_MSG(CComboBoxForMrDouglas)
    //}}AFX_MSG
    afx_msg void OnSelEndOK();
    DECLARE_MESSAGE_MAP()
};
Here it is the class implementation:
IMPLEMENT_DYNAMIC( CComboBoxForMrDouglas, CExtComboBox );
CTypedPtrList < CPtrList, CComboBoxForMrDouglas * >
     CComboBoxForMrDouglas::g_listAllComboBoxesForMrDouglas;
bool CComboBoxForMrDouglas::g_bSynchronizingCurSel = false;
 
CComboBoxForMrDouglas::CComboBoxForMrDouglas()
{
}
CComboBoxForMrDouglas::~CComboBoxForMrDouglas()
{
}
#ifdef _DEBUG
void CComboBoxForMrDouglas::AssertValid() const
{
    CExtComboBox::AssertValid();
}
void CComboBoxForMrDouglas::Dump( CDumpContext & dc ) const
{
    CExtComboBox::Dump( dc );
}
#endif
BEGIN_MESSAGE_MAP( CComboBoxForMrDouglas, CExtComboBox )
    //{{AFX_MSG_MAP(CComboBoxForMrDouglas)
    //}}AFX_MSG_MAP
    ON_CONTROL_REFLECT( CBN_SELENDOK, OnSelEndOK )
END_MESSAGE_MAP()
void CComboBoxForMrDouglas::PostNcDestroy()
{
    ASSERT_VALID( this );
    CExtComboBox::PostNcDestroy();
    g_listAllComboBoxesForMrDouglas.AddTail( this );
}

void CComboBoxForMrDouglas::PreSubclassWindow()
{
    ASSERT_VALID( this );
POSITION pos = g_listAllComboBoxesForMrDouglas.Find( this );
    ASSERT( pos != NULL );
    g_listAllComboBoxesForMrDouglas.RemoveAt( pos );
    CExtComboBox::PreSubclassWindow();
}
void CComboBoxForMrDouglas::OnSelEndOK()
{
    ASSERT_VALID( this );
    Default();
    SynchronizeCurSel();
}
void CComboBoxForMrDouglas::SynchronizeCurSel()
{
    ASSERT_VALID( this );
    if( g_bSynchronizingCurSel )
        return;
    g_bSynchronizingCurSel = true;
int nCurSel = GetCurSel();
POSITION pos =
        g_listAllComboBoxesForMrDouglas.GetHeadPosition();
    for( ; pos != NULL; )
    {
        CComboBoxForMrDouglas * pComboBoxForMrDouglas =
            g_listAllComboBoxesForMrDouglas.GetNext( pos );
        ASSERT_VALID( pComboBoxForMrDouglas );
        if( pComboBoxForMrDouglas == this )
            continue;
        pComboBoxForMrDouglas->SetCurSel( nCurSel );
    }
    g_bSynchronizingCurSel = false;
}
You can programmatically change selection of any combo box of this type and then invoke its SynchronizeCurSel() method to make other combo boxes having the same selection. This method is also called from the OnSelEndOK() message reflection handler. You can also append your specific code to the OnSelEndOK() method. Please note that we keep only pointers to the combo box windows which have the m_hWnd property as a property of a valid window because we add these pointers to a list in the PreSubclassWindow() method and remove them in the PostNcDestroy() method. So, each combo box window should know all the created combo boxes of the same type. This makes possible synchronization of the currently selected item. Of course, this approach assumes all combo boxes have equal content.