Еще один интересный трюк при работе с окнами - так называемые "липкие" или "магнитные" окна, которые прилипают к границам экрана при перемещении. Это реализуется достаточно просто, но выглядит очень эффектно. Для перехвата перемещения окна надо обрабатывать сообщение 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 пикселов.
В приложении рабочий пример программы с "магнитным" окном. При включенной галочке окно приобретает магнитные свойства, при отключенной становится обычным. Чтобы отлепить окно от края экрана его надо резко дернуть в сторону.