
Блокировка автовыделения текста в поле 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 очищает содержимое.
Просмотров: 1289 | Комментариев: 2
Метки: Assembler
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(01.04.2020 в 11:29):
Так ведь никто же не заставляет так делать всегда. Но когда возникнет необходимость, тогда уже будет готовое решение.
user
(01.04.2020 в 08:27):
Да чего там - реально удобно с этим автовыделением.
Тем более, что оно сбрасывается при первом же движении курсора.
Тем более, что оно сбрасывается при первом же движении курсора.
Добавить комментарий
Заполните форму для добавления комментария
Пример программы с исходным текстом (FASM)

