Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Visual C++/MFC/WTL > Определение ID нажатой кнопки


Автор: voyageur 30.3.2010, 10:52
Здравствуйте! Второй день мучаю поисковики, но так и не нашел исчерпывающего ответа...
Ситуация: диалоговый проект MFC. На поле много button'ов у каждой свой ИД, по нажатию любого баттона выполняется _1_ функция OnBnClickedButton1(). В этой функции надо определить, если нажат допустим IDC_BUTTON1 то делать то-то, если IDC_BUTTON2 то то-то. Так вот вопрос, как же определить этот самый ид? Если функцией GetDlgCtrlID( ), как ей пользоваться?
Код

    ON_BN_CLICKED(IDC_BUTTON1, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON8, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON2, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON3, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON4, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON5, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON6, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON7, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON9, &Cmy_calcDlg::OnBnClickedButton1)
    ON_BN_CLICKED(IDC_BUTTON10, &Cmy_calcDlg::OnBnClickedButton1)

Код

void Cmy_calcDlg::OnBnClickedButton1()
{
    // TODO: добавьте свой код обработчика уведомлений
    if(GetDlgCtrlID()==IDC_BUTTON1)
    {
        my_edit1.SetWindowTextW(L"1");
    }
     else
    {;
    }
}



Автор: xTr1m 30.3.2010, 11:58
Цитата

ON_BN_CLICKED(IDC_BUTTON1, &Cmy_calcDlg::OnBnClickedButton1)

вот эта строка означает, что при нажатии на кнопку IDC_BUTTON1 будет вызвана функция OnBnClickedButton1.

Цитата

void Cmy_calcDlg::OnBnClickedButton1()
{
    // TODO: добавьте свой код обработчика уведомлений
    if(GetDlgCtrlID()==IDC_BUTTON1)
    {
        my_edit1.SetWindowTextW(L"1");
    }
     else
    {;
    }
}

а тут получается, что эта функция для обработчика события клик кнопки IDC_BUTTON1, то есть других быть не может (в твоем случае).

Автор: 586 30.3.2010, 12:34
Как вариант, можно перегрузить метод OnCommand.
Код
BOOL Cmy_calcDlg::OnCommand(WPARAM wParam, LPARAM lParam)
{
    switch(LOWORD(wParam))
    {
    case IDC_BUTTON1:
    case IDC_BUTTON2:
    case IDC_BUTTON3:
    case IDC_BUTTON4:
    case IDC_BUTTON5:
    case IDC_BUTTON6:
    case IDC_BUTTON7:
    case IDC_BUTTON8:
    case IDC_BUTTON9:
    case IDC_BUTTON10:
        MessageBox(_T("!!!"));
        return TRUE;
    }
    return CDialog::OnCommand(wParam, lParam);
}

Автор: voyageur 30.3.2010, 13:04
xTr1m,  функция обрабатывает все кнопки, т.е. по нажатию любой будет печататься "1", другой вопрос, что значение GetDlgCtrlID() не равно IDC_BUTTON1 (1000), по этому не работает.. Вот мне интересно, что я забыл подставить?
в результате должно получится что по нажатию IDC_BUTTON1 напечатается "1" по IDC_BUTTON2 "2" и тд


586, а как этим пользоваться?

Автор: 586 30.3.2010, 13:14
Цитата(voyageur @  30.3.2010,  13:04 Найти цитируемый пост)
586, а как этим пользоваться? 

Так же, как и обрабатывается сообщение http://msdn.microsoft.com/en-us/library/aa930761.aspx.
В LOWORD(wParam) находится идентификатор элемента (кнопки, эдита, или другого контрола), в HIWORD(wParam) передаётся код события (при нажатии кнопки это будет BN_CLICKED), в lParam находится дескриптор контрола, которое отправило сообщение.

Автор: voyageur 30.3.2010, 13:22
Код

error C2555: Cmy_calcDlg::OnCommand: возвращаемый тип перегруженной виртуальной функции отличается от 'CWnd::OnCommand' и не является ковариантным
1>        c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afxwin.h(2666): см. объявление 'CWnd::OnCommand'

вот что мне пишет..

Автор: xTr1m 30.3.2010, 14:01
Ох, прошу прощения. Тогда можно использовать ON_COMMAND_RANGE.

Автор: 586 30.3.2010, 21:04
Цитата(voyageur @  30.3.2010,  13:22 Найти цитируемый пост)
Код
error C2555: Cmy_calcDlg::OnCommand: возвращаемый тип перегруженной виртуальной функции отличается от 'CWnd::OnCommand' и не является ковариантным
1>        c:\program files\microsoft visual studio 9.0\vc\atlmfc\include\afxwin.h(2666): см. объявление 'CWnd::OnCommand'

вот что мне пишет.. 

Проверь, правильно ли описан метод OnCommand в прототипе класса Cmy_calcDlg.
проблем быть не должно.
Вот кстати описание CWnd::OnCommand в MSDN: http://msdn.microsoft.com/en-us/library/3t3ddsb9.aspx

Автор: Albor 31.3.2010, 06:48
Цитата(voyageur @  30.3.2010,  10:52 Найти цитируемый пост)
Второй день мучаю поисковики, но так и не нашел исчерпывающего ответа...


voyageur, нужно было посмотреть что делает GetDlgCtrlId(). Вызывая его в классе Cmy_calcDlg, данный метод вызывается для объекта этого класса, то есть для диалога. Чтобы получить ID кнопки, нужно вызвать этот метод, например через указатель на кнопку, так pButton->GetDlgCtrlId(); В твоём стартовом топике искать ID нет смысла, так как ты определил обработчик для каждой кнопки и попав в такой обработчик можно быть уверенным в том, что никакой другой ID кроме нажатой кнопки здесь не присутствует. Об этом тебе и говорил xTr1m. 
586 предложил другой подход: обработка всех команд в одном методе. Вот здесь уже нужно проверить от какого контрола и какая пришла команда (но GetDlgCtrlId() здесь не нужен).  В этом случае тебе не нужны те функции нажатия кнопок, которые ты уже определил. Так что не путайся и определись как будешь решать задачу: как делал сначала или через OnCommand.

Автор: voov 31.3.2010, 10:22
Цитата(xTr1m @  30.3.2010,  14:01 Найти цитируемый пост)
Тогда можно использовать ON_COMMAND_RANGE

В данном случае это удобнее всего

Автор: voyageur 31.3.2010, 10:36
Все, проект заново создал, просто надо было удалить функции нажатия кнопок, как сказал Albor, и все заработало с OnCommand. 
Я работаю в фотоне QNX, там виджеты и попроще)) Всем спасибо!

Автор: Earnest 31.3.2010, 10:44
1) Проще всего, безусловно, как уже сказано , изменить сигнатуру обработчика на void (UINT) и использовать ON_COMMAND_RANGE
2) Если уже переопределять виртуальную обработку коммангд, то уж никак не OnCommand, а OnCmdMsg - она более специализирована... Для переопределения OnCommand должны быть более веские основания. Я бы, кстати, так и сделала... Все эти ON_RANGE, во первых, требуют, чтобы ид-ры были в одном диапазоне, что сложно поддерживать, да и вообще...
3) Для крайних случаев, когда изменить сигнатуру обработчика почему-либо нельзя, есть замечательная функция CWnd::GetCurrentMessage, которая возвращает текущее обрабатываемое сообщение, со всеми его параметрами. Вот в нем-то и можно посмотреть, кого нажали (т.е. WPARAM).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)