Графический курсор (каретка) в поле EDIT
Сегодня отдохнем от системы и немного поработаем с графикой, будем делать собственный графический курсор в поле EDIT. Какого-то необычайно полезного практического применения этому нет, просто симпатичное дополнение к интерфейсу, например, к окнам нестандартной формы. Ну а что, раз уж наворотили чудо-окна, почему бы не наворотить и чудо-курсор.Начнем с теории. В отличие от "мышиного" курсора, который может легко принимать любой вид, управлять кареткой, то есть курсором в текстовом поле, не так просто. Функция CreateCaret позволяет только описывать форму для каретки, но не меняет ее изображение. Достаточно один раз попробовать, чтобы убедиться в ее бесполезности. Придется самостоятельно рисовать графическую каретку на холсте поля ввода.
Code (Assembler) : Убрать нумерацию
- ; Загрузить из ресурсов картинку
- invoke GetModuleHandle,0
- invoke LoadBitmap,eax,1
- mov [hСaret],eax
- ; Выбрать картинку для холста поля ввода
- invoke GetDlgItem,[hwnddlg],ID_EDIT
- invoke GetDC,eax
- mov [hDC],eax
- invoke CreateCompatibleDC,[hDC]
- mov [hСaretDC],eax
- invoke SelectObject,[hСaretDC],[hСaret]
- ; Получить цвет угловой точки картинки
- invoke GetPixel,[hСaretDC],0,0
- mov [bColor],eax
- ; Создать кисть с этим цветом
- invoke CreateSolidBrush,[bColor]
- mov [hBrush],eax
- ; Прибраться за собой
- invoke DeleteObject,[hСaret]
Тут есть одна проблема, которую мне не удалось решить. Дело в том, что даже если создать BMP с прозрачностью, то при его загрузке и наложении на форму все прозрачные места будут перекрашены в черный цвет. Поэтому приходится использовать картинку курсора, например, на белом фоне, а затем при создании окна назначать этот же фон полю ввода. Если найдете нормальный способ загрузки и отрисовки картинки с прозрачностью, то вся эта свистопляска с подгонкой фона поля ввода не понадобится. Чтобы хоть немного облегчить задачу, за фоновый цвет принимается угловая точка картинки курсора.
Code (Assembler) : Убрать нумерацию
- cmp [msg],WM_CTLCOLOREDIT
- je .wm_color
- ...
- ...
- .wm_color:
- ; Красный текст
- invoke SetTextColor,[wparam],0x000000FF
- ; Подогнать фон под картинку
- invoke SetBkColor,[wparam],[bColor]
- ; Установить режим смешивания фоновых цветов
- invoke SetBkMode,[wparam],OPAQUE
- ; Фоновая кисть
- mov eax,[hBrush]
- jmp .finish
Поскольку основная работа происходит непосредственно в пределах поля ввода, его обработчик придется субклассировать. Из-за ограничений в реализации графическая каретка должна работать по терминальному принципу, то есть она всегда находится после текста, а новые символы добавляются только в конец строки. Именно это и надо оформить в субклассированном обработчике. При получении сообщения о нажатии клавиши каретка принудительно переводится в конец поля ввода, а только потом обрабатывается само нажатие. Там же при наступлении различных событий штатная каретка скрывается при помощи функции HideCaret, а часть сообщений вообще подавляются, чтобы не допустить установку каретки в середину текста. Кроме перечисленных действий, в поле ввода блокируется автовыделение текста при перемещении по форме клавишей табуляции.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------
- ; Субклассированный обработчик
- ;------------------------------------------------
- proc EditWindowProc hEdit:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
- cmp [uMsg],WM_GETDLGCODE
- je .getdlgcode
- cmp [uMsg],WM_CHAR
- je .wm_char
- cmp [uMsg],WM_PAINT
- je .wm_paint
- cmp [uMsg],WM_SETFOCUS
- je .wm_paint
- cmp [uMsg],WM_LBUTTONDOWN
- je .cancel
- cmp [uMsg],WM_LBUTTONDBLCLK
- je .cancel
- cmp [uMsg],WM_KEYDOWN
- je .cancel
- .char_ok:
- ; Передать управление предыдущему обработчику или пропустить
- ; разрешенный символ
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
- ret
- .cancel:
- ; Спрятать курсор
- invoke HideCaret,[hEdit]
- ; Подавить сообщение
- xor eax,eax
- ret
- .wm_paint:
- ; Курсор в конец текста
- invoke SendMessage,[hEdit],WM_GETTEXTLENGTH,0,0
- invoke SendMessage,[hEdit],EM_SETSEL,eax,eax
- ; Спрятать курсор
- invoke HideCaret,[hEdit]
- jmp .char_ok
- .wm_char:
- ; Курсор в конец текста
- invoke SendMessage,[hEdit],WM_GETTEXTLENGTH,0,0
- invoke SendMessage,[hEdit],EM_SETSEL,eax,eax
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
- ; Перерисовать содержимое окна
- invoke InvalidateRect,[hEdit],0,TRUE
- invoke UpdateWindow,[hEdit]
- ret
- .getdlgcode:
- ; Спрятать курсор
- invoke HideCaret,[hEdit]
- ; Передать управление предыдущему обработчику
- invoke CallWindowProc,[OldProc],[hEdit],[uMsg],[wParam],[lParam]
- ; Подавить в ответе флаг DLGC_HASSETSEL
- and eax,NOT DLGC_HASSETSEL
- ret
- endp
Code (Assembler) : Убрать нумерацию
- .wmtimer:
- ; Получить координаты каретки
- invoke GetCaretPos,CaretPos
- ; Немного сдвинуть вправо
- add [CaretPos.x],1
- ; Нарисовать картинку сердечка
- invoke BitBlt,[hDC],[CaretPos.x],[CaretPos.y],32,32,\
- [hСaretDC],0,0,SRCCOPY
В приложении пример программы с исходным текстом, которая рисует собственную каретку в поле ввода и обрабатывает ввод текста.
Просмотров: 1637 | Комментариев: 7
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(15.09.2021 в 22:45):
Не смог воспроизвести ситуацию с кареткой, я вроде предусмотрел ее подавление в разных ситуациях.
==DJ==[ZLO]
(14.09.2021 в 08:18):
==DJ==[ZLO]
(13.09.2021 в 21:56):
Что-то похожее видел в кейгенах.
[Дело в том, что даже если создать BMP с прозрачностью, то при его загрузке и наложении на форму все прозрачные места будут перекрашены в черный цвет.]
- А с пнг такое не прокатит?
Заметил штуку: (Win7) При запуске customcaret в системной панели перейти на другое приложение и вернуться щелкнув customcaret появляется каретка | возле сердечка и остаётся мигать пока не нажмешь на edit.
[Дело в том, что даже если создать BMP с прозрачностью, то при его загрузке и наложении на форму все прозрачные места будут перекрашены в черный цвет.]
- А с пнг такое не прокатит?
Заметил штуку: (Win7) При запуске customcaret в системной панели перейти на другое приложение и вернуться щелкнув customcaret появляется каретка | возле сердечка и остаётся мигать пока не нажмешь на edit.
wet
(12.08.2021 в 20:55):
Проблема с индикатором раскладки решается гораздо проще. Как известно в поле ввода системный курсор мыши принимает вид OCR_IBEAM - I-образный курсор.
Всё что нам нужно, это заменять безликий I-образный курсор на свой красивый, с флагом страны например. Мониторить GetKeyboardLayout на предмет раскладки, и ставить свои курсоры SetSystemCursor. Курсоры брать из файла ресурсов, как вариант. Программа на несколько строк.
Всё что нам нужно, это заменять безликий I-образный курсор на свой красивый, с флагом страны например. Мониторить GetKeyboardLayout на предмет раскладки, и ставить свои курсоры SetSystemCursor. Курсоры брать из файла ресурсов, как вариант. Программа на несколько строк.
ManHunter
(09.08.2021 в 10:32):
Кстати, да, отличный пример с раскладкой.
rnd
(09.08.2021 в 07:05):
Ну, практическое применение графическому курсору есть, правда почему-то большинство разработчиков игнорируют этот запрос, даже создатели ОСей.
Логично предположить, коль наше внимание уперлось в курсорное поле, то мы ожидаем там увидеть не только само поле и текст с курсором, но и... правильно - раскладку клавиатуры, дабы не стрелять глазами на панель - какой же там язык сейчас на раскладке (?)
Неплохо в этом смысле организована программа Curlit, хотя есть и другие в том числе и платные, увы. Когда мы смотрим на курсор - то лучше видеть сразу информацию о раскладке (флаг языка, например), и это освобождает наше внимание от поиска переключения раскладки на панели, которая имеет свойство ещё и сворачиваться...
Логично предположить, коль наше внимание уперлось в курсорное поле, то мы ожидаем там увидеть не только само поле и текст с курсором, но и... правильно - раскладку клавиатуры, дабы не стрелять глазами на панель - какой же там язык сейчас на раскладке (?)
Неплохо в этом смысле организована программа Curlit, хотя есть и другие в том числе и платные, увы. Когда мы смотрим на курсор - то лучше видеть сразу информацию о раскладке (флаг языка, например), и это освобождает наше внимание от поиска переключения раскладки на панели, которая имеет свойство ещё и сворачиваться...
Добавить комментарий
Заполните форму для добавления комментария
https://www.mediafire.com/file...7_083555.mp4
-upd
на 7-ke тоже самое. Вот только при записи заметил, что он не постоянно мигает, а только шесть раз.