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

Представьте, что у меня есть 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, так и в 2005 году.

Спасибо!

Ответы [ 7 ]

6 голосов
/ 13 мая 2009

Вот решения, которые я нашел до сих пор в порядке актуальности:

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

  2. Перегрузите CWnd::PreTranslateMessage() и делайте все что угодно с полученными сообщениями. ПРИМЕЧАНИЕ. При работе с кнопками учтите, что событие BN_CLICKED НЕ отправляется в PreTranslateMessage, а напрямую отправляется в оконную процедуру.

  3. Перегрузите CWnd::WindowProc() и делайте все что угодно с полученными сообщениями. Обратите внимание, что при работе с кнопками это ЕДИНСТВЕННЫЙ ПУТЬ, который я нашел для обработки события BN_CLICKED.

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

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

5 голосов
/ 13 мая 2009

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

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


void MyDialog::OnButtonDynamic(UINT nID)
{

}

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

2 голосов
/ 05 февраля 2015

Я на несколько лет опоздал на эту вечеринку, но решение этой проблемы состоит в том, чтобы назначить один и тот же контрольный идентификатор каждой кнопке (нет необходимости «резервировать» идентификаторы в resource.h, и нет искусственных ограничений на количество элементы управления, которые могут быть созданы), чтобы сохранить дескриптор окна и использовать 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]
    }
}
0 голосов
/ 21 октября 2016

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

ON_CONTROL_RANGE(EN_UPDATE, IDC_EDIT_START, IDC_EDIT_END, OnEnUpdateEditParams)
0 голосов
/ 24 февраля 2010

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

0 голосов
/ 13 мая 2009

Вы можете найти детали (+ намного больше) в немодальных диалогах там .

0 голосов
/ 13 мая 2009

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

Статья

...