Магнитное окно с учетом нескольких мониторов
Продолжаем работу над ошибками. Несколько лет назад в одной из статей я рассказывал, как сделать окно, которое при перемещении будет прилипать ко краям экрана. Этот способ рабочий, но он не учитывает ситуацию, когда у пользователя более одного монитора. Дело в том, что функция SystemParametersInfo с параметром SPI_GETWORKAREA возвращает координаты рабочей области только основного монитора. Для поддержки нескольких мониторов, в том числе произвольных размеров, надо сперва определить, на каком мониторе находится окно. Затем надо будет получить характеристики этого монитора, точнее координаты его рабочей области. Но сперва придется определить структуру и константу, про которую не знает коробочный FASM.Code (Assembler) : Убрать нумерацию
- MONITOR_DEFAULTTONEAREST = 2
- struct MONITORINFO
- cbSize dd ?
- rcMonitor RECT
- rcWork RECT
- dwFlags dd ?
- ends
В остальном код очень похож на предыдущий пример. Точно так же обрабатывается событие окна WM_MOVING, точно так же задается размер магнитной сетки MAX_GRID. Только для удобства я вынес проверку и корректировку координат окна в отдельную процедуру:
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------------------------
- ; Корректировка координат окна с учетом положения относительно
- ; границ монитора, на котором он находится
- ;---------------------------------------------------------------------
- ; Параметры:
- ; hwnd - хэндл окна
- ; coord - координаты окна
- ; grid - размер магнитной сетки
- ;---------------------------------------------------------------------
- proc StickyWindow hwnd:DWORD, coord:DWORD, grid:DWORD
- MONITOR_DEFAULTTONEAREST = 2
- struct MONITORINFO
- cbSize dd ?
- rcMonitor RECT
- rcWork RECT
- dwFlags dd ?
- ends
- locals
- minfo MONITORINFO
- endl
- pusha
- ; Монитор, на котором находится окно
- invoke MonitorFromWindow,[hwnd],MONITOR_DEFAULTTONEAREST
- ; В регистре ESI указатель на структуру информации о мониторе
- lea esi,[minfo]
- mov [esi+MONITORINFO.cbSize],sizeof.MONITORINFO
- invoke GetMonitorInfo,eax,esi
- ; В регистре EDI указатель на структуру координат окна
- mov edi,[coord]
- ; Смещение окна относительно левой границы экрана
- mov edx,[edi+RECT.left]
- sub edx,[esi+MONITORINFO.rcWork.left]
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.right],eax
- sub [edi+RECT.left],eax
- @@:
- ; Смещение окна относительно правой границы экрана
- mov edx,[edi+RECT.right]
- sub edx,[esi+MONITORINFO.rcWork.right]
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.right],eax
- sub [edi+RECT.left],eax
- @@:
- ; Смещение окна относительно верхней границы экрана
- mov edx,[edi+RECT.top]
- sub edx,[esi+MONITORINFO.rcWork.top]
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.top],eax
- sub [edi+RECT.bottom],eax
- @@:
- ; Смещение окна относительно нижней границы экрана
- mov edx,[edi+RECT.bottom]
- sub edx,[esi+MONITORINFO.rcWork.bottom]
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.top],eax
- sub [edi+RECT.bottom],eax
- @@:
- popa
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ;---------------------------------------------------------------------
- ; Корректировка координат окна с учетом положения относительно
- ; границ монитора, на котором он находится
- ;---------------------------------------------------------------------
- ; Параметры:
- ; hwnd - хэндл окна
- ; coord - координаты окна
- ; grid - размер магнитной сетки
- ;---------------------------------------------------------------------
- proc StickyWindow hwnd:DWORD, coord:DWORD, grid:DWORD
- MONITOR_DEFAULTTONEAREST = 2
- struct MONITORINFO
- cbSize dd ?
- rcMonitor RECT
- rcWork RECT
- dwFlags dd ?
- ends
- locals
- minfo MONITORINFO
- endl
- pusha
- ; Монитор, на котором находится окно
- invoke MonitorFromWindow,[hwnd],MONITOR_DEFAULTTONEAREST
- ; В регистре ESI указатель на структуру информации о мониторе
- lea esi,[minfo]
- mov [esi+MONITORINFO.cbSize],sizeof.MONITORINFO
- invoke GetMonitorInfo,eax,esi
- ; Учитывать толщину рамки окна
- invoke GetSystemMetrics,SM_CXFRAME
- shr eax,1
- mov ecx,eax
- ; В регистре EDI указатель на структуру координат окна
- mov edi,[coord]
- ; Смещение окна относительно левой границы экрана
- mov edx,[edi+RECT.left]
- sub edx,[esi+MONITORINFO.rcWork.left]
- sub edx,ecx
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.right],eax
- sub [edi+RECT.left],eax
- @@:
- ; Смещение окна относительно правой границы экрана
- mov edx,[edi+RECT.right]
- sub edx,[esi+MONITORINFO.rcWork.right]
- add edx,ecx
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.right],eax
- sub [edi+RECT.left],eax
- @@:
- ; Смещение окна относительно верхней границы экрана
- mov edx,[edi+RECT.top]
- sub edx,[esi+MONITORINFO.rcWork.top]
- sub edx,ecx
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.top],eax
- sub [edi+RECT.bottom],eax
- @@:
- ; Смещение окна относительно нижней границы экрана
- mov edx,[edi+RECT.bottom]
- sub edx,[esi+MONITORINFO.rcWork.bottom]
- add edx,ecx
- mov eax,edx
- jns @f
- neg edx
- @@:
- cmp edx,[grid]
- ja @f
- sub [edi+RECT.top],eax
- sub [edi+RECT.bottom],eax
- @@:
- popa
- ret
- endp
Code (Assembler) : Убрать нумерацию
- ; Обработчик событий окна
- cmp [msg],WM_MOVING
- je moving_window
- ...
- ...
- ...
- moving_window:
- ; Примагничивание окна при перетаскивании его мышкой
- stdcall StickyWindow,[hwnddlg],[lparam],MAX_GRID
Code (Assembler) : Убрать нумерацию
- some_case:
- ; Примагничивание окна при каком-либо событии
- invoke GetWindowRect,[hwnddlg],coord
- stdcall StickyWindow,[hwnddlg],coord,MAX_GRID
- mov eax,[coord.right]
- sub eax,[coord.left]
- mov ebx,[coord.bottom]
- sub ebx,[coord.top]
- invoke MoveWindow,[hwnddlg],[coord.left],[coord.top],eax,ebx,TRUE
Просмотров: 2014 | Комментариев: 0
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария