这是《windows程序设计》中的例题,在case   WM_PAINT:分支中用了InvalidateRect (hwnd, NULL, TRUE)函数,但是我去掉这个函数以后程序也可以正常运行,请那位达人给解释一下用法和原因!
#include <windows.h>
        
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
        
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
        
                          PSTR szCmdLine, int iCmdShow)
        
{
        
    static TCHAR szAppName[] = TEXT ("Bezier") ;
        
    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 ("Program requires Windows NT!"),
        
                                    szAppName, MB_ICONERROR) ;
        
                  return 0 ;
        
    }
        
   
        
    hwnd = CreateWindow (szAppName, TEXT ("Bezier Splines"),
        
                                         WS_OVERLAPPEDWINDOW,
        
                           CW_USEDEFAULT, CW_USEDEFAULT,
        
                           CW_USEDEFAULT, CW_USEDEFAULT,
        
                           NULL, NULL, hInstance, NULL) ;
        
   
        
    ShowWindow (hwnd, iCmdShow) ;
        
    UpdateWindow (hwnd) ;
        
   
        
    while (GetMessage (&msg, NULL, 0, 0))
        
    {
        
            TranslateMessage (&msg) ;
        
            DispatchMessage (&msg) ;
        
    }
        
    return msg.wParam ;
        
}
        void DrawBezier (HDC hdc, POINT apt[])
        
{
        
    PolyBezier (hdc, apt, 4) ;
        
    MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ;
        
    LineTo   (hdc, apt[1].x, apt[1].y) ;
        
   
        
    MoveToEx (hdc, apt[2].x, apt[2].y, NULL) ;
        
    LineTo   (hdc, apt[3].x, apt[3].y) ;
        
}
        
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        
{
        
    static POINT apt[4] ;
        
    HDC          hdc ;
        
    int          cxClient, cyClient ;
        
    PAINTSTRUCT  ps ;
            switch (message)
        
    {
        
    case WM_SIZE:
        
            cxClient = LOWORD (lParam) ;
        
            cyClient = HIWORD (lParam) ;
        
        
        
                   apt[0].x = cxClient / 4 ;
        
                   apt[0].y = cyClient / 2 ;
        
        
        
                   apt[1].x = cxClient / 2 ;
        
                   apt[1].y = cyClient / 4 ;
        
        
        
                   apt[2].x = cxClient / 2 ;
        
                   apt[2].y = 3 * cyClient / 4 ;
        
        
        
                   apt[3].x = 3 * cxClient / 4 ;
        
                   apt[3].y = cyClient / 2 ;
        
        
        
                   return 0 ;
            case WM_LBUTTONDOWN:
        
    case WM_RBUTTONDOWN:
        
    case WM_MOUSEMOVE:
        
            if (wParam & MK_LBUTTON || wParam & MK_RBUTTON)
        
            {
        
                   hdc = GetDC (hwnd) ;
        
                   SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
        
                   DrawBezier (hdc, apt) ;
        
             
        
                   if (wParam & MK_LBUTTON)
        
                   {
        
                           apt[1].x = LOWORD (lParam) ;
        
                           apt[1].y = HIWORD (lParam) ;
        
                   }
        
             
        
              if (wParam & MK_RBUTTON)
        
                  {
        
                                   apt[2].x = LOWORD (lParam) ;
        
                                   apt[2].y = HIWORD (lParam) ;
        
                   }
        
             
        
                   SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
        
                   DrawBezier (hdc, apt) ;
        
                   ReleaseDC (hwnd, hdc) ;
        
            }
        
                   return 0 ;
        
    case   WM_PAINT:
        
            InvalidateRect (hwnd, NULL, TRUE) ;
        
        
        
            hdc = BeginPaint (hwnd, &ps) ;
        
        
        
            DrawBezier (hdc, apt) ;
        
        
        
            EndPaint (hwnd, &ps) ;
        
            return 0 ;
        
        
        
    case WM_DESTROY:
        
            PostQuitMessage (0) ;
        
            return 0 ;
        
    }
        
    return DefWindowProc (hwnd, message, wParam, lParam) ;
        
}

解决方案 »

  1.   

    InvalidateRect函数使矩形区域变得无效,从而引发重绘
      

  2.   

    程序是可以正常运行,但当你改变窗口中的东西以后,程序并不调用InvalidateRect函数使矩形区域变得无效,你画出来的东西就不会立即显示出来,只有当你移动窗口时才会引起窗口重绘,从而将你刚才所画的东西显示出来。
    加上了InvalidateRect函数就会在你在窗口中画出东西后立即在窗口中显示你画的东西。
    其实就这个样了,要我说得多么清楚我也说不清,你试试就可以了。
    先不加此函数,然后做一些操作,然后再加上此函数,再做一些操作,看两次有什么区别,然后函数的作用就出来了。
      

  3.   

    InvalidateRect()单独用是没效果的,要和UpdateWindow()一起使用才有效果
    //立即刷新这块区域
    InvalidateRect(rect);
    UpdateWindow();
      

  4.   

    我的理解是 InvalidateRect (hwnd, NULL, TRUE) ;
    将会引发一个WM_PAINT消息,这样的理解对不?
      

  5.   

    我一直认为这段例程是错的,误导了很多人,在WM_PAINT消息中加InvalidateRect()不知道干什么。
      

  6.   

    我的理解是 InvalidateRect (hwnd, NULL, TRUE) ;
    将会引发一个WM_PAINT消息,这样的理解对不?不会!!这仅仅是把一个矩形标记为一个需要下一次重绘的无效区域,在下一个WM_PAINT消息的时候,会把这个区域加入到需要更新的区域,并计算出需要重绘的最小区域在程序里调用UpdateWindow();可以强制发出WM_PAINT消息,至于是否重绘,取决于计算出来的需要更新的区域又没有,如果没有,就不需要重绘,否则重绘那些无效区域