Блокировка автовыделения текста в поле EDIT
При создании диалогового окна, а также при перемещении по его элементам клавишей табуляции, текст в полях типа EDIT автоматически выделяется. Это стандартное поведение системы, так предусмотрено разработчиками Windows. Интересный вопрос, почему сделано именно так. Может быть самому Биллу Гейтсу было лениво нажимать кнопки Ctrl+A перед копированием текста из форм, может быть еще что-то, ответа я не знаю. Но зато у меня есть ответ на другой вопрос: можно ли сделать так, чтобы текст в поле EDIT автоматически не выделялся?Перед тем, как принять решение о (не)выделении текста в поле EDIT, система посылает элементу диалогового окна сообщение WM_GETDLGCODE, которое должно вернуть соответствующий набор флагов. Так вот, если в ответе взведен флаг DLGC_HASSETSEL, то текст выделяется. Несложно догадаться, что по умолчанию этот флаг взводится всегда. При этом сообщение WM_GETDLGCODE самим диалоговым окном никак не обрабатывается, так что нужно воспользоваться уже известным нам субклассированием. Будь то разовое для конкретного поля или универсальное субклассирование, не важно.
Code (Assembler) : Убрать нумерацию
- ; Сегмент данных
- section '.data' data readable writeable
- OldProc dd ? ; Адрес предыдущего обработчика
- ; Сегмент кода
- section '.code' code readable executable
- ...
- ; Субклассирование на этапе инициализации окна
- invoke GetDlgItem,[hwnddlg],ID_SUB
- ; Установить наш собственный обработчик
- invoke SetWindowLong,eax,GWL_WNDPROC,EditWindowProc
- ; Сохранить хэндл предыдущего обработчика
- mov [OldProc],eax
- ...
Делается это очень просто. В субклассированном обработчике элемента диалогового окна ловим сообщение WM_GETDLGCODE, отправляем запрос дальше по цепочке через CallWindowProc, но в полученном ответе сбрасываем соответствующий флаг DLGC_HASSETSEL:
Code (Assembler) : Убрать нумерацию
- proc EditWindowProc hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
- ; Пришло сообщение WM_GETDLGCODE?
- cmp [uMsg],WM_GETDLGCODE
- je .getdlgcode
- ...
- .getdlgcode:
- ; Передать управление предыдущему обработчику
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
- ; Подавить в ответе флаг DLGC_HASSETSEL
- and eax,NOT DLGC_HASSETSEL
- ret
Но раз уж речь коснулась сообщения сообщения WM_GETDLGCODE и сопутствующих флагов, то давайте еще разберем флаг DLGC_WANTMESSAGE. На секунду отвлечемся. Как известно, если в диалоговом окне нажать клавишу Esc, то окну будет отправлено сообщение WM_CLOSE, неважно, был ли в это время активен какой-нибудь из его элементов или было активно само окно. Возвращаемся к теме. Перед тем, как отправить сообщение WM_CLOSE главному обработчику диалогового окна, система интересуется, а нет ли у активного элемента диалогового окна желания как-то прореагировать на нажатие кнопки Esc? Опять же, как несложно догадаться, при стандартном поведении означенных элементов, такого желания у них возникать не должно. По умолчанию флаг DLGC_WANTMESSAGE возвращается сброшенным, но раз уж мы субклассировали обработчик элемента, то почему бы не обработать и этот флаг? Отрабатываем сообщение, как показано выше, затем для ответа взводим флаг DLGC_WANTMESSAGE. Таким образом главный обработчик диалогового окна никогда не узнает о том, что от него хотела система.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------
- ; Субклассированный обработчик
- ;------------------------------------------------
- proc EditWindowProc hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
- cmp [uMsg],WM_GETDLGCODE
- je .getdlgcode
- .char_ok:
- ; Передать управление предыдущему обработчику или пропустить
- ; разрешенный символ
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
- ret
- .getdlgcode:
- ; Передать управление предыдущему обработчику
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
- ; Подавить в ответе флаг DLGC_HASSETSEL
- and eax,NOT DLGC_HASSETSEL
- ; Нажата клавиша Esc?
- cmp [wParam],27
- jne @f
- ; Очистить поле ввода
- push eax
- invoke SendMessage,[hEdit],WM_SETTEXT,0,0
- pop eax
- ; Взвести в ответе флаг DLGC_WANTMESSAGE
- or eax,DLGC_WANTMESSAGE
- @@:
- ret
- endp
В приложении пример программы с исходным текстом, которая создает в диалоговом окне обычное и субклассированное поле ввода. Субклассированное поле подавляет автоматическое выделение текста, а по нажатию клавиши Esc очищает содержимое.
Просмотров: 1095 | Комментариев: 2
Метки: Assembler
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(01.04.2020 в 11:29):
Так ведь никто же не заставляет так делать всегда. Но когда возникнет необходимость, тогда уже будет готовое решение.
user
(01.04.2020 в 08:27):
Да чего там - реально удобно с этим автовыделением.
Тем более, что оно сбрасывается при первом же движении курсора.
Тем более, что оно сбрасывается при первом же движении курсора.
Добавить комментарий
Заполните форму для добавления комментария