Поймать, когда пользователь выбирает элемент из CComboBox - PullRequest
7 голосов
/ 31 марта 2009

Это так же просто, как и получается.

Я хочу поймать, когда пользователь выбирает элемент из CComboBox (фактически, подкласс CComboBox).

Пробовал много комбинаций OnCblSelChange, OnCommand. Полагаю, я еще не выбрал правильную комбинацию (без каламбура).

ОС - это Vista, но я вынуждаю диалог в стиле XP (Это не должно иметь значения, не так ли?)

Я могу ловить события для классов, производных от CEdit и CFileDialog.

Я в своем уме. Любая помощь будет очень цениться.

Разумеется, любой исходный код будет более чем когда-либо оценен.

Ответы [ 2 ]

7 голосов
/ 04 ноября 2009

К сожалению, кажется, что все сообщения (даже SELEND_OK) для изменения поля со списком отправляются до , текст фактически изменился, поэтому DoDataExchange выдаст вам предыдущий текст в CComboBox , Я использовал следующий метод в соответствии с 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();
}

Кажется, он работает довольно хорошо.

1 голос
/ 31 марта 2009

CBN_SELENDOK должно быть сообщением, которое вы ищете. Он отправляется после завершения выбора пользователя, но до закрытия поля со списком (если это так). CBN_SELCHANGE отправляется до выбор фактически сохраняется в элементе управления поля со списком.

Эта ссылка MSDN содержит больше информации (вы, вероятно, уже видели это ...)

Вот код, который я вам обещал. Одна вещь, которую я заметил, собирая это, это то, что возможно подавить это сообщение, если вы используете обработчик ON_CONTROL_REFLECT в классе, производном от CComboBox. Это заставит сам элемент управления обрабатывать сообщение и не передавать его родителю. Вы можете обойти эту проблему, используя ON_CONTROL_REFLECT_EX с правильным кодом возврата, который заставит и сам ящик, и родительский элемент получить сообщение.

В любом случае, вот фрагмент кода:

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 ...
}
...