peekmessage和wm_paint的关系msdn说:The PeekMessage function does not remove WM_PAINT messages from the queue. WM_PAINT messages remain in the queue until they are processed.
windows程序设计说,while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) ;
这行叙述从消息队列中删除WM_PAINT之外的所有消息。如果队列中有一个WM_PAINT消息,程序就会永远地陷在while循环中。)作者是否理解错了,为什么死循环? 如果是死循环。作者又提供了这样的一个例子:
while (TRUE)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
else
DrawRectangle (hwnd) ; //这里进行绘图操作
}
return msg.wParam ;}作者就不担心死循环???????? 他一方面说,会产生死循环,一方面她还用peekmessage我是在昏了
2.PM_REMOVE 对 wm_paint 不起作用,返回 0.
我觉得作者的意图:wm_paint由系统默认处理第二:利用 空闲时候绘图。当发现消息对垒中有wm_paint的时候,由 系统默认处理
它所说的死循环,猜测是 认为的去处理wm_paint,但是处理的时候,并没有用beginpaint等函数去掉wm_paint!
windows程序设计randrect.c 这个例子书上是 164页5.6.2节
while (TRUE)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
if (msg.message == WM_PAINT)
OutputDebugString("WM_PAINT: PeekMessage return TRUE");
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else if (msg.message == WM_PAINT)
OutputDebugString("WM_PAINT: PeekMessage return FALSE");
}可以用这段代码测试一下,有时会出现不断输出"WM_PAINT: PeekMessage return FALSE"的情况
而且也发现这段代码是比较占CPU的
while (TRUE)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
else
DrawRectangle (hwnd) ;
}
return msg.wParam ;
}
void DrawRectangle (HWND hwnd)
{
HBRUSHhBrush ;
HDC hdc ;
RECT rect ;
if (cxClient == 0 || cyClient == 0)
return ;
SetRect (&rect, rand () % cxClient, rand () % cyClient,
rand () % cxClient, rand () % cyClient) ;
hBrush = CreateSolidBrush (
RGB (rand () % 256, rand () % 256, rand () % 256)) ;
hdc = GetDC (hwnd) ;
FillRect (hdc, &rect, hBrush) ;
ReleaseDC (hwnd, hdc) ;
DeleteObject (hBrush) ;
}
什么叫重绘动作? 可否科普一下。我理解的重绘: 重新绘制,什么时候重新绘制, wm_paint等消息产生的时候绘制。何时产生,如:拖动,放大缩小,被遮盖!这些才是需要重绘。
其他不算,比如:在wm_close里 填充背景。 这是刻意的, 仅仅是调用画图的代码,不能叫重绘
息并没有被处理也没有被移除,然后不断循环++
作者提供的源码,其实是处理了,peekmessage并没有去除掉。但是由于defwindowproc 使无效区域成为有效,所以wm_paint就消失了
case WM_PAINT:
return 0;怎么又不见了? 你的while (TRUE) 是在WndProc还是哪个里面的?
/*----------------------------------------------------------------------
RANDRECT.C -- Displays Random Rectangles
(c) Charles Petzold, 1998
-----------------------------------------------------------------------*/
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>// for the rand function
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
void DrawRectangle (HWND) ;
int cxClient, cyClient ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("RandRect") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc= WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName= NULL ;
wndclass.lpszClassName= szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Random Rectangles"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (TRUE)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
else
DrawRectangle (hwnd) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
switch (iMsg)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ; //case wm_paitn是我添加的,我加的目的是,故意return 0; 这样的话,wm_paint就无法把无效区域变成有效区域,导致其一直在队列中,看
是否会堵塞?? case WM_PAINT: return 0;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
void DrawRectangle (HWND hwnd)
{
HBRUSH hBrush ;
HDC hdc ;
RECT rect ;
if (cxClient == 0 || cyClient == 0)
return ;
SetRect (&rect, rand () % cxClient, rand () % cyClient,
rand () % cxClient, rand () % cyClient) ;
hBrush = CreateSolidBrush (
RGB (rand () % 256, rand () % 256, rand () % 256)) ;
hdc = GetDC (hwnd) ;
FillRect (hdc, &rect, hBrush) ;
ReleaseDC (hwnd, hdc) ;
DeleteObject (hBrush) ;
}
注意wm_paint!!!,是我加的, 作者的源码是没有的
MSDN说的null update region是指无效区域吧,那么PeekMessage就会移除WM_PAINT,并返回TRUE了;如果一直是无效区域,那么PeekMessage总是返回TRUE另外可能是PeekMessage不等待的缘故,CPU占用率还是比较高的
贴完整的:The PeekMessage function normally does not remove WM_PAINT messages from the queue. WM_PAINT messages remain in the queue until they are processed. However, if a WM_PAINT message has a NULL update region, PeekMessage does remove it from the queue.作者对wm_paitn的理解,早就有人指出有错误了,一个国外的网站上。根本不会死循环。msdn是这样解释的:The PeekMessage function normally does not remove WM_PAINT messages from the queue. WM_PAINT messages remain in the queue until they are processed. However, if a WM_PAINT message has a NULL update region, PeekMessage does remove it from the queue.一般不会删除,直到 XX来处理。 XX可以使程序员,也可以是os. 如何处理,没规定。那么指定了pm_remove,会不会一定删除,应该是不会的。一旦删除,是进入不了case wm_paint的.那么wm_paint是如何产生的,是有非null update region才产生, 否则不产生。这里msdn是有不少疑问。总之:不存在所谓死循环, windows程序设计这本书wm_paitn 的理解不对, 早就有人指出了
我好像说错了,wm_paint如果处理不正确(无效区域一直存在,无论getmessage,peekmesssage都不会去掉一直存在的该帖子讨论的是与peekmessage的关系, windows程序一书多虑了自己可以设置断点,