Как обрабатывать сообщения из динамически созданных элементов управления в приложении MFC?

представьте, что у меня есть CDialog, который создает элементы управления динамически, когда пользователь нажимает кнопку. Это могло быть так:

// We don't know which is the first id for the new buttons until runtime (!)
MyDialog::MyDialog(/*whatever parameters needed*/, first_id)
  : next_id_(first_id) 
{ /*...*/ }

BOOL MyDialog::OnSomeButtonClicked()
{
  CButton* new_button = new CButton;
  new_button->Create("Caption", WS_CHILD | WS_VISIBLE, this->new_button_rect_, 
                     this, this->next_id_++);
}

тогда мой вопрос будет: как я могу обрабатывать сообщения от этой кнопки? Можно ли использовать средство карты сообщений MFC?

решение должно работать как в vs6, так и в vs2005.

спасибо!

7 ответов


это решение я нашел до сих пор в порядке значимости:

  1. использовать ON_COMMAND_RANGE Если вы можете определить диапазон идентификаторов элементов управления, которые вы хотите обработать.

  2. перегрузка CWnd::PreTranslateMessage() и делайте все, что хотите, с полученными сообщениями. Примечание. при работе с кнопками учитывайте, что событие BN_CLICKED отправляется не в PreTranslateMessage, а непосредственно в процедуру window.

  3. перегрузка CWnd::WindowProc() и делайте все, что хотите, с полученными сообщениями. Обратите внимание, что при работе с кнопками это единственный способ обработки события BN_CLICKED.

Интересные ссылки:

надеюсь, это поможет... спасибо всем за Ваш вклад.


Eventhough вы не знаете точных значений идентификатора, если вы знаете возможный диапазон идентификаторов, то можно использовать следующий макрос.

BEGIN_MESSAGE_MAP(MyDialog, CDialog)
    ...
    ...
    ON_COMMAND_RANGE(1000, 5000, OnButtonDynamic)
END_MESSAGE_MAP()


void MyDialog::OnButtonDynamic(UINT nID)
{

}

Это будет работать для идентификаторов в диапазоне 1000 - 5000.


Я на несколько лет опоздал на эту вечеринку, но решение заключается в том, чтобы назначить один и тот же идентификатор элемента управления каждой кнопке (нет необходимости "резервировать" id в ресурсе.ч, и никаких искусственных ограничений на количество элементов управления, которые могут быть созданы), чтобы сохранить дескриптор окна и использовать GetCurrentMessage() в обработчик кнопки:

// resource.h
#define IDC_DYNAMIC_BUTTON 123

// In message map
ON_BN_CLICKED(IDC_DYNAMIC_BUTTON, OnDynamicButtonClicked)

// Store the window handles when creating them in a member:
std::map<HWND, SomeStruct> m_Buttons;
... fill this map when creating the buttons, presumably in OnInitDialog()

// Actual handler
void MyDialog::OnDynamicButtonClicked()
{
    const MSG* message = GetCurrentMessage();

    if (m_Buttons.find((HWND)message->lParam) != m_Buttons.end()) {
        // Do something with m_Buttons[(HWND)message->lParam]
    }
}

Я считаю, что эта статья объясняет это довольно хорошо и имеет исходный код. Я не пробовал это, поэтому я не могу гарантировать, что он работает, но в то время я думал, что это может помочь.

статьи


вы можете найти детали (+намного больше) на modeless dialogs здесь.


вставьте запись ID обработчика в Resouce.ч Затем вставьте запись в карту сообщений обработчика, например ON_BN_CLICKED(IDC_BTNCREATE, OnBnClickedrunCreated) или вы можете напрямую использовать целочисленный идентификатор, например ON_BN_CLICKED (1200, OnBnClickedrunCreated). Если вы используете 2nd версию, то есть нет необходимости вставлять запись в resource.h. Дайте defination и объявление обработчика внутри .h и .файл cpp. вы получите ответ.


используйте этот путь: ON_CONTROL_RANGE (wNotifyCode, id1, id2, memberFxn ). например:

ON_CONTROL_RANGE(EN_UPDATE, IDC_EDIT_START, IDC_EDIT_END, OnEnUpdateEditParams)