
Быстрый поиск
Введите фрагмент названия статьи для поиска

Установка окна по центру с учетом нескольких мониторов
24.06.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
И вновь работа над ошибками. На этот раз переосмысление статьи об установке окна по центру экрана. Приведенный там код работает без проблем, но только для единственного монитора, при наличии двух и более мониторов результат получается неправильным. Основные принципы работы с несколькими мониторами я расписал в предыдущей статье, повторять не буду.Code (Assembler) : Убрать нумерацию
- ;-------------------------------------------------------------------------
- ; Процедура перемещения окна в центр экрана. Если окно развернуто или
- ; его размеры превышают размеры экрана, то окно не перемещается
- ; Параметры:
- ; hwnd - хэндл окна
- ; mode - относительно каких координат центровать окно (1 - только
- ; рабочая область экрана с учетом размеров панели задач и
- ; различных тулбаров, 0 - относительно размеров всего экрана)
- ;-------------------------------------------------------------------------
- proc WindowToCenterEx hwnd:DWORD, mode:DWORD
- MONITOR_DEFAULTTONEAREST = 2
- struct MONITORINFO
- cbSize dd ?
- rcMonitor RECT
- rcWork RECT
- dwFlags dd ?
- ends
- locals
- minfo MONITORINFO
- coord RECT
- endl
- ; Сохранить все регистры
- pusha
- ; Такое окно существует?
- invoke IsWindow,[hwnd]
- or eax,eax
- jz .loc_ret
- ; Окно развернуто на весь экран?
- invoke IsZoomed,[hwnd]
- or eax,eax
- jnz .loc_ret
- ; Получить размеры окна
- lea eax,[coord]
- invoke GetWindowRect,[hwnd],eax
- ; Монитор, на котором находится окно
- invoke MonitorFromWindow,[hwnd],MONITOR_DEFAULTTONEAREST
- ; В регистре ESI указатель на структуру информации о мониторе
- lea esi,[minfo]
- mov [esi+MONITORINFO.cbSize],sizeof.MONITORINFO
- invoke GetMonitorInfo,eax,esi
- ; Весь экран
- lea esi,[minfo.rcMonitor]
- cmp [mode],0
- je @f
- ; Рабочая область экрана
- lea esi,[minfo.rcWork]
- @@:
- mov eax,[esi+RECT.right]
- sub eax,[esi+RECT.left]
- lea edi,[coord]
- mov ebx,[edi+RECT.right]
- sub ebx,[edi+RECT.left]
- ; Окно шире монитора
- cmp ebx,eax
- jg .loc_ret
- mov ecx,[esi+RECT.bottom]
- sub ecx,[esi+RECT.top]
- mov edx,[edi+RECT.bottom]
- sub edx,[edi+RECT.top]
- ; Окно выше монитора
- cmp edx,ecx
- jg .loc_ret
- shr ebx,1
- shr eax,1
- add eax,[esi+RECT.left]
- sub eax,ebx
- shr edx,1
- shr ecx,1
- add ecx,[esi+RECT.top]
- sub ecx,edx
- ; Разместить окно по центру монитора
- invoke SetWindowPos,[hwnd],NULL,eax,ecx,NULL,NULL,\
- SWP_NOSIZE+SWP_NOZORDER
- .loc_ret:
- ; Восстановить все регистры
- popa
- ret
- endp
Читать статью целиком »
Просмотров: 1598 | Комментариев: 5

Магнитное окно с учетом нескольких мониторов
04.06.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
Продолжаем работу над ошибками. Несколько лет назад в одной из статей я рассказывал, как сделать окно, которое при перемещении будет прилипать ко краям экрана. Этот способ рабочий, но он не учитывает ситуацию, когда у пользователя более одного монитора. Дело в том, что функция SystemParametersInfo с параметром SPI_GETWORKAREA возвращает координаты рабочей области только основного монитора. Для поддержки нескольких мониторов, в том числе произвольных размеров, надо сперва определить, на каком мониторе находится окно. Затем надо будет получить характеристики этого монитора, точнее координаты его рабочей области. Но сперва придется определить структуру и константу, про которую не знает коробочный FASM.Code (Assembler) : Убрать нумерацию
- MONITOR_DEFAULTTONEAREST = 2
- struct MONITORINFO
- cbSize dd ?
- rcMonitor RECT
- rcWork RECT
- dwFlags dd ?
- ends
Читать статью целиком »
Просмотров: 1846 | Комментариев: 0

Обмен данными между процессами с помощью WM_COPYDATA
17.02.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

Обмен данными между процессами с помощью WM_COPYDATA
Обмен данными между процессами приложений может выполняться различными способами. Это может быть shared-память, буфер обмена, COM-объекты и другие высокоуровневые способы. Но наиболее простым и понятным способом является передача данных с использованием сообщения WM_COPYDATA. В этом случае обмен происходит через ядро системы с выделением памяти в принимающем процессе. Таким образом, например, выполняется взаимодействие с окном плеера JetAudio.
Читать статью целиком »
Просмотров: 2698 | Комментариев: 2

Моргание окна на Ассемблере
12.12.2017 | Категория: Образ мышления: Assembler | Автор: ManHunter
Наверняка вы не раз сталкивались с тем, что приложение, которое свернуто или работает в фоновом режиме, но хочет привлечь внимание пользователя, использует эффект моргания окна. Это может быть оповещение об окончании длительного процесса или просто информация для пользователя, с которой ему надо как можно быстрее ознакомиться. И действительно, такой способ работает. В этой статье я вам расскажу, как такой эффект реализуется.Самый простой способ моргнуть окном - использовать стандартную функцию FlashWindow. Для ее использования нужно только знать хэндл окна, которое должно моргнуть, вот и все. Это не обязательно должно быть окно именно вашего приложения, вы можете легко моргать любым окном, доступным в системе. Вызов простейший:
Code (Assembler) : Убрать нумерацию
- ; hwnd - хэндл окна, которое должно моргнуть
- invoke FlashWindow,[hwnd],FALSE
Если требуется иметь полный контроль над параметрами моргания, то надо использовать более продвинутую функцию FlashWindowEx. Но сперва придется самостоятельно описать используемые структуры и константы, так как FASM в стандартной комплектации их не знает.
Code (Assembler) : Убрать нумерацию
- ; Описание структуры для моргания окна
- struct FLASHWINFO
- cbSize dd ?
- hwnd dd ?
- dwFlags dd ?
- uCount dd ?
- dwTimeout dd ?
- ends
- ; Флаги режимов моргания окна
- FLASHW_CAPTION = 0x00000001
- FLASHW_TRAY = 0x00000002
- FLASHW_ALL = 0x00000003
- flash FLASHWINFO ; Структура для моргания окна
Code (Assembler) : Убрать нумерацию
- ; Заполнить структуру FLASHWINFO
- mov [flash.cbSize],sizeof.FLASHWINFO
- ; Хэндл окна, которое должно моргнуть
- mov ecx,[hwnd]
- mov [flash.hwnd],ecx
- ; Режим моргания - заголовок и кнопка окна в панели задач
- mov [flash.dwFlags],FLASHW_ALL
- ; Количество морганий, в моем примере 10 итераций
- mov [flash.uCount],10
- ; Частота морганий
- mov [flash.dwTimeout],80
- ; Вызвать функцию
- invoke FlashWindowEx,flash
Читать статью целиком »
Просмотров: 1418 | Комментариев: 0

Ассемблер: получаем имя файла оболочки
27.09.2017 | Категория: Образ мышления: Assembler | Автор: ManHunter
В этой статье я расскажу, как можно программно получить имя файла оболочки Windows. Зачем это нужно? Например, есть программа, которая инжектит свою библиотеку в работающую копию explorer.exe и при этом подразумевает, что такой процесс в системе гарантированно должен присутствовать. В подавляющем большинстве случаев действительно все работает, никаких нареканий нет. Но стоит запустить программу под альтернативным шеллом, например, Aston Desktop, и она неизбежно падает с ошибкой, потому что explorer.exe в системе вообще не запущен. Проверки на соответствие оболочки в программе нет, и вместо корректного информирования пользователя о причинах невозможности запуска мы получаем фатальное падение. И хорошо, если не вместе с системой.Чтобы найти процесс оболочки, сперва надо определить ее главное окно. В MSDN для этого рекомендуют воспользоваться следующим кодом:
Code (Assembler) : Убрать нумерацию
- ; Найти окно с классом "Progman"
- invoke FindWindow, szClass, NULL
- ...
- szClass db 'Progman',0
Читать статью целиком »
Просмотров: 2235 | Комментариев: 3
