Blog. Just Blog

Как сделать перетаскиваемый курсор-прицел

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
У многих программ для работы с окнами приложений есть такая фича, как перетаскиваемый указатель-прицел, с помощью которого можно выбрать определенное окно. Когда-то у меня в комментариях спросили, как можно сделать что-то подобное. Что ж, лучше поздно, чем никогда.

Начнем с теории, как это все должно работать. На форме программы сперва рисуется значок прицела, это самая обычная статическая картинка. При клике на нее активируется процесс перетаскивания. Системный курсор меняется на этот же прицел, а значок на форме скрывается. Тем самым достигается визуальный эффект, что перетаскивается именно прицел с формы. Пока кнопка мыши нажата, обрабатываются координаты курсора и выполняются нужные действия с этой информацией. При отпускании кнопки мыши курсор меняется на дефолтный системный, а на форме снова отображается картинка. Таким образом нам надо отслеживать три сообщения окна: WM_LBUTTONDOWN для нажатия левой кнопки мыши, WM_LBUTTONUP для ее отпускания и WM_MOUSEMOVE для перемещения мыши.
  1.         cmp     [msg],WM_LBUTTONDOWN
  2.         je      .wmsetcursor
  3.         cmp     [msg],WM_LBUTTONUP
  4.         je      .wmreleasecursor
  5.         cmp     [msg],WM_MOUSEMOVE
  6.         je      .wmmousemove
Теперь разберем каждый обработчик более подробно. При нажатии левой кнопки мыши сперва проверяется координата, по которой было произведено нажатие. Если она находится внутри области, занимаемой картинкой прицела на форме, то загружается курсор, прячется картинка, как написано выше.
  1. .wmsetcursor:
  2.         ; Получить координаты события
  3.         invoke  GetMessagePos
  4.         ; Координата Y
  5.         mov     ebx,eax
  6.         shr     ebx,16
  7.         mov     [pt.y],ebx
  8.         ; Координата X
  9.         mov     ebx,eax
  10.         and     ebx,0FFFFh
  11.         mov     [pt.x],ebx
  12.  
  13.         ; Получить границы иконки
  14.         invoke  GetWindowRect,[hStatic],img
  15.  
  16.         ; Клик произошел в области иконки?
  17.         invoke  PtInRect,img,[pt.x],[pt.y]
  18.         or      eax,eax
  19.         jz      .processed
  20.  
  21.         ; Установить захват событий мыши
  22.         invoke  SetCapture,[hwnddlg]
  23.  
  24.         ; Загрузить наш курсор
  25.         invoke  SetCursor,[hCursor]
  26.  
  27.         ; Скрыть иконку на форме
  28.         invoke  SendMessage,[hStatic],STM_SETIMAGE,IMAGE_CURSOR,0
  29.  
  30.         mov     [state],1
Но главное, надо обязательно установить захват мыши для окна программы при помощи функции SetCapture. Иначе события перемещения перестанут передаваться, как только курсор покинет пределы окна. Также надо взвести флаг, что теперь выполняется перемещение прицела.

При отпускании левой кнопки мыши надо освободить захват событий мыши при помощи функции ReleaseCapture, вернуть картинку прицела на место и установить дефолтный курсор. Флаг активности также надо сбросить.
  1. .wmreleasecursor:
  2.         ; Отпустить захват событий мыши
  3.         invoke  ReleaseCapture
  4.  
  5.         ; Загрузить стандартный курсор
  6.         invoke  LoadCursor,NULL,IDC_ARROW
  7.         invoke  SetCursor,eax
  8.  
  9.         ; Вернуть иконку на место
  10.         invoke  SendMessage,[hStatic],STM_SETIMAGE,IMAGE_CURSOR,[hCursor]
  11.  
  12.         mov     [state],0
Основной функционал приложения ложится на обработчик перемещения курсора. Тут первым делом проверяется флаг активности, если он не установлен, то ничего делать не требуется. Если он взведен, то следует получить координаты курсора, определить окно под курсором и выполнить с этой информацией нужные действия. Поскольку в режиме активного перемещения выполнен захват окном событий мыши, то в него будут поступать сообщения при перемещении курсора по всему экрану, а не только над окном программы.
  1. .wmmousemove:
  2.         ; Режим отслеживания?
  3.         cmp     [state],1
  4.         jne     .processed
  5.  
  6.         ; Координаты курсора
  7.         invoke  GetCursorPos,pt
  8.  
  9.         ; Действия по этим координатам
В приложении пример программы с исходным текстом, которая реализует перетаскиваемый курсор-прицел.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Target.Cursor.Demo.zip (4,556 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 441 | Комментариев: 2

Метки: Assembler

Комментарии

Отзывы посетителей сайта о статье
semiono (05.04.2024 в 03:35):
Ну, получилось! Добавился ресурс из comctl32.dll.
Правда как обработать контрол не знаю, к одному человеку снова неловко обращаться) Как бы мне этим контролом зачения байта крутить)
0 – 7Fh практически всегда рабочий диапазон.
semiono (31.03.2024 в 23:56):
Приветствую! Может быть было где-то, но никогда не встречал фейдеров, крутилок контролов, хотььчего-то лишь бы работало.
numeric up down control, Slider Control, spin control.
Был бы пример Fasm, я к сожалению нибумбум, но недавно сделал
ComboBox шикарно работает! Просто фронт-енд для консольной sendmidi.exe.
А вот крутилку бы привинтить чтобы что-нибудь регулировало...
По миди обычно диапазон 0 – 7Fh
Может где-то есть пример на слайдер?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.08 сек. / MySQL: 2 (0.0047 сек.) / Память: 4.5 Mb
Наверх