|
0 / 0 / 0
Регистрация: 10.07.2015
Сообщений: 16
|
|||||||||||
Странное поведение (анимация)25.03.2018, 21:14. Показов 1644. Ответов 3
Метки нет (Все метки)
Здравствуйте, задача простая и я ее когда то решал успешно. Вывести эллипс, двигающийся по экрану (анимация) с помощью WinAPI.
Есть код, кривой, но рабочий. Я решил переделать его. Первым делом, я хочу рисовать не сразу в hdc, а в памяти (использовать контекст памяти для ускорения рисования), а потом при наступлении WM_PAINT из памяти копировать на экран. Второе: убрать весь код рисования по максимому из обработчика WM_PAINT. Сейчас приведу фрагменты 2 кодов, А потом будут вопросы. Вот код кривой, но худо бедно работающий, хотя непонятно как (код в спойлере): Кликните здесь для просмотра всего текста
Теперь новый код, в котором убрал лишнее из WM_PAINT и рисую в памяти: Кликните здесь для просмотра всего текста
Теперь вопросы: 1. Если убрать из WM_TIMER старого кода команду Ellipse, то он все равно будет рисовать. Почему? 2. Если убрать из WM_PAINT старого кода Ellipse, но оставить Ellipse в WM_TIMER, то рисоваться ничего не будет вообще. Почему? По идее он должен рисоваться в памяти, а потом обновляться с помощью InvalidateRect. При наступлении WM_PAINT там стоит функция BitBlt, которая должна из памяти перекидывать на экран, но ничего не происходит. 3. и главное: в новом коде не могу добиться, чтобы эллипс рисовался без шлейфа. При каждом WM_TIMER, я пересчитываю координаты и делаю InvalidateRect с последним параметром что TRUE, что FALSE - программа все равно не стирает старые положения эллипса, получается некрасивый шлейф. Ожидалось, что при установке TRUE он будет стирать прошлый эллипс и рисовать эллипс в новом положении, то есть анимация. Раньше не думая использовал InvalidateRect и анимация работала без казусов. Объясните, пожалуйста, чего я не понимаю?
0
|
|||||||||||
| 25.03.2018, 21:14 | |
|
Ответы с готовыми решениями:
3
Странное поведение
Странное поведение именованного канала |
|
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
|
||||||||||||
| 26.03.2018, 00:13 | ||||||||||||
Сообщение было отмечено Fireball как решение
Решение Есть такой способ, рисуем эллипс в режиме xor ( xor, "exclusive or", "исключающее или", сложение по модулю 2). Y =A+X mod 2. Если еще раз прибавить X, получим начальное значение. Y+X = A + X + X = A (mod 2 ). Что будет, если два раза нарисовать эллипс в том же самом положении в режиме xor? A - произвольный разряд какой-то точки исходного изображения на экране, X - разряд (бит) изображения эллипса. A+X (mod 2) - после того, как первый раз нарисовали эллипс в режиме xor A+X+X = A (mod 2) - второй раз нарисовали Результат: получилось исходное значение A.
1
|
||||||||||||
|
0 / 0 / 0
Регистрация: 10.07.2015
Сообщений: 16
|
|||
| 26.03.2018, 00:24 [ТС] | |||
|
0
|
|||
|
0 / 0 / 0
Регистрация: 10.07.2015
Сообщений: 16
|
||||||
| 27.03.2018, 18:06 [ТС] | ||||||
|
Ну раз никто не ответил на остальные вопросы, то сам отвечу. Разобрался. Честно скажу, что пришлось перелопатить много информации. В официальной MSDN очень мутно написано и во многих ссылках в интернете просто перепечатка из MSDN.
Прочитав официальную документацию, я думал, что эта функция стирает с экрана перед обновлением в зависимости от последнего параметра. Оказалось хитрее. Алгоритм кратко такой: 1. помечает область, как требующую перерисовки (Сама не перерисовывает ничего, только помечает!), 2. посылает сообщение WM_PAINT, перед BeginPaint (или в нем) внутри WM_PAINT сначала стирает, если написано TRUE. Причем стирает до фона окна. 3. А потом выполняет код, написанный в WM_PAINT. Но что такое фон окна? Казалось бы я в WM_CREATE указал залить все окно синим. Эту инфу пришлось покопать. Но это не считается фоном окна. Фоном окна считается
Но, если рисуешь в памяти и потом делаешь BitBlt в WM_PAINT, то после стирания эллипса на экране он снова появляется в добавок к новому из памяти. В памяти то InvalidateRect не стирает (я об этом не задумывался)! Я прочитав MSDN и подумал, что она стирает фон, то есть мой эллипс. Как только я понял, что он отображает первоначальный фон окна, заданный в классе окна, я понял, что это практически бесполезная функция с TRUE: 1. вызывает мерцание при перерисовке, 2. зачем вообще отображать фон окна снова, если можно перекрашивать кистью, созданной для раскраски фона, делая Rectangle(). Тем более он показывает его на доли секунды(то есть как бы стирает), а потом (внимание!) снова отображает, то что там было! то есть стирать лучше, казалось бы, просто делая Rectangle на все окно цветом фона (в моем случае белым). Но если рисуешь сразу на экране в hdc без буфера memdc, то InvalidateRect с параметром TRUE становится полезным. Нарисовал эллипс, потом послал InvalidateRect с TRUE (только не из WM_PAINT, иначе будет цикл), он стер эллипс, а потом сработал TIMER, который пересчитал положение и снова послал Invalidate с TRUE и так далее. Создается иллюзия движения. Но врядли хорошо часто без memdc использовать. Назначение. То есть я использовал функцию не по назначению. Основное назначение - сообщить системе, что надо бы после рисования обновить окно. А я использовал еще и для стирания. Как было отмечено выше стирать лучше, рисуя белый эллипс на белом фоне заместо прошлого. Ответы на мои вопросы. На номер 3 уже ответили. 1. Если убрать Ellipse в WM_TIMER старого кода, то программа все равно рисует эллипс, так как там стоит InvalidateRect с TRUE, который стирает предыдущий эллипс и вызывает код WM_PAINT, который рисует уже на экране на прямую без BitBlt. А потом расчет новых координат идет в WM_TIMER, и вызов снова InvalidateRect, который стирает старый эллипс и отображает на экране новый в hdc. Код плохой, так как задумка была рисовать в памяти и при WM_PAINT отображать память на экран и все (это видно по коду в WM_TIMER). Но тут действительно InvalidateRect стирает экран без способа, который предложил Alex5. Я поэтому и думал раньше, что Invalidate для удобного стирания и движения хорошо годится. 2. Если убрать из WM_PAINT старого кода Ellipse, но оставить Ellipse в WM_TIMER, то рисоваться ничего не будет вообще. Потому, что WM_PAINT рисовал на экране в hdc, а BitBlt там нет. А в WM_TIMER рисование только в memdc, а потом Invalidate, который стирает только на экране, а не в памяти, как я думал сначала. То есть в памяти остается прошлый эллипс нестертым и новый, который я нарисовал, а потом обновляем, но WM_PAINT ничего не рисует. Все нарисовано со шлейфом, но в памяти. Для себя решил, что буду рисовать по возможности методом, предложенным Alex5. Но если надо на экране напрямую, то можно и с помощью InvalidateRect с TRUE. Ссылки: P.S. Уже сегодня, когда разобрался в этом нашел еще одно полезное сообщение из соседней темы. вопрос об отличии InvalidateRect FALSE и TRUE, который я вначале тоже неправильно понял из документации MSDN MSDN описание функции InvalidateRect что такое фон окна на самом деле и тут полезная тема по InvalidateRect Всем спасибо! Вопрос решен и понят
0
|
||||||
| 27.03.2018, 18:06 | |
|
Помогаю со студенческими работами здесь
4
Странное поведение функции с переменным количеством аргументов
Странное поведение окна при нажатии VK_ALT Странное поведение указателя Странное поведение bool Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Налог на собак: https:/ / **********/ gallery/ V06K53e
Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf
Пост отсюда. . .
|
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop?
Ниже её машинный перевод.
После долгих разбирательств я наконец-то вернула себе. . .
|
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод
Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод.
Thinkpad X220 Tablet —. . .
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|