Поле для ввода только цифр организовать несложно, для этого достаточно просто прописать в ресурсах у нужного поля флаг ES_NUMBER. После этого с клавиатуры в это поле можно будет ввести только символ из интервала "0" - "9". Впрочем этот ничуть не мешает через Ctrl+C / Ctrl+V затолкать в него все что угодно, вплоть до непечатных бинарных данных. А как сделать поле, в которое можно вводить с клавиатуры только шестнадцатеричные цифры? Ведь там могут быть не только символы с десятичными цифрами, но и символы "A" - "F", которые также являются шестнадцатеричными цифрами. Это делается через субклассирование. Мы уже рассмотрели один пример субклассирования,
превратив поле EDIT в гиперссылку, и там же определили алгоритм обработчика субклассированного элемента. Как и в прошлый раз, субклассирование должно выполняться на этапе инициализации диалогового окна.
; Сегмент данных
section '.data' data readable writeable
OldProc dd ? ; Адрес предыдущего обработчика
; Сегмент кода
section '.code' code readable executable
...
; Субклассирование на этапе инициализации окна
invoke GetDlgItem,[hwnddlg],ID_HEX
; Установить наш собственный обработчик
invoke SetWindowLong,eax,GWL_WNDPROC,EditWindowProc
; Сохранить хэндл предыдущего обработчика
mov [OldProc],eax
...
Здесь все почти то же самое, разница будет лишь в обрабатываемых сообщениях. Соответственно, если будет несколько полей ввода, то надо субклассировать каждое из них отдельно.
Назначенная процедура EditWindowProc будет обрабатывать только одно сообщение: WM_CHAR, оно происходит при нажатии на любую клавишу, когда курсор находится в нашем поле EDIT. При фильтрации нажатых клавиш, кроме шестнадцатеричных цифр не забывайте про служебные комбинации Ctrl+C / Ctrl+V и клавишу Backspace. Все остальные клавиши фильтруются и блокируются. Похожий пример на MASM был показан в одном из уроков Iczelion'а, но в нем не учитывались клавиши копирования-вставки.
proc EditWindowProc hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
; Нажатие клавиши?
cmp [uMsg],WM_CHAR
je .chk_char
.char_ok:
; Передать управление предыдущему обработчику или пропустить
; разрешенный символ
invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
ret
.chk_char:
; Проверить код нажатой клавиши
mov eax,[wParam]
cmp al,VK_BACK ; Backspace
je .char_ok
cmp al,22 ; Ctrl+V
je .char_ok
cmp al,3 ; Ctrl+C
je .char_ok
cmp al,'0' ; Hex-цифра?
jb .exit_proc
cmp al,'9'
jbe .char_ok
or al,20h ; Символ в нижний регистр
cmp al,'a'
jb .exit_proc
cmp al,'f'
jbe .char_ok
.exit_proc:
; Подавить сообщение нажатия клавиши и вернуть из обработчика FALSE
xor eax,eax
ret
endp
Обработчик можно легко модифицировать для других правил фильтрации ввода, например, если требуется ввести только латинские символы или число в восьмеричной системе счисления. Напоминаю, что такие методы обеспечивают защиту только от ручного ввода, и никакое субклассирование не спасает от копирования и вставки данных в поле EDIT. Поэтому обязательно выполняйте дополнительные проверки при чтении и дальнейшем использовании введенных данных!
В приложении пример диалогового окна с двумя полями ввода. Одно имеет флаг ES_NUMBER для ввода десятичных цифр, второе реализовано через субкласирование и позволяет вводить шестнадцатеричные цифры.