C++ 无限循环使程序停止工作
所以我正在创建一个程序,其中有5个矩形,它们朝着不同的方向移动,就像DVD屏幕保护程序一样 问题是当我开始在无限循环中移动它们时,程序停止工作,不允许进行任何输入。如果我使循环不是无限的,它将停止工作,直到循环结束,然后程序允许你做一些事情 我想问题在于我试图移动矩形的方式,但我不确定C++ 无限循环使程序停止工作,c++,winapi,C++,Winapi,所以我正在创建一个程序,其中有5个矩形,它们朝着不同的方向移动,就像DVD屏幕保护程序一样 问题是当我开始在无限循环中移动它们时,程序停止工作,不允许进行任何输入。如果我使循环不是无限的,它将停止工作,直到循环结束,然后程序允许你做一些事情 我想问题在于我试图移动矩形的方式,但我不确定 void MovePredator(HDC hdc, PAINTSTRUCT ps,int size, int amount) { for (;;) {
void MovePredator(HDC hdc, PAINTSTRUCT ps,int size, int amount)
{
for (;;)
{
FillRect(hdc, &ps.rcPaint, (HBRUSH)(1));
for (int i = 0; i < amount; ++i)
{
int Offset = size / 2;
if (Predator[i].LocationX - Offset == 0 || Predator[i].LocationX + Offset == 1420)
{
Predator[i].MoveX *= -1;
}
if (Predator[i].LocationY - Offset == 0 || Predator[i].LocationY + Offset == 700)
{
Predator[i].MoveY *= -1;
}
Predator[i].LocationX += Predator[i].MoveX;
Predator[i].LocationY += Predator[i].MoveY;
Rectangle(hdc, Predator[i].LocationX - Offset, Predator[i].LocationY - Offset, Predator[i].LocationX + Offset, Predator[i].LocationY + Offset);
}
Sleep(10);
}
}
void SpawnPredator(HDC hdc, int size, int amount)
{
int Offset = size / 2;
for (int i = 0; i < amount; ++i)
{
Predator[i].LocationX = rand() % 1300 + 50;
Predator[i].LocationY = rand() % 600 + 50;
Predator[i].MoveX = rand()%2;
Predator[i].MoveY = rand()%2;
if (Predator[i].MoveX == 0) Predator[i].MoveX = -1;
if (Predator[i].MoveY == 0) Predator[i].MoveY = -1;
Rectangle(hdc, Predator[i].LocationX - Offset, Predator[i].LocationY - Offset, Predator[i].LocationX + Offset, Predator[i].LocationY + Offset);
}
}
此应用程序挂起的原因是Windows应用程序基于事件的设计的本质 在后台,任何windows应用程序都不允许直接访问任何硬件,这与操作系统不同,操作系统一次只能运行一个程序,例如DOS。这是在多个程序之间共享视频卡或鼠标等硬件所必需的。Windows内核不直接访问硬件,而是在运行向内核发送特殊请求的应用程序(系统调用)时操纵硬件本身,Win API实际上是一组可用于向内核发送此类请求的函数 当您的应用程序创建或绘制窗口时,它实际上要求操作系统内核执行此操作。内核选择何时以及如何处理此操作,然后使用视频卡设备驱动程序绘制(通过硬件抽象层或特殊的fast API,如OpenGL或Direct X等) 另一件事——应用程序如何知道用户是否使用鼠标或键盘进行输入。Windows将这些输入存储在称为事件的特殊内部结构队列中,每个应用程序线程都有这样一个队列。 应用程序本身应该有一个等待操作系统事件并对其作出反应的循环—这种循环称为运行循环,通常如下所示:
MSG messages; // Here messages to the application are saved
// Run the message loop. It will run until GetMessage() returns 0
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
如果您使用的是像MFC这样的库,则该循环由库提供,但它仍然存在。
创建窗口后,您或您的库–注册一个WindowProcedure
回调函数,该函数对运行循环发送到窗口对象(如WM_PAINT)的消息作出反应。当您的程序不需要处理某些特定事件时,此类函数通常调用DefWindowProc
函数
WM_PAINT
在最大化、最小化、恢复或显示隐藏窗口时发生,或者您可以使用SendMessage功能将此消息发送给自己的窗口。
如果在处理消息期间执行无限循环,或阻止执行运行循环的线程,则会冻结运行循环,并且在需要调用DefWindowProc或其他自定义消息处理时不会调用它们,应用程序将挂起
演示如何制作要实现的动画。此应用程序挂起的原因是基于Windows应用程序事件的设计 在后台,任何windows应用程序都不允许直接访问任何硬件,这与操作系统不同,操作系统一次只能运行一个程序,例如DOS。这是在多个程序之间共享视频卡或鼠标等硬件所必需的。Windows内核不直接访问硬件,而是在运行向内核发送特殊请求的应用程序(系统调用)时操纵硬件本身,Win API实际上是一组可用于向内核发送此类请求的函数 当您的应用程序创建或绘制窗口时,它实际上要求操作系统内核执行此操作。内核选择何时以及如何处理此操作,然后使用视频卡设备驱动程序绘制(通过硬件抽象层或特殊的fast API,如OpenGL或Direct X等) 另一件事——应用程序如何知道用户是否使用鼠标或键盘进行输入。Windows将这些输入存储在称为事件的特殊内部结构队列中,每个应用程序线程都有这样一个队列。 应用程序本身应该有一个等待操作系统事件并对其作出反应的循环—这种循环称为运行循环,通常如下所示:
MSG messages; // Here messages to the application are saved
// Run the message loop. It will run until GetMessage() returns 0
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
如果您使用的是像MFC这样的库,则该循环由库提供,但它仍然存在。
创建窗口后,您或您的库–注册一个WindowProcedure
回调函数,该函数对运行循环发送到窗口对象(如WM_PAINT)的消息作出反应。当您的程序不需要处理某些特定事件时,此类函数通常调用DefWindowProc
函数
WM_PAINT
在最大化、最小化、恢复或显示隐藏窗口时发生,或者您可以使用SendMessage功能将此消息发送给自己的窗口。
如果在处理消息期间执行无限循环,或阻止执行运行循环的线程,则会冻结运行循环,并且在需要调用DefWindowProc或其他自定义消息处理时不会调用它们,应用程序将挂起
演示如何制作要实现的动画。不要在UI消息处理程序中执行无限循环。这是你的应用程序无法运行的主要原因。您不允许应用程序对来自操作系统的消息保持响应 此外,请勿在绘制处理程序内执行非绘制逻辑。更新捕食者根本不属于你的
WM_PAINT
事件。改为使用计时器,并使其在发生更改时使窗口失效以触发重新绘制。只要在你被要求粉刷窗户的时候,按原样粉刷现有的捕食者就可以了
另外,您的WndProc()
缺少对所有未处理消息的DefWindowProc()
调用
尝试类似以下内容:
void MovePredator(int size, int amount)
{
int Offset = size / 2;
for (int i = 0; i < amount; ++i)
{
if (Predator[i].LocationX - Offset == 0 || Predator[i].LocationX + Offset == 1420)
{
Predator[i].MoveX *= -1;
}
if (Predator[i].LocationY - Offset == 0 || Predator[i].LocationY + Offset == 700)
{
Predator[i].MoveY *= -1;
}
Predator[i].LocationX += Predator[i].MoveX;
Predator[i].LocationY += Predator[i].MoveY;
}
}
void SpawnPredator(int amount)
{
for (int i = 0; i < amount; ++i)
{
Predator[i].LocationX = rand() % 1300 + 50;
Predator[i].LocationY = rand() % 600 + 50;
Predator[i].MoveX = rand() % 2;
Predator[i].MoveY = rand() % 2;
if (Predator[i].MoveX == 0)
Predator[i].MoveX = -1;
if (Predator[i].MoveY == 0)
Predator[i].MoveY = -1;
}
}
void PaintPredator(HDC hdc, int size, int amount)
{
int Offset = size / 2;
for (int i = 0; i < amount; ++i)
{
Rectangle(hdc, Predator[i].LocationX - Offset, Predator[i].LocationY - Offset, Predator[i].LocationX + Offset, Predator[i].LocationY + Offset);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
srand(time(NULL));
SetTimer(hWnd, 1, 10, NULL);
return 0;
case WM_TIMER:
SpawnPredator(5);
MovePredator(50, 5);
InvalidateRect(hWnd, NULL);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(1));
PaintPredator(hdc, 50, 5);
EndPaint(hWnd, &ps);
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
void MovePredator(整数大小,整数金额)
{
int Offset=大小/2;
对于(int i=0;i#define STEP 1
int idtimer = -1;
struct Mob
{
int LocationX = 0;
int LocationY = 0;
int MoveX = 0;
int MoveY = 0;
};
struct Mob Predator[100];
void SpawnPredator(int amount)
{
for (int i = 0; i < amount; ++i)
{
Predator[i].LocationX = rand() % 1300 + 50;
Predator[i].LocationY = rand() % 600 + 50;
Predator[i].MoveX = rand() % 2;
Predator[i].MoveY = rand() % 2;
if (Predator[i].MoveX == 0) Predator[i].MoveX = -STEP;
else Predator[i].MoveX = STEP;
if (Predator[i].MoveY == 0) Predator[i].MoveY = -STEP;
else Predator[i].MoveY = STEP;
}
}
void MovePredator(int size, int amount)
{
for (int i = 0; i < amount; ++i)
{
int Offset = size / 2;
if (Predator[i].LocationX - Offset <= 0 || Predator[i].LocationX + Offset >= 1420)
{
Predator[i].MoveX *= -1;
}
if (Predator[i].LocationY - Offset <= 0 || Predator[i].LocationY + Offset >= 700)
{
Predator[i].MoveY *= -1;
}
Predator[i].LocationX += Predator[i].MoveX;
Predator[i].LocationY += Predator[i].MoveY;
}
}
void PaintPredator(HDC hdc, int size, int amount)
{
for (int i = 0; i < amount; ++i)
{
int Offset = size / 2;
Rectangle(hdc, Predator[i].LocationX - Offset, Predator[i].LocationY - Offset, Predator[i].LocationX + Offset, Predator[i].LocationY + Offset);
}
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
srand(time(NULL));
switch (message)
{
case WM_CREATE:
{
SpawnPredator(5);
SetTimer(hWnd, idtimer = 1, 10, NULL);
}
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Разобрать выбор в меню:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_TIMER:
{
MovePredator(50, 5);
InvalidateRect(hWnd, NULL, FALSE);
break;
}
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(4));
PaintPredator(hdc, 50, 5);
//Rectangle(hdc, 0, 10, 20, 30);
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}