窗口函数如下:LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
     static BOOL fState[DIVISIONS][DIVISIONS] ;
     static int  cxBlock, cyBlock ;
     HDC         hdc ;
     int         x, y ;
     PAINTSTRUCT ps ;
     RECT        rect ;
     
     switch (message)
     {
     case WM_SIZE :
          cxBlock = LOWORD (lParam) / DIVISIONS ;
          cyBlock = HIWORD (lParam) / DIVISIONS ;
          return 0 ;
          
     case WM_LBUTTONDOWN :
          x = LOWORD (lParam) / cxBlock ;
          y = HIWORD (lParam) / cyBlock ;
          
          if (x < DIVISIONS && y < DIVISIONS)
          {
               fState [x][y] ^= 1 ;
               
               rect.left   = x * cxBlock ;
               rect.top    = y * cyBlock ;
               rect.right  = (x + 1) * cxBlock ;
               rect.bottom = (y + 1) * cyBlock ;
               
               InvalidateRect (hwnd, &rect, FALSE) ;
          }
          else
               MessageBeep (0) ;
          return 0 ;
          
     case WM_PAINT :
          hdc = BeginPaint (hwnd, &ps) ;
  
          for (x = 0 ; x < DIVISIONS ; x++)
          for (y = 0 ; y < DIVISIONS ; y++)
          {
               Rectangle (hdc, x * cxBlock, y * cyBlock,
                         (x + 1) * cxBlock, (y + 1) * cyBlock) ;
                    
               if (fState [x][y])
               {
                    MoveToEx (hdc,  x    * cxBlock,  y    * cyBlock, NULL) ;
                    LineTo   (hdc, (x+1) * cxBlock, (y+1) * cyBlock) ;
                    MoveToEx (hdc,  x    * cxBlock, (y+1) * cyBlock, NULL) ;
                    LineTo   (hdc, (x+1) * cxBlock,  y    * cyBlock) ;
               }
          }
          EndPaint (hwnd, &ps) ;
          return 0 ;
               
     case WM_DESTROY :
          PostQuitMessage (0) ;
          return 0 ;
     }
     return DefWindowProc (hwnd, message, wParam, lParam) ;
}红字部分我觉得有问题,鼠标左键单击后,会运行InvalidateRect函数使一小块矩形无效,然后发出WM_PAINT,在处理WM_PAINT时,获得的hdc会仅用于这一小块无效矩形阿,怎么在函数里用了两个for循环阿,这样不就会使hdc对有效矩形操作了吗?这难道不会出错吗?作者这么用又是出于什么意图呢?望各位指点指点,谢谢!

解决方案 »

  1.   

    LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
         static BOOL fState[DIVISIONS][DIVISIONS] ;
         static int  cxBlock, cyBlock ;
         HDC         hdc ;
         int         x, y ;
         PAINTSTRUCT ps ;
         RECT        rect ;
         
         switch (message)
         {
         case WM_SIZE :
              cxBlock = LOWORD (lParam) / DIVISIONS ;
              cyBlock = HIWORD (lParam) / DIVISIONS ;
              return 0 ;
              
         case WM_LBUTTONDOWN :
              x = LOWORD (lParam) / cxBlock ;
              y = HIWORD (lParam) / cyBlock ;
              
              if (x < DIVISIONS && y < DIVISIONS)
              {
                   fState [x][y] ^= 1 ;
                   
                   rect.left   = x * cxBlock ;
                   rect.top    = y * cyBlock ;
                   rect.right  = (x + 1) * cxBlock ;
                   rect.bottom = (y + 1) * cyBlock ;
                   
                   InvalidateRect (hwnd, &rect, FALSE) ;
              }
              else
                   MessageBeep (0) ;
              return 0 ;
              
         case WM_PAINT :
              hdc = BeginPaint (hwnd, &ps) ;
              
              for (x = 0 ; x < DIVISIONS ; x++)
              for (y = 0 ; y < DIVISIONS ; y++)
              {
                   Rectangle (hdc, x * cxBlock, y * cyBlock,
                             (x + 1) * cxBlock, (y + 1) * cyBlock) ;
                        
                   if (fState [x][y])
                   {
                        MoveToEx (hdc,  x    * cxBlock,  y    * cyBlock, NULL) ;
                        LineTo   (hdc, (x+1) * cxBlock, (y+1) * cyBlock) ;
                        MoveToEx (hdc,  x    * cxBlock, (y+1) * cyBlock, NULL) ;
                        LineTo   (hdc, (x+1) * cxBlock,  y    * cyBlock) ;
                   }
              }
              EndPaint (hwnd, &ps) ;
              return 0 ;
                   
         case WM_DESTROY :
              PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }
      

  2.   

    这好像扫雷,但是按一下先下去,再按一下出来,先不管在wm_paint中做了什么,反正是往窗口上画了一些东西。在lbuttondown中,就将鼠标所在的那个区域重画。而其他的不变,并维护了fstate变量。由于wm_paint中的图像是由二维数组fState 维护的,所以整个窗口重画时并不破坏原来操作。
      

  3.   

    但是WM_LBUTTONDOWN中的
    InvalidateRect (hwnd, &rect, FALSE) ; 
    已经把无效窗口的区域写进了rect中,而在WM_PAINT中           
    hdc = BeginPaint (hwnd, &ps) ;
    ps里存的难道不是rect里的区域?我觉得获得的hdc仅能用于选定的无效窗口,而在for循环里Rectangle()肯定会在有效窗口内绘图,参数里的hdc难道允许它这么做吗? 
      

  4.   

    Windows重绘机制自己会处理无效矩形,在无效矩形外面的绘制不会有结果。
      

  5.   

    也就是说在for循环里Rectangle()会在有效窗口和无效窗口内绘图,但是由于hdc的作用,在有效窗口内的绘图将不产生效果,也就是说一楼的函数实现中在处理WM_PAINT时,作了一些多余的事情。是这个意思吗?
      

  6.   

    我晕,你把光盘上的源代码拷贝了过来。InvalidateRect( hwnd, &rect, FALSE );会将WM_PAINT放入消息队列,目前消息队列中处理的是WM_LBUTTONDOWN消息,只有等此消息处理完后,才从队列中取出下一个消息。
      

  7.   

    是这样,但是我的问题是,这段代码是否在处理WM_PAINT消息时,绘制了有效窗口,而绘制有效窗口我觉得是不会有效果产生的,所以这不是浪费吗?
      

  8.   

    4L正解,在失效区域外不管怎么画都没有用,而且在失效区域外的绘图操作都会在瞬间完成,基本上相当于没有执行绘图操作一样。
    可以看这帖里面关于绘图速率的问题:http://topic.csdn.net/u/20080129/15/5a642c5b-20a9-4db2-89c6-00219c2cda09.html