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

Установка точного размера клиентской области окна
19.06.2022 | Категория: Образ мышления: Assembler | Автор: ManHunter
Очередная тривиальная задача с нетривиальным решением и очередной пламенный привет разработчикам Windows. Начнем с задачи. Надо изменить размер окна таким образом, чтобы его клиентская область, то есть внутреннее содержимое без учета заголовка, рамок и полос прокрутки, стала четко заданной ширины и высоты. Создатели Windows, безусловно, позаботились о программистах, для решения этой задачи есть как минимум две функции - SetWindowPos и MoveWindow, все хорошо и замечательно, но... Как метко подметили в одном телесериале, все, что сказано до слова "но" - чушь собачья. Эти функции действительно выполняют свое предназначение, меняют размер окна, только применяют переданные им значения к внешней границе окна. При этом не учитываются ни визуальные темы, ни стили окна, ни наличие полос прокрутки, ни толщина рамки, короче, решения поставленной задачи "в лоб" дадут гарантированно неправильный результат.
Размеры областей окна
К счастью, в Windows имеется вспомогательная функция AdjustWindowRectEx, которая используется как раз для подобных ситуаций. Он вычисляет фактические размеры окна, которые соответствуют заданным размерам его клиентской области. И вот здесь как раз учитываются стили, в том числе и расширенные, наличие у окна строки меню и установленная визуальная тема, но... Да-да, очередное "но". При расчете размеров никак не учитывается наличие в окне полос вертикальной и/или горизонтальной прокрутки. Они могут входить в размер клиентской области, а могут и не входить, в зависимости от задачи.
Читать статью целиком »
Просмотров: 508 | Комментариев: 2

Как сделать ProgressBar с надписью
21.04.2022 | Категория: Образ мышления: Assembler | Автор: ManHunter
Не перестаю удивляться, почему разработчики Microsoft с самого начала не реализовали "из коробки" очевиднейшие решения. Например, есть хороший и удобный элемент диалоговых окон - Progress Bar. Легко реализовать, удобно управлять, но по какой-то причине нет никаких инструментов, чтобы системными средствами наложить на индикатор прогресса какую-нибудь надпись типа "42% завершено". Градиентный ProgressBar мы уже делали, настала очередь реализовать ProgressBar с надписью.
ProgressBar с надписью
Использовать стандартный элемент msctls_progress32 не будем, вместо него возьмем элемент EDIT или STATIC, как и в предыдущем примере. Полоса индикатора и надпись реализуется путем рисования прямо на канве элемента диалогового окна, которое выделено под индикатор.
Основная загвоздка заключается в том, что при отрисовке текста поверх индикатора прогресса, надо учитывать разницу в цвете фона и полосы выполненной части. Посмотрите на скриншоте, чтобы стало понятно, о чем идет речь. В некоторых случаях при определенной комбинации цветов можно использовать единый цвет, но это не самое хорошее решение. Так что сделаем все правильно.
Читать статью целиком »
Просмотров: 679 | Комментариев: 1

Обработка Drag'n'Drop в разные поля ввода
28.03.2022 | Категория: Образ мышления: Assembler | Автор: ManHunter
В статье об обработке перетаскивания файлов я упомянул про раздельную обработку перетаскивания файлов в разные поля. В частности про вариант с субклассированием. Теперь расскажу, как это делается. Предположим, что у нас на форме есть три поля для выбора файла, причем каждое должно работать независимо.Code (Assembler) : Убрать нумерацию
- ; Разрешить каждому полю принимать файлы
- invoke GetDlgItem,[hwnddlg],ID_FILE1
- mov ebx,eax
- invoke DragAcceptFiles,ebx,TRUE
- ; Установить наш собственный обработчик
- invoke SetWindowLong,ebx,GWL_WNDPROC,EditWindowProc
- ; Сохранить хэндл предыдущего обработчика
- invoke SetWindowLong,ebx,GWL_USERDATA,eax
- invoke GetDlgItem,[hwnddlg],ID_FILE2
- mov ebx,eax
- invoke DragAcceptFiles,ebx,TRUE
- ; Установить наш собственный обработчик
- invoke SetWindowLong,ebx,GWL_WNDPROC,EditWindowProc
- ; Сохранить хэндл предыдущего обработчика
- invoke SetWindowLong,ebx,GWL_USERDATA,eax
- invoke GetDlgItem,[hwnddlg],ID_FILE3
- mov ebx,eax
- invoke DragAcceptFiles,ebx,TRUE
- ; Установить наш собственный обработчик
- invoke SetWindowLong,ebx,GWL_WNDPROC,EditWindowProc
- ; Сохранить хэндл предыдущего обработчика
- invoke SetWindowLong,ebx,GWL_USERDATA,eax
Читать статью целиком »
Просмотров: 409 | Комментариев: 3

MessageBox с чекбоксом "Больше не показывать"
04.10.2021 | Категория: Образ мышления: Assembler | Автор: ManHunter
Еще одна хорошая практика взаимодействия с пользователем - окно сообщения с чекбоксом "Больше не показывать это диалоговое окно". Таким образом и приложение выполняет свою работу по уведомлению пользователя о каком-то периодическом событии, и пользователь сам решает, желает ли он наблюдать это уведомление в дальнейшем. Делается это при помощи стандартной функции SHMessageBoxCheck. По параметрам эта функция очень похожа на вызов MessageBox, но поддерживает ограниченное количество стилей и не весь набор кнопок, а также обязательно требует текстовую строку с уникальным идентификатором этого сообщения. В остальном все сводится к единственному вызову, типа такого:Code (Assembler) : Убрать нумерацию
- ; Уникальный идентификатор окна сообщения
- szUID db '{D9108BA3-9A61-4398-BFBC-B02102C77E8A}',0
- ...
- ; Значение по умолчанию
- DEFAULT_RESULT = 0
- ; Вывести окно сообщения с галочкой "Больше не показывать"
- invoke SHMessageBoxCheck,HWND_DESKTOP,\
- szMess,szTitle,MB_YESNO+MB_ICONEXCLAMATION,\
- DEFAULT_RESULT,szUID
- ; EAX = выбранная кнопка или DEFAULT_RESULT
Читать статью целиком »
Просмотров: 784 | Комментариев: 6

Работа с кнопкой Help в заголовке окна
28.07.2021 | Категория: Образ мышления: Assembler | Автор: ManHunter
В самом начале развития Windows во многих приложениях очень часто встречалась кнопка "Help" в заголовке окна. Кликнув на нее и переместив курсор на нужный элемент, пользователь мог получить подсказку, например, какие данные надо вводить в конкретное текстовое поле или что получится, если нажать какую-нибудь кнопку. Сейчас UIX-дизайнеры прокачали свои навыки, кнопка справки стала уже не так популярна, по крайней мере я не встречал ее ни в одном современном приложении. Но может быть кому-нибудь будет интересно, как ей пользоваться и как правильно обрабатывать ее сообщения. Начнем с интерфейса. Чтобы в заголовке окна появилась кнопка справки, оно должно быть изначально создано с расширенным стилем WS_EX_CONTEXTHELP. Для динамического управления кнопкой справки можно воспользоваться способом, описанным в этой статье.Из программной части нам понадобится одна структура, которую почему-то не знает коробочный FASM. Хотя, блин, чему я удивляюсь...
Code (Assembler) : Убрать нумерацию
- struct HELPINFO
- cbSize dd ?
- iContextType dd ?
- iCtrlId dd ?
- hItemHandle dd ?
- dwContextId dd ?
- MousePos POINT
- ends
Code (Assembler) : Убрать нумерацию
- .wminitdialog:
- ; Назначить контекстный идентификатор справки элементу окна
- invoke GetDlgItem,[hwnddlg],ID_BUTTON_1
- invoke SetWindowContextHelpId,eax,777
Читать статью целиком »
Просмотров: 845 | Комментариев: 4
