请问为什么下面的程序会出现一些区域 没有重绘 的现象(灰色的区域)?重现步骤:
运行下面程序, 最大化
运行另外一个程序,比如计算器, 移动计算器窗口 
就会出现 灰色区域 (最好快速拖动计算器窗口,比较容易重现)
// vcwin32.cpp : Defines the entry point for the application.
//#include "stdafx.h"
#include "vcwin32.h"//---------------------------------------------------------------------------
#include <windows.h>
#include <winuser.h>
#include <commctrl.h>
#include <tchar.h>#include <assert.h>HINSTANCE ghInstance;// Global Instance// Prototyp WindowFunction
LRESULT CALLBACK WndProcedure (HWND hwnd, UINT msg,WPARAM w, LPARAM l);
//****************************************************************************************HWND mainWin;int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR /*lpCmdLine*/, int nCmdShow)
{
//InitCommonControls();
static TCHAR szAppName[]= __TEXT("Test_WmPaint");
static TCHAR szTitleBar[]= __TEXT("Title Bar"); WNDCLASSEX    wndclass;
MSG         msg; // Register Class
ghInstance = hInstance; wndclass.cbSize  = sizeof(WNDCLASSEX);
wndclass.style        = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
wndclass.lpfnWndProc  = WndProcedure;
wndclass.cbClsExtra   = 0;
wndclass.cbWndExtra   = 0;
wndclass.hInstance    = hInstance;
wndclass.hIcon        = NULL;//LoadIcon (ghInstance, IDI_APPLICATION);
wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW); //wndclass.hbrBackground = Null;
//wndclass.hbrBackground = CreateSolidBrush(RGB(200,0,0));
wndclass.hbrBackground = (HBRUSH)(COLOR_GRAYTEXT+1);//GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm  = NULL;//LoadIcon(NULL, IDI_APPLICATION); if (!RegisterClassEx (&wndclass)) {
MessageBox(NULL, __TEXT("Window Registration Failed!"), __TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
return -1;
} // Create Window and show Window
mainWin = CreateWindow (szAppName,
szTitleBar,
WS_OVERLAPPEDWINDOW, //WS_POPUP, //!WS_CAPTION ,
200,                   // x position for this window
200,                   // y position for this window
300,                 // window width
300,                 // window height
NULL,                // parent
NULL,                // menu
hInstance,
NULL);               // user data if (mainWin == NULL) {
MessageBox(NULL, __TEXT("Window Creation Failed!"), __TEXT("Error!"),MB_ICONEXCLAMATION | MB_OK);
return 0;
} ShowWindow   (mainWin, nCmdShow);
UpdateWindow (mainWin); // Dispatch Message or exit program
while (GetMessage (&msg, NULL, 0, 0)) {
//if(!IsDialogMessage(hwnd, &msg)){
TranslateMessage (&msg);
DispatchMessage  (&msg);
//}
}
return (msg.wParam);
}//**************************************************************************HBRUSH brushes[] = {
CreateSolidBrush(RGB(100,0,0)),
CreateSolidBrush(RGB(0,160,0)),
CreateSolidBrush(RGB(0,0,255)),
};LRESULT CALLBACK WndProcedure (HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
{
static int x=0;
assert(hWnd!=NULL);
int ret=0; HDC hdc=NULL;
//HPEN pen=NULL;
PAINTSTRUCT ps;
RECT rt;
SetRect(&rt,0,0,0,0); // init switch (wMsg) {
case WM_CREATE:
break;
case WM_LBUTTONDOWN:
return 0;
/*
hdc = GetDC(hWnd); GetClientRect(hWnd, &rt);
FillRect(hdc, &rt,  brushes[0]);
ReleaseDC(hWnd, hdc);
break;
*/ case WM_PAINT:{
x++; hdc = BeginPaint(hWnd, &ps);
rt = ps.rcPaint; SetRect(&rt, 0,0,2000,2000);
//use this line can easy see which region is painted.
ret=FillRect(hdc, &rt/*&ps.rcPaint*/, brushes[x%2]);
//ret=FillRect(hdc, &ps.rcPaint, brushes[0]);
if(ret==0) {
MessageBox(mainWin, __TEXT("fill rect Error "), __TEXT("Error"), MB_OK);
} //RedrawWindow(hWnd, &ps.rcPaint, NULL, RDW_NOERASE);
EndPaint(hWnd, &ps); //GdiFlush ();
return 0;
} case WM_ERASEBKGND:
hdc = (HDC)wParam; rt.left = 0 ; rt.top = 0;
rt.right = 300; rt.bottom = 300;
ret=FillRect(hdc, &rt, brushes[2] );
return 1; case WM_DESTROY:
PostQuitMessage (0);
return (0);
}
return DefWindowProc (hWnd, wMsg, wParam, lParam);
}

解决方案 »

  1.   

    1 背景填充没有包含所有客户区case WM_ERASEBKGND:
                hdc = (HDC)wParam;
                GetClientRect(hWnd, &rt);
                //rt.left = 0 ; rt.top = 0;
                //rt.right = 300; rt.bottom = 300;
                ret=FillRect(hdc, &rt, brushes[2] );
                return 1;
    2 WM_PAINT 中 BeginPaint 会自动裁剪刷新区域,因此导致不能刷新其它区域,
     可以在BeginPaint前 InvalidateRect(hWnd, NULL, TRUE) 这样就会全部刷新
     推荐使用双缓冲贴图的方法,还可以解决闪烁的问题
      

  2.   

    谢谢回复, 但即使是改成所示代码, 在俺的机器上, 移动其他窗口时还是会
    出现灰色的区域, 即 没有重绘俺还叫一个使用vista的朋友运行过, 但运行结果有点奇怪, 居然只会显示一种颜色,绿色
    非常确定当时运行的是这一句:
    ret=FillRect(hdc, &rt/*&ps.rcPaint*/, brushes[x%2]);
    结果应该时 红色 和 绿色 交替 的呀
    然道跟系统有关, 俺的系统是 xp, sp3
      

  3.   

    如果:
    需要在 BeginPaint() 前调用 InvalidateRect(hWnd,NULL, TRUE), 
    那样相当于重绘整个窗口 , 理论上应该只用重绘:
    PAINTSTRUCT.rcPaint 区域啊, 这还是最简化的窗口, 
    如果对每个窗口都 双缓冲, 重绘整个窗口 , 那样对性能会有影响啊
      

  4.   

    在vista和win7上运行是一种颜色,出不来你说的效果。
    默认的aero主题不会像你想的那样去重绘。
    win7下把界面主题改成Windows经典就可以测试你的程序了。
    我在win7下测试了一下,没有出现你说的没有重绘的问题。
      

  5.   


    谢谢回复! 原来真的是跟 外观 设置有关啊,在 xp 上面,
    如果使用 经典window 外观, 就会出现 没有 重绘的区域 
    如果使用 xp 样式 外观 , 就不会出现 没有 重绘的区域 ,显示的 是 交替的 红色 或 绿色如果代码是执行的是:ret=FillRect(hdc, &rt/*&ps.rcPaint*/, brushes[x%2]);
    不太清楚为什么vista上只显示一种颜色,应该显示 交替的 红色 或 绿色 啊谢谢大家!