Обработать нажатие ENTER в Диалоге
От: morgot  
Дата: 17.01.20 07:17
Оценка:
Банальный вопрос, но не могу разобраться, т.к. очень мало писал gui проги. Есть простой диалог, в котором есть 2 EDIT-контрола и 2 Button. Один из EDIT мультистрочный, т.е. чтобы пользователь мог там ввести разные данные. Но, при нажатии на ENTER внутри этого едита, почему-то нажимается совсем другая кнопка! Как это можно обработать, и почему так происходит? Т.е. нужно, чтобы просто переносило на другую строку.
winapi dialogbox
Re: Обработать нажатие ENTER в Диалоге
От: CEMb  
Дата: 17.01.20 07:43
Оценка: 1 (1)
Здравствуйте, morgot, Вы писали:

M>Банальный вопрос, но не могу разобраться, т.к. очень мало писал gui проги. Есть простой диалог, в котором есть 2 EDIT-контрола и 2 Button. Один из EDIT мультистрочный, т.е. чтобы пользователь мог там ввести разные данные. Но, при нажатии на ENTER внутри этого едита, почему-то нажимается совсем другая кнопка! Как это можно обработать, и почему так происходит? Т.е. нужно, чтобы просто переносило на другую строку.


О! Это древняя фича винды, которая так-то описана в документации, но я лет 10 назад, тоже наступив на неё, нашёл её корни под дебагом, в ассемблере, в системных библиотеках. Ностальгия
Суть фичи: если 1. на диалоге 2. мультистрочный edit, то, при наличии фокуса, при нажатии enter ищется кнопка с ID = IDOK и жмётся.
Точно не скажу, но вроде ES_WANTRETURN спасает ситуацию. Если не спасает, то можно ловить WM_COMMAND в диалоге и проверять, где фокус: если на мультиедите — игнорируем и работаем дальше. А так же: нажатие enter-а с зажатым shift-ом должно тоже делать перевод на следующую строчку. И вроде при ES_WANTRETURN этот функционал инвертируется.
Re: Обработать нажатие ENTER в Диалоге
От: qaz77  
Дата: 17.01.20 11:59
Оценка: 9 (1)
Здравствуйте, morgot, Вы писали:

M>Есть простой диалог, в котором есть 2 EDIT-контрола и 2 Button. Один из EDIT мультистрочный, т.е. чтобы пользователь мог там ввести разные данные. Но, при нажатии на ENTER внутри этого едита, почему-то нажимается совсем другая кнопка!


За это поведение отвечает функция IsDialogMessage, которая зовется в цикле обработки сообщений.
В общем случае, для кастомизации ее поведения при обработке клавиатуры есть сообщение WM_GETDLGCODE, посылаемое контролам из IsDialogMessage.
Если контрол на него отвечает, например, кодом DLGC_WANTALLKEYS, то IsDialogMessage ничего делать не будет и контрол получит WM_KEYDOWN/WM_CHAR в полном объеме.

Конкретно для многострочного edit'a есть стиль ES_WANTRETURN, который делает то, что нужно в стандартной оконной процедуре edit'а.

Кстати, с этим связан древний баг, который так и не исправили.
Если есть дочерний (WS_CHILD) диалог с многострочным edit'ом, лежащий на другом диалоге, то при нажатии Enter окно дочернего диалога разрушается (типа по ОК закрылся),
а родительский диалог с пустой частью продолжает работать. При этом наличие дефолтной кнопки с IDOK не обязательно. Я думаю, что там просто EndDialog(IDOK) зовется.
Re[2]: Обработать нажатие ENTER в Диалоге
От: morgot  
Дата: 20.01.20 10:20
Оценка:
Здравствуйте, CEMb, Вы писали:

CEM>Точно не скажу, но вроде ES_WANTRETURN спасает ситуацию.


Да, спасло, спасибо! GetDlgItem, GetWindowLong , и SetWindowLong — и все работает. Правда, на всякий случай удалил кнопку с IDOK.
Re[2]: Обработать нажатие ENTER в Диалоге
От: morgot  
Дата: 20.01.20 10:21
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>За это поведение отвечает функция IsDialogMessage, которая зовется в цикле обработки сообщений.


Ради интереса — а куда ее вставлять? Если у меня обычный модальный диалог, т.е. нет CreateWindows и цикла обработки сообщений.
Re[3]: Обработать нажатие ENTER в Диалоге
От: qaz77  
Дата: 20.01.20 14:31
Оценка:
Здравствуйте, morgot, Вы писали:

Q>>За это поведение отвечает функция IsDialogMessage, которая зовется в цикле обработки сообщений.


M>Ради интереса — а куда ее вставлять? Если у меня обычный модальный диалог, т.е. нет CreateWindows и цикла обработки сообщений.


Если используется функция DialogBoxXXX, она внутри содержит цикл обработки и вызов IsDialogMessage.
Тут скорее речь идет о подавлении, создаваемого ей эффекта.

P.S. Стили типа ES_WANTRETURN лучше указывать в шаблоне диалога (если заранее известны).
Не все стили можно установить/изменить с помощью SetWindowLong после создания окна (и чтобы, при этом, работали правильно).
Например, ES_MULTILINE — нельзя.
Отредактировано 20.01.2020 14:33 qaz77 . Предыдущая версия .
Re[4]: Обработать нажатие ENTER в Диалоге
От: morgot  
Дата: 20.01.20 19:48
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>P.S. Стили типа ES_WANTRETURN лучше указывать в шаблоне диалога (если заранее известны).

Q>Не все стили можно установить/изменить с помощью SetWindowLong после создания окна (и чтобы, при этом, работали правильно).

А где это указывать? Если я использую функцию DialogBox(), то там нет такого параметра (имею ввиду, задать для Edit отдельно стиль(. Наверное, следует тогда юзать CreateWindow(Ex) ?
Re[5]: Обработать нажатие ENTER в Диалоге
От: qaz77  
Дата: 21.01.20 07:35
Оценка:
Здравствуйте, morgot, Вы писали:

M>А где это указывать? Если я использую функцию DialogBox(), то там нет такого параметра (имею ввиду, задать для Edit отдельно стиль(. Наверное, следует тогда юзать CreateWindow(Ex) ?


В шаблоне диалога, который в ресурсах.
Функции типа DialogBox принимают имя или целочисленный идентификатор (MAKEINTRESOURCE) ресурса, содержащегося в exe или dll файле.
У функции DialogBox — это второй параметр LPCTSTR lpTemplate.

Шаблоны диалогов и другие ресурсы описываются в файлах .rc, обрабатываемых компилятором ресурсов (rc).
На выхлопе получаются .res файлы, которые добавляются к итоговому exe или dll.

Если используешь Visual Studio, от открой окно Resource View (View->Resource View) для своего солюшена.
Там будут отображены все .rc файлы, включенные в проекты этого солюшена.


Вот тут соответствующий параметр называется "Want Return":


Ну или ручками можно написать в rc файле, там простой синтаксис.
Re: Обработать нажатие ENTER в Диалоге
От: Vaynamond Россия  
Дата: 23.01.20 12:49
Оценка:
Здравствуйте, morgot, Вы писали:

Т.е. нужно, чтобы просто переносило на другую строку.
По-умолчанию в таком окне перевод строки происходит по комбинации Ctrl-Enter.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.