怎样在屏幕上连续不断显示图形来催眠用户呢?仅用GetMessage()是办不到的。
如果消息队列中没有消息,GetMessage()就会等待,直到新的消息出现在队列中。
因为许多游戏是充满动作的,需要猛击键盘,产生场景变化,利用简单的GetMessage()
通常不能符合要求,游戏编程者不希望玩家在没有新的动作是游戏静止不动,他们希望
怪兽从后面冲出来,围攻玩家,追捕玩家。为了做到这样的效果,需要这样一种消息
循环:只有遇到需要处理的消息时才去处理消息,其余的时间都让游戏代码自动产生
激烈的场面。为了做到这一点需要用到PeekMessage()函数。
PeekMessage (From MSDN)
The PeekMessage function checks a thread message queue for a message and
places the message (if any) in the specified structure.
BOOL PeekMessage(
LPMSG lpMsg, // pointer to structure for message
HWND hWnd, // handle to window
UINT wMsgFilterMin, // first message
UINT wMsgFilterMax, // last message
UINT wRemoveMsg // removal flags
);
PeekMessage()函数和GetMessage()函数很相,惟一不同的是最后个参数: wRemoveMsg;
它的值可以是: PM_NOREMOVE--表示消息处理后仍留在消息队列中;
PM_REMOVE--表示消息处理后从队列中移去。 通常选择使用后者。
若队列中有消息,PeekMessage()将返回true;
若队列中无消息,PeekMessage()将返回false;
要创建实时消息的抽取循环,就需要更复杂一些. 若只是简单的把GetMessage()替换为
PeekMessage(), 则当队列中没有消息时,程序将会一闪而过. 因此实际的程序中需要
更强健的设计.
#include <time.h>
#include <windows.h>
char* g_szAppName = "Cute Bubble";
inline int RandInt(int x, int y) {return rand() % (y - x +1) +x; }
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
MSG Msg;
HWND hWnd;
WNDCLASS wc;
bool bFlag = false;
char* szClassName = "CPeekMessage";
wc.style = CS_HREDRAW|CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
if (!RegisterClass(&wc)) {
MessageBox(NULL, "register window class failed! ", g_szAppName, MB_OK|MB_ICONERROR);
return false;
}
hWnd = CreateWindow(
szClassName,
g_szAppName,
WS_OVERLAPPEDWINDOW,
0,0,
300, 300,
NULL,
NULL,
hInstance,
NULL);
if (!hWnd) {
MessageBox(NULL, "create window failed! ", g_szAppName, MB_OK|MB_ICONERROR);
return false;
}
ShowWindow(hWnd, nShowCmd);
UpdateWindow(hWnd);
while (!bFlag) {
while(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
if (Msg.message == WM_QUIT) {
bFlag = true;
}
else {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
// This will call WM_PAINT which well render our scene
InvalidateRect(hWnd, NULL, true);
UpdateWindow(hWnd);
Sleep(8);
}
return Msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
switch(Msg) {
case WM_CREATE:
srand((unsigned)time(NULL));
return false;
case WM_PAINT:
RECT rect;
POINT point;
HBRUSH RandBrush;
HBRUSH OldBrush;
PAINTSTRUCT ps;
int radius;
BeginPaint(hWnd, &ps);
// create a random brush
RandBrush = CreateSolidBrush(RGB(RandInt(0, 255), RandInt(0, 255), RandInt(0, 255)));
OldBrush = (HBRUSH)SelectObject(ps.hdc, RandBrush);
GetClientRect(hWnd, &rect);
point.x = rect.right;
point.y = rect.bottom;
point.x = RandInt(0, point.x);
point.y = RandInt(0, point.y);
radius = RandInt(0, 100);
Ellipse(ps.hdc, point.x-radius, point.y-radius, point.x+radius, point.y+radius);
SelectObject(ps.hdc, OldBrush);
EndPaint(hWnd, &ps);
return false;
case WM_DESTROY:
PostQuitMessage(0);
return false;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
} // WndProc