windows消息处理机制
一、win32 api下消息处理机制与画图例子:
//画图函数,winmain中循环调用此函数来画图。
int DrawGLScene(GLvoid);
//消息处理函数,处理所有窗口消息
LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
{
switch(uMsg)
{
case WM_ACTIVATE: //窗口激活状态
{
if (!HIWORD(wParam)) //最小化
active=TRUE; //程序运行
break;
}
//从窗口系统菜单上发送该消息
case WM_SYSCOMMAND:
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
}
case WM_CLOSE:
case WM_KEYDOWN:
keys[wParam] = TRUE;
break;
case WM_KEYUP:
keys[wParam] = FALSE;
break;
case WM_SIZE:
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LOWord=Width, HIWord=Height
break;
}
//缺省消息处理函数
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg; // Windows Message Structure
BOOL done=FALSE;//是否继续画图标志
while(!done)
{
//使用PeekMessage()可以在不锁住我们的程序的前提下对消息进行检查。
//使用GetMessage()程序在收到paint消息等窗口消息之前不会做任何事。
//即:函数PeekMesssge在返回前不等待消息被放到队列里。
//hWnd为NULL,PeekMessage接收属于当前调用线程的窗口的消息。
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
done=TRUE;
else
{
//将虚拟键消息转换为字符消息。
//字符消息被送到调用线程的消息队列中,
//在下一次线程调用函数GetMessage或PeekMessage时被读出。
TranslateMessage(&msg);
//传递给窗口消息处理函数wndproc。
DispatchMessage(&msg);
}
}
else //如果没有消息,就画图
{
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) //Updating View Only If Active
done=TRUE; // ESC or DrawGLScene Signalled A Quit
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
if (keys[VK_ADD] );
if (keys[VK_SUBTRACT]) ;
if (keys[VK_PRIOR]);
if (keys[VK_NEXT]);
if (keys[VK_RETURN]) ;
if (!keys[VK_RETURN]) ;
if ((keys[' '] ) ;
if (keys[VK_UP]);
if (keys[VK_DOWN]);
if (keys[VK_RIGHT]);
if (keys[VK_LEFT]);
if (keys[VK_F1]);
}
}//else
}//while
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
二、MFC下消息处理机制与画图:
1、Invalidate和UpdateWindow的区别。Invalidate在消息队列中加入一条WM_PAINT消息,其无效区为整个客户区。而UpdateWindow直接发送一个WM_PAINT消息,其无效区范围就是消息队列中WM_PAINT消息(最多只有一条)的无效区。效果很明显,调用Invalidate之后,屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头部,而调用UpdateWindow会使WM_PAINT消息马上执行的,绕过了消息队列。如果你调用Invalidate之后想马上更新屏幕,那就加上UpdateWindow()这条语句。
2、MFC下画动画,我现在采用的是不在OnPaint()或OnDraw()写语句,而是设定定时器SetTimer(),在OnTimer()中完成画图函数的调用,仅从简单的例子来看,效果还算可以。(2009年12月22日)