#visual-c #animation
#visual-c #Анимация
Вопрос:
Итак, я попробовал некоторые очень простые анимационные материалы (если это вообще можно назвать анимацией) в Windows. Я перепутал параметры вывода текста (координаты для текста) без анимации. По сути, он печатал «привет» в нескольких разных местах один раз, и после этого казалось, что ничего не происходит. Проблема в том, что текст выводится на экран без удаления текста из предыдущего вызова InvalidateRect с экрана. Кроме того, когда вы добавляете некоторые простые значения увеличивающихся рядов (например, 1,2,3,4,5 и т.д.) в качестве параметров для вывода текста, такой проблемы нет.
#include <Windows.h>
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam);
struct point
{
double x;
double y;
double t;
};
point obj={30,30,1};
int WINAPI wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR cmdLine,int cmdShow)
{
WNDCLASSEX windowsClass={0};
windowsClass.hCursor=LoadCursor(NULL,IDC_ARROW);
windowsClass.cbSize=sizeof(WNDCLASSEX);
windowsClass.hInstance=hInstance;
windowsClass.lpfnWndProc=WndProc;
windowsClass.cbClsExtra=NULL;
windowsClass.style=CS_HREDRAW | CS_VREDRAW;
windowsClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
windowsClass.hbrBackground=(HBRUSH)GetStockObject(NULL_BRUSH);
windowsClass.lpszClassName="Devjeet's Window";
if(!RegisterClassExA(amp;windowsClass))
return -1;
HWND hWnd = CreateWindowExA(NULL,"Devjeet's Window","Animation V1 By Devjeet",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,400,400,NULL,NULL,hInstance,NULL);
if(!hWnd)
return -1;
ShowWindow(hWnd,cmdShow);
MSG msg={0};
while(msg.message!=WM_QUIT)
{
if(PeekMessage(amp;msg,0,0,0,PM_REMOVE))
{
TranslateMessage(amp;msg);
DispatchMessage(amp;msg);
}
}
return static_cast<int>(msg.wParam);
}
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hDC;
PAINTSTRUCT paintStruct;
switch(message)
{
case WM_PAINT:
hDC=BeginPaint(hWnd,amp;paintStruct);
TextOut(hDC,(int)(obj.x),(int)(obj.y),"Hello",sizeof("Hello"));
obj.y=(double)(30*obj.t (obj.t*obj.t*9.8/2));
obj.x=(double)(30*obj.t (obj.t*obj.t*9.8/2));
obj.t =.8;
EndPaint(hWnd,amp;paintStruct);
if(obj.y>100.0)
{
obj.x=30.0;
obj.y=30.0;
obj.t=1.0;
}
Sleep(800);
InvalidateRect(hWnd,NULL,TRUE);
break;
case WM_DESTROY:
PostQuitMessage(NULL);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
break;
}
return 0;
}
Комментарии:
1. мой вопрос в том, почему это происходит? что-то не так с уравнением или есть что-то о Windows, чего я не знаю?
2. @devjeetroy: какое отношение название вашего вопроса имеет к вашему вопросу?
3. @Mat Извините, ребята, это была ошибка. Это был заголовок вопроса, который я думал опубликовать ранее
Ответ №1:
Первое: никогда, никогда не вызывайте Sleep
из своего WM_PAINT hander. Вы заблокируете свой пользовательский интерфейс.
Рекомендуемый способ создания простой анимации в Windows — использовать SetTimer
и обрабатывать WM_TIMER
сообщение. Ваш WM_TIMER
обработчик определяет, где должен быть ваш спрайт, и вызывает InvalidateRect
. Вы можете либо сделать недействительным все окно, либо только старую и новую позиции перемещенного спрайта.
В ответ на InvalidateRect
Windows отправит вам WM_PAINT
сообщение, позволяющее перерисовать ваше окно.
Что касается того, почему он не стирает старую: вы указали NULL_BRUSH
в качестве фона окна, что означает, что обработчик по умолчанию WM_ERASEBKGND
(где Windows удалит содержимое вашего окна) ничего не делает. Вам либо нужно обработать WM_ERASEBKGND
самостоятельно (чтобы стереть окно, используя, например, — FillRect
), либо вам также нужно обработать эту часть в вашем WM_PAINT
обработчике.
О, и причина, по которой простое увеличение позиции работает, вероятно, заключается в том, что (если я правильно помню), TextOut
удалит фон ограничивающей рамки для данного текста. Поскольку это, вероятно, на пару пикселей больше текста, предыдущий текст будет удален, если он находится всего в одном пикселе.