Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Диалог закрывантся при нажатии Enter на контроле  (Прочитано 19901 раз)
0 Пользователей и 1 Гость смотрят эту тему.
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« : 13-04-2005 09:28 » 

MSVS6.0. MFC.
Есть класс от CDialog'а. На нем накиданы всякие контролы как-то CTreeCtrl, CComboBox и т.п.
Если на контроле нажмешь Enter - форма закрывается как по OnOK(). Как ей запретить это делать??
То же самое по Esc.
« Последнее редактирование: 19-12-2007 19:56 от Алексей1153++ » Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Pu
Большой босс

ru
Offline Offline
78


« Ответ #1 : 13-04-2005 09:52 » 

IDOK и IDCANCEL просто обработай по своему или переопредели функции их обрабатывающие если уж в мфц они спрятаны.
Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #2 : 13-04-2005 10:28 » 

Обычно при нажатии на Enter в диалоге отрабатывается дефолтная кнопка. Можно сделать невидимую дефолтную кнопку.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
CyberMan
Гость
« Ответ #3 : 13-04-2005 11:06 » 

В редакторе ресурсов кликаешь дважды на кнопки OK И CANCEL создается обработчик и оттуда удаляешь вызовы СDialog::OnOK() ил  CDialog::OnCancel(). Кстати Джон сказал что при нажатии на ентер обрабатывается дефолтная кнопка то какая кнопка обрабатывается при нажатии ескейп.
Записан
Pu
Большой босс

ru
Offline Offline
78


« Ответ #4 : 13-04-2005 12:23 » 

повторюсь еще раз  Ага. при нажатии на ентер обрабатывается по умолчанию команда IDOK, при нажатии на эскейп IDCANCEL.
вот выдержка из файла winuser.h
Код:
/*
 * Dialog Box Command IDs
 */
#define IDOK                1
#define IDCANCEL            2
#define IDABORT             3
#define IDRETRY             4
#define IDIGNORE            5
#define IDYES               6
#define IDNO                7
я представляю себе что в карте сообщений нужно вручную прописать обработку этих ID. При этом будут выполняться ваши функции. У меня это выглядит так.
Код:
class dlg
{
     BEGIN_MSG_MAP(dlg)
COMMAND_HANDLER(IDOK, BN_CLICKED, OnBnClickedOk)
COMMAND_HANDLER(IDCANCEL, BN_CLICKED, OnBnClickedCancel)
     END_MSG_MAP()
LRESULT OnBnClickedOk(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled)
      {
          //EndDialog(IDOK);       
           return 0;
      }
LRESULT OnBnClickedCancel(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled)
    {
      //EndDialog(IDCANCEL);       
       return 0;
    }
};
« Последнее редактирование: 14-04-2005 06:38 от Pu » Записан

Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать.
(с) Артур Джонс
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #5 : 13-04-2005 14:10 » 

Так, парни. Спокойно. А то получится медвежья помощь. CyberMan, а это случаем не опасно? Удалить обработчики? А как потом диалог закрыть? Опаньки. Улыбаюсь
Поэтому мееееедленно разбираемся.

1. Нажатие кнопки Enter
Pu, повторюсь ещё раз Улыбаюсь - при нажатии на Enter отрабатывает именно дефолтная кнопка! При создании диалога в редакотре ресурсов таковой является кнопка IDOK. Если переназначить дефолтную кнопку (например добавить ещё одну), то можно уснуть на Enter - диалог не закроется.
Тк будет вызыватся обработчик ЭТОЙ (дефолтной) кнопки. Причем обработчик IDOK остаётся без изменений и даёт нам возможность всегда "положительно" завершить диалог с кодом возврата ID_OK.
Обычно в таких случаях эту кнопку делают ещё и невидимой. Чтоб не маячила.

2. Нажатие кнопки Esc
Здесь халявы не будет. Те нет кнопки отрабатывающей по Esc. Проблемма заключается в том, что OnCancel() - виртуальная ф-я вызываемая не только при нажатии на Esc, но и при нажатии комбинации Alt+F4 и других стандартных способов закрытия окна (системное меню, кликание на Х и тд и тп)
Поэтому напрочь убирать обработчик CDialog::OnCancel() не стоит. Для затыкания Esc лучше воспользоваться обработчиком PreTranslateMessage (к сожаления диалговые окна не обрабатывают WM_KEYDOWN)

BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)
{
   if((pMsg->message==WM_KEYDOWN) && (pMsg->wParam==VK_ESCAPE))
   {
      return TRUE;
   }
   
   return CDialog::PreTranslateMessage(pMsg);
}
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
esgal
Гость
« Ответ #6 : 13-04-2005 16:05 » 

Поэтапно:
1. С помощью классвизард выбираем IDOK, щёлкаем по BN_CLICKED.
2. Изменяем идентификатор кнопки IDOK на что то типа IDC_OK и отменяем в свойствах default button.
3. С помощью классвизард создаём ф-ию член OnClickedOk и редактируем её
void CDlgExample::OnClickedOk()
{
           CDialog::OnOk();
}
4. Редактируем исходную ф-ию OnOk
void CDlgExample::OnOk()
{
//Вроде как заглушка
}

С OnCancel аналогично.
Мне думается так проще, чем делать кныпки невидимыми. Если где нагнал, поправте.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #7 : 13-04-2005 17:59 » 

Все правильно - меняем обработчики...
А закрыть окошко надо по WM_DESTROY это полный идиотизм от мелкомягких так закрывать...
Записан

А птичку нашу прошу не обижать!!!
Джон
просто
Администратор

de
Offline Offline
Пол: Мужской

« Ответ #8 : 13-04-2005 22:31 » 

Народ, вы чего? А? Чем вам Ok  не нравится? А как-же диалог закрыть, и спросить его возвращённое значение?
ну типа if(dlg.DoModal()==ID_OK) ... ?
если вы всё позатыкаете, то нафига он тогда вообще нужен? Прочитайте вопрос внимательно. Речь идёт о нажатии на клаве Enter!!!! А не о затыкании кнопки Ок, на которую например можно мышкой кликнуть. Горе пользователю такого диалога, бедняга поседеет кликая на Ок пытаясь подтвердить введённую инфу.

esgal, опять 25 Улыбаюсь , а как ты диалог закрывать собираешься? если OnCancel заткнёшь? Попробуй и  напиши о результатах.

Гром, те ты предлагаешь вставить кнопку, в обработчике которой посылать самому себе WM_DESTROY? А если эта кнопка будет дефолтная? То тогда при каждом Enter кранты окошку? Или кто должен WM_DESTROY посылать? А если диалог модальный?
"Чёт я вас ребята не пойму, "Муму" Тургенев написал, а памятник вы Пушкину ставите." Улыбаюсь

зы Если это продолжение первоапрельской темы, то тогда сорри. С юмором у меня в последнее время напряжёнка.
Записан

Я вам что? Дурак? По выходным и праздникам на работе работать. По выходным и праздникам я работаю дома.
"Just because the language allows you to do something does not mean that it’s the correct thing to do." Trey Nash
"Physics is like sex: sure, it may give some practical results, but that's not why we do it." Richard P. Feynman
"All science is either physics or stamp collecting." Ernest Rutherford
"Wer will, findet Wege, wer nicht will, findet Gründe."
esgal
Гость
« Ответ #9 : 14-04-2005 03:48 » 

Пробовал и не один раз.  Улыбаюсь
Закрывается по щелчку на кныпку. Если не веришь, попробуй сам, всё работает на отлично. Метод кстати стандартный. Просто не стоит на мух с молотом охотиться, когда есть мухобойка.
Ведь мы же убрали только обработчик производного от класса. CDialog::OnOk() никуда не делся.
Получаем, что у нас нормально закрывается диалог и больше не мешают клавиши эскап и ентер.
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #10 : 14-04-2005 04:51 » 

Джон - ты не понял.
Есть несколько вариантов использования контрола диалога.
1. Обычный когда ты возврат смотришь.
2. Когда тебе не нужен возрат. росто тебе нужно окошко.
3. Как основное окно апликации.

В первом случае все ясно.
Во втором есть несколько типов контролов типа едит бокса в котором можно выставить Enter needed тогда по enter-у закрываться не будет если активным является он, но в остальных случаях закрытие по ентереу нежелательным оказувается.
В третьем вообще бред сивой кобылы.

Я обычно кнопочки Ок и Ентере когда они мне не нужны убиваю на корню.
Учти что дефолтная кнопка в таком случае остается ентереом, и не поменять уже.
Отсюда и проблема с ОнОк. Беру изначально ставлю обработчики и убираю все что надо, и не закрывается.
А WM_DESTROY ставить на кнопку глупо. Я обычно менюшку делаю или выход по х в правом верхнем углу оставляю.

Теперь немного из теории.
Нажатие на ESC и Enter у мелкомягких в диалоге априори стоит и изавиться полностью трудно. Я бы сказал, что в случаях когда вот такой выход не нужен ставить не модальный диалог, а немодальный с помощью Create ShowWindow.
Тогда все в твоих лапах Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
Hooter
Опытный

ru
Offline Offline
Пол: Мужской

« Ответ #11 : 14-04-2005 15:33 » 

Если OK и Cancel  в диалоге не нужны (это происходит чаще всего, когда диалоговое окно является главным окном приложения Ага ), то действительно, проще всего - убить обработчики.

А вот, когда их нужно оставить, имхо, самый правильный способ - фильтровать команды в PreTranslateMessage.
Реализация этого способа тут уже проскакивала.
Записан
CyberMan
Гость
« Ответ #12 : 15-04-2005 10:22 » 

Гы-гы-гы тут идея такая пришла. Когда пользователь нажимает на кнопку ентер диалогу посылается сообщение диалог обрабатывает это сообщение и вызывает фукцию OnOk() так давай те перепишем эти функции в нашем производном классе(ескейп соответственно) после удалим дефолтные кнопки создадим новые с идентификаторами ID_MYOK создадим методы для их обработки и вызовем в ний функции CDialog::OnOk() (ескейп соответственно) геморойно получилось но должно работать и теоретически все выглядит ништяк никто не придередся DоModal возвратит IDOK/IDCANCEL ГЫ-ГЫ-ГЫ    Отлично
Записан
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #13 : 15-04-2005 15:05 » 

Циберман, я так и сделал. Но это не метод. Фишка в том, что нажатие Enter на самом диалоге я отловил, а на контроле - нет.
Esc вообще везде работает...
Еще не пробовал совет Джона и Pu... Счас попробуем..
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #14 : 15-04-2005 15:07 » new

Вернее, я переопределил OnOK - но это глупо, потому что проще было убрать его из карты сообщений...
Вообще говоря, идея переопределить DoModal мне в голову не приходила...
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines