
Быстрый поиск
Введите фрагмент названия статьи для поиска
Особенности работы с контролом SysMonthCal32
07.09.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

Различная ширина SysMonthCal32 в разных локалях
При разработке одной из своих программ я столкнулся с интересной ситуацией. Никаких ракетных технологий, просто в диалоговом окне выводится стандартный виджет календарика через контрол SysMonthCal32. Я работаю в русской версии Windows и наивно предположил, что размеры виджета календарика всегда должны как-то вписываться в те границы, которые я ему определил. Но, как вы можете видеть на этих скриншотах, ширина контрола с календариком заметно отличается в зависимости от установленной в системе локали, на что мне указал один из пользователей (Mufasa, спасибо!). Вариантов нет, пришлось изучить этот вопрос.
Читать статью целиком »
Просмотров: 1832 | Комментариев: 2
Перетаскивание окна за любое место правой кнопкой мыши
24.07.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter
В одной из первых статей на этом блоге я рассказывал, как легко сделать перетаскивание окна за любое место левой кнопкой мыши. А тут что-то мне захотелось странного, а именно реализовать перетаскивание окна точно так же за любое место, но только правой кнопкой мыши. Как оказалось, простым пробросом сообщения от мышки на заголовок окна сделать это нельзя. После некоторых раздумий у меня получился вот такой вариант. При клике мышкой по окну оно захватывает события мыши при помощи функции SetCapture и сохраняет начальные координаты окна, при перемещении курсора принудительно перемещает окно вслед за ним, а при отпускании кнопки мышки освобождает перехват событий мыши функцией ReleaseCapture. Начнем с обработчика сообщений окна.Code (Assembler) : Убрать нумерацию
- ; Установка обработчика перетаскивания правой кнопкой
- ; мыши и колесиком
- cmp [msg],WM_RBUTTONDOWN
- je .drag_window_set
- cmp [msg],WM_MBUTTONDOWN
- je .drag_window_set
- ; Снятие обработчика перетаскивания правой кнопкой
- ; мыши и колесиком
- cmp [msg],WM_RBUTTONUP
- je .drag_window_release
- cmp [msg],WM_MBUTTONUP
- je .drag_window_release
- ; Обработчик перемещения мыши
- cmp [msg],WM_MOUSEMOVE
- je .drag_window_ex
Читать статью целиком »
Просмотров: 2099 | Комментариев: 0
Установка окна по центру с учетом нескольких мониторов
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
Читать статью целиком »
Просмотров: 2024 | Комментариев: 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
Читать статью целиком »
Просмотров: 2242 | Комментариев: 0
Обмен данными между процессами с помощью WM_COPYDATA
17.02.2018 | Категория: Образ мышления: Assembler | Автор: ManHunter

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


