Банальный вопрос, но не могу разобраться, т.к. очень мало писал gui проги. Есть простой диалог, в котором есть 2 EDIT-контрола и 2 Button. Один из EDIT мультистрочный, т.е. чтобы пользователь мог там ввести разные данные. Но, при нажатии на ENTER внутри этого едита, почему-то нажимается совсем другая кнопка! Как это можно обработать, и почему так происходит? Т.е. нужно, чтобы просто переносило на другую строку.
Здравствуйте, morgot, Вы писали:
M>Банальный вопрос, но не могу разобраться, т.к. очень мало писал gui проги. Есть простой диалог, в котором есть 2 EDIT-контрола и 2 Button. Один из EDIT мультистрочный, т.е. чтобы пользователь мог там ввести разные данные. Но, при нажатии на ENTER внутри этого едита, почему-то нажимается совсем другая кнопка! Как это можно обработать, и почему так происходит? Т.е. нужно, чтобы просто переносило на другую строку.
О! Это древняя фича винды, которая так-то описана в документации, но я лет 10 назад, тоже наступив на неё, нашёл её корни под дебагом, в ассемблере, в системных библиотеках. Ностальгия
Суть фичи: если 1. на диалоге 2. мультистрочный edit, то, при наличии фокуса, при нажатии enter ищется кнопка с ID = IDOK и жмётся.
Точно не скажу, но вроде ES_WANTRETURN спасает ситуацию. Если не спасает, то можно ловить WM_COMMAND в диалоге и проверять, где фокус: если на мультиедите — игнорируем и работаем дальше. А так же: нажатие enter-а с зажатым shift-ом должно тоже делать перевод на следующую строчку. И вроде при ES_WANTRETURN этот функционал инвертируется.
Здравствуйте, 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) зовется.
Здравствуйте, morgot, Вы писали:
Q>>За это поведение отвечает функция IsDialogMessage, которая зовется в цикле обработки сообщений.
M>Ради интереса — а куда ее вставлять? Если у меня обычный модальный диалог, т.е. нет CreateWindows и цикла обработки сообщений.
Если используется функция DialogBoxXXX, она внутри содержит цикл обработки и вызов IsDialogMessage.
Тут скорее речь идет о подавлении, создаваемого ей эффекта.
P.S. Стили типа ES_WANTRETURN лучше указывать в шаблоне диалога (если заранее известны).
Не все стили можно установить/изменить с помощью SetWindowLong после создания окна (и чтобы, при этом, работали правильно).
Например, ES_MULTILINE — нельзя.
Здравствуйте, qaz77, Вы писали:
Q>P.S. Стили типа ES_WANTRETURN лучше указывать в шаблоне диалога (если заранее известны). Q>Не все стили можно установить/изменить с помощью SetWindowLong после создания окна (и чтобы, при этом, работали правильно).
А где это указывать? Если я использую функцию DialogBox(), то там нет такого параметра (имею ввиду, задать для Edit отдельно стиль(. Наверное, следует тогда юзать CreateWindow(Ex) ?
Здравствуйте, 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 файле, там простой синтаксис.