Как обрабатывать сообщения из динамически созданных элементов управления в приложении 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 ответов
это решение я нашел до сих пор в порядке значимости:
использовать
ON_COMMAND_RANGE
Если вы можете определить диапазон идентификаторов элементов управления, которые вы хотите обработать.перегрузка
CWnd::PreTranslateMessage()
и делайте все, что хотите, с полученными сообщениями. Примечание. при работе с кнопками учитывайте, что событие BN_CLICKED отправляется не в PreTranslateMessage, а непосредственно в процедуру window.перегрузка
CWnd::WindowProc()
и делайте все, что хотите, с полученными сообщениями. Обратите внимание, что при работе с кнопками это единственный способ обработки события BN_CLICKED.
Интересные ссылки:
- пожалуйста, помогите с PreTranslateMessage и обработкой пользовательских сообщений.
- TN006: карты сообщений
надеюсь, это поможет... спасибо всем за Ваш вклад.
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]
}
}
Я считаю, что эта статья объясняет это довольно хорошо и имеет исходный код. Я не пробовал это, поэтому я не могу гарантировать, что он работает, но в то время я думал, что это может помочь.
вставьте запись 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)