Lou
Lou

Reputation:

Catching when user selects an item from a CComboBox

This is as basic as it gets.

I want to catch when the user selects an item from a CComboBox (actually, a subclass of CComboBox).

Tried lots of combinations of OnCblSelChange, OnCommand. Guess I haven't hit the right combo yet (no pun intended).

OS is Vista but I'm forcing an XP-style dialog (That shouldn't matter, should it?)

I'm able to catch events for classes derived from CEdit and CFileDialog.

I am at my wits end here. Any assistance would be ever-so appreciated.

Any source code would, of course, be more than ever-so appreciated.

Upvotes: 9

Views: 15263

Answers (3)

BilalOmar
BilalOmar

Reputation: 49

Use ON_CBN_SELCHANGE on message map. it will hit when selection changed in combo box.

Upvotes: 0

Smashery
Smashery

Reputation: 59673

Unfortunately, it seems that all messages (even SELEND_OK) for combo box changing are sent before the text has actually changed, so DoDataExchange will give you the previous text in the CComboBox. I have used the following method, as suggested by MSDN:

void MyDialog::DoDataExchange(CDataExchange* pDX)
{
    DDX_Text(pDX, IDC_COMBO_LOCATION, m_sLocation);
    CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(MyDialog, CDialog)
    ON_CBN_SELENDOK(IDC_COMBO1, &MyDialog::OnComboChanged)
    ON_CBN_EDITUPDATE(IDC_COMBO1, &MyDialog::OnComboEdited) // This one updates immediately
END_MESSAGE_MAP()

...

void MyDialog::OnComboChanged()
{
    m_myCombo.GetLBText(m_myCombo.GetCurSel(), m_sSomeString);
}

void MyDialog::OnComboEdited()
{
    UpdateData();
}

It seems to work quite nicely.

Upvotes: 10

mwigdahl
mwigdahl

Reputation: 16578

CBN_SELENDOK should be the message that you're looking for. It's sent after the user selection is finalized but before the combo box closes up (if it does). CBN_SELCHANGE is sent before the selection is actually saved to the combo box control.

This MSDN link has more information (you've likely seen it already...)

Here is the code I promised you. One thing I noticed when gathering this up is that it is possible to have this message suppressed if you are using an ON_CONTROL_REFLECT handler within the class derived from CComboBox. This would cause the control itself to handle the message and not pass it on to the parent. You can get around that problem by using ON_CONTROL_REFLECT_EX with the proper return code, which will make both the box itself and the parent receive the message.

Anyway, here's the code snippet:

class SPC_DOCK_CLASS ProcessingExceptionDockDlg : public CSPCDockDialog
{
    SPC_DOCK_DECLARE_SERIAL(ProcessingExceptionDockDlg);

public:
    // ... redacted ...

    //{{AFX_DATA(ProcessingExceptionDockDlg)
    CComboBox                   m_comboFilter;
    //}}AFX_DATA

    //{{AFX_VIRTUAL(ProcessingExceptionDockDlg)
    protected:
    virtual void DoDataExchange(CDataExchange* pDX);
    //}}AFX_VIRTUAL

protected:

    //{{AFX_MSG(ProcessingExceptionDockDlg)
    afx_msg void OnSelendokComboTreeFilter();
    //}}AFX_MSG
    DECLARE_MESSAGE_MAP()
};

/****************/

// ProcessingExceptionDockDlg.cpp : implementation file
//

#include "stdafx.h"
#include "resource.h"
#include "ProcessingExceptionDockDlg.h"

// ... much code redacted ...

void ProcessingExceptionDockDlg::DoDataExchange(CDataExchange* pDX)
{
    CSPCDockDialog::DoDataExchange(pDX);
    //{{AFX_DATA_MAP(ProcessingExceptionDockDlg)
    DDX_Control(pDX, IDC_COMBO_TREE_FILTER, m_comboFilter);
    //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(ProcessingExceptionDockDlg, CSPCDockDialog)
    //{{AFX_MSG_MAP(ProcessingExceptionDockDlg)
    ON_CBN_SELENDOK(IDC_COMBO_TREE_FILTER, OnSelendokComboTreeFilter)
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void ProcessingExceptionDockDlg::OnSelendokComboTreeFilter() 
{
    // ... code redacted ...
}

Upvotes: 3

Related Questions