Магнитное (липкое) окно на Ассемблере

Еще один интересный трюк при работе с окнами - так называемые "липкие" или "магнитные" окна, которые прилипают к границам экрана при перемещении. Это реализуется достаточно просто, но выглядит очень эффектно. Для перехвата перемещения окна надо обрабатывать сообщение WM_MOVING. В параметре lParam передается адрес структуры RECT, которая содержит значения конечных координат окна после отпускания курсора мыши. Чтобы при изменении координат окна не возникало неприятного эффекта моргания, их надо менять сразу же в передаваемой структуре. Обработчик WM_MOVING выглядит следующим образом:
; Обработчик сообщения WM_MOVING
 
MAX_GRID = 20   ; Размер магнитной сетки
 
; Проверить положение левой границы окна
chk_left_position:
        ; В регистре EDX указатель на структуру координат окна
        mov     edx,[lparam]
        mov     eax,dword [edx+0]  ; left
        mov     ecx,dword [edx+8]  ; right
        sub     ecx,eax
        test    eax,eax
        jns     @f
        neg     eax
@@:
        cmp     eax,MAX_GRID
        ja      @f
        mov     dword [edx+0],0
        mov     dword [edx+8],ecx
@@:
 
; Проверить положение правой границы окна
chk_right_position:
        ; Получить размер рабочей области экрана
        invoke  SystemParametersInfo,SPI_GETWORKAREA,NULL,coord,FALSE
 
        ; В регистре EDX указатель на структуру координат окна
        mov     edx,[lparam]
 
        mov     eax,dword [edx+8]  ; right
        sub     eax,dword [edx+0]  ; left
        push    eax
 
        mov     eax,[coord.right]  ; workarea right
        mov     ecx,dword [edx+8]  ; right
        sub     eax,ecx
        test    eax,eax
        jns     @f
        neg     eax
@@:
        cmp     eax,MAX_GRID
        pop     eax
        ja      @f
        mov     ecx,[coord.right]
        mov     dword [edx+8],ecx
        sub     ecx,eax
        mov     dword [edx+0],ecx
@@:
 
; Проверить положение верхней границы окна
chk_top_position:
; В регистре EDX указатель на структуру координат окна
        mov     edx,[lparam]
        mov     eax,dword [edx+4]   ; top
        mov     ecx,dword [edx+12]  ; bottom
        sub     ecx,eax
        test    eax,eax
        jns     @f
        neg     eax
@@:
        cmp     eax,MAX_GRID
        ja      @f
        mov     dword [edx+4],0
        mov     dword [edx+12],ecx
@@:
 
; Проверить положение нижней границы окна
chk_bottom_position:
        ; Получить размер рабочей области экрана. Структура coord
        ; определена заранее в сегменте данных
        invoke  SystemParametersInfo,SPI_GETWORKAREA,NULL,coord,FALSE
 
        ; В регистре EDX указатель на структуру координат окна
        mov     edx,[lparam]
 
        mov     eax,dword [edx+12]  ; bottom
        sub     eax,dword [edx+4]   ; top
        push    eax
 
        mov     eax,[coord.bottom]  ; workarea bottom
        mov     ecx,dword [edx+12]  ; bottom
        sub     eax,ecx
        test    eax,eax
        jns     @f
        neg     eax
@@:
        cmp     eax,MAX_GRID
        pop     eax
        ja      @f
        mov     ecx,[coord.bottom]
        mov     dword [edx+12],ecx
        sub     ecx,eax
        mov     dword [edx+4],ecx
@@:
        mov     eax,TRUE
        jmp     finish

Размеры области экрана для вычисления новых координат окна с учетом таскбара и других видимых панелей можно получить вызовом функции SystemParametersInfo с параметром SPI_GETWORKAREA. В приведенном примере размер магнитной сетки (минимальное расстояние до границы экрана, с которого начинает действовать сила притяжения), меняется в константе MAX_GRID. По умолчанию значение равно 20 пикселов.

В приложении рабочий пример программы с "магнитным" окном. При включенной галочке окно приобретает магнитные свойства, при отключенной становится обычным. Чтобы отлепить окно от края экрана его надо резко дернуть в сторону.
Теги:
окно
Добавлено: 10 Апреля 2018 20:16:55 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...