  | 
      
        
          1樓
          巨大八爪鱼
          2016-6-25 15:44
          
          
           
         
        【原程序】 void OnPaint(HDC hdc, LPPAINTSTRUCT lpps) {     int i, j;     for (i = lpps->rcPaint.left; i <= lpps->rcPaint.right; i++)     {         for (j = lpps->rcPaint.top; j <= lpps->rcPaint.bottom; j++)             SetPixel(hdc, i, j, i * j * i * j);     } } 该程序需要3秒左右才能执行完。
  
       | 
    
    
        | 
      
        
          2樓
          巨大八爪鱼
          2016-6-25 15:47
          
          
           
         
        【解决方案1:CreateCompatibleBitmap + SetDIBits】 LPBYTE AllocateBits(int nWidth, int nHeight, int nBitCount, int *pSize) {     *pSize = ((nWidth * nBitCount + 31) / 32) * 4 * nHeight;     if (*pSize < 0)         *pSize = -*pSize;     return (LPBYTE)malloc(*pSize); }
  void OnPaint(HDC hdc, LPPAINTSTRUCT lpps) {     BITMAPINFOHEADER bmh;     COLORREF color;     HBITMAP hbmp;     HDC hdcMem;     LPBYTE lpBits, p;     int i, j;     int padding, size;
      ZeroMemory(&bmh, sizeof(bmh));     bmh.biSize = sizeof(bmh);     bmh.biBitCount = 24; // 真彩色     bmh.biPlanes = 1; // 颜色平面数必须为1     bmh.biWidth = lpps->rcPaint.right - lpps->rcPaint.left;     bmh.biHeight = lpps->rcPaint.top - lpps->rcPaint.bottom; // 使height为负数的目的是使位图数据的方向为从上到下
      // 生成DIB位图数据     lpBits = AllocateBits(bmh.biWidth, bmh.biHeight, bmh.biBitCount, &size); // 为位图分配内存     padding = (4 - (bmh.biWidth * bmh.biBitCount / 8) % 4) % 4; // 计算每行后的保留字节     p = lpBits;     for (j = lpps->rcPaint.top; j < lpps->rcPaint.bottom; j++)     {         for (i = lpps->rcPaint.left; i < lpps->rcPaint.right; i++)         {             color = i * j * i * j; // 算法和之前一样             *p++ = (color >> 16) & 0xff;             *p++ = (color >> 8) & 0xff;             *p++ = color & 0xff;         }         p += padding;     }
      hbmp = CreateCompatibleBitmap(hdc, bmh.biWidth, -bmh.biHeight); // 创建DDB位图     SetDIBits(hdc, hbmp, 0, -bmh.biHeight, lpBits, (LPBITMAPINFO)&bmh, DIB_RGB_COLORS); // DIB转换为DDB     free(lpBits);
      hdcMem = CreateCompatibleDC(hdc);     SelectObject(hdcMem, hbmp);     BitBlt(hdc, lpps->rcPaint.left, lpps->rcPaint.top, bmh.biWidth, -bmh.biHeight, hdcMem, 0, 0, SRCCOPY); // DDB输出到显示器     DeleteDC(hdcMem);     DeleteObject(hbmp); }
  
       | 
    
    
        | 
      
        
          3樓
          巨大八爪鱼
          2016-6-25 15:52
          
          
           
         
        【解决方案2:CreateDIBitmap】 由于CreateDIBitmap = CreateCompatibleBitmap + SetDIBits,所以可以把上述代码中的:
  hbmp = CreateCompatibleBitmap(hdc, bmh.biWidth, -bmh.biHeight); // 创建DDB位图 SetDIBits(hdc, hbmp, 0, -bmh.biHeight, lpBits, (LPBITMAPINFO)&bmh, DIB_RGB_COLORS); // DIB转换为DDB
  直接换成: hbmp = CreateDIBitmap(hdc, &bmh, CBM_INIT, lpBits, (LPBITMAPINFO)&bmh, DIB_RGB_COLORS); // 根据DIB直接创建DDB位图
  
       | 
    
    
        | 
      
        
          4樓
          巨大八爪鱼
          2016-6-25 15:55
          
          
           
         
        
          
          【原程序】 void OnPaint(HDC hdc, LPPAINTSTRUCT lpps) {     int i, j;...
  
         
        如果显示器较大的话,执行完需要8秒! 
       | 
    
    
        | 
      
        
          5樓
          巨大八爪鱼
          2016-6-25 16:01
          
          
           
         
        【解决方案3:CreateDIBSection,自动分配和释放位图内存】 void OnPaint(HDC hdc, LPPAINTSTRUCT lpps) {     BITMAPINFOHEADER bmh;     COLORREF color;     HBITMAP hbmp;     HDC hdcMem;     LPBYTE lpBits, p; // CreateDIBSection自动分配内存     int i, j;     int padding;
      ZeroMemory(&bmh, sizeof(bmh));     bmh.biSize = sizeof(bmh);     bmh.biBitCount = 24; // 真彩色     bmh.biPlanes = 1; // 颜色平面数必须为1     bmh.biWidth = lpps->rcPaint.right - lpps->rcPaint.left;     bmh.biHeight = lpps->rcPaint.top - lpps->rcPaint.bottom; // 使height为负数的目的是使位图数据的方向为从上到下
      hbmp = CreateDIBSection(hdc, (LPBITMAPINFO)&bmh, DIB_RGB_COLORS, (LPVOID *)&lpBits, NULL, NULL);     padding = (4 - (bmh.biWidth * bmh.biBitCount / 8) % 4) % 4; // 计算每行后的保留字节     p = lpBits;     for (j = lpps->rcPaint.top; j < lpps->rcPaint.bottom; j++)     {         for (i = lpps->rcPaint.left; i < lpps->rcPaint.right; i++)         {             color = i * j * i * j; // 算法和之前一样             *p++ = (color >> 16) & 0xff;             *p++ = (color >> 8) & 0xff;             *p++ = color & 0xff;         }         p += padding;     }
      hdcMem = CreateCompatibleDC(hdc);     SelectObject(hdcMem, hbmp);     BitBlt(hdc, lpps->rcPaint.left, lpps->rcPaint.top, bmh.biWidth, -bmh.biHeight, hdcMem, 0, 0, SRCCOPY);     DeleteDC(hdcMem);     DeleteObject(hbmp); // 删除位图时自动释放内存 }
  
       | 
    
    
        | 
      
        
          6樓
          巨大八爪鱼
          2016-6-25 16:08
          
          
           
         
        【解决方案4:SetDIBitsToDevice,不创建位图对象,直接把位图数据往显示器上输出】 LPBYTE AllocateBits(int nWidth, int nHeight, int nBitCount, int *pSize) {     *pSize = ((nWidth * nBitCount + 31) / 32) * 4 * nHeight;     if (*pSize < 0)         *pSize = -*pSize;     return (LPBYTE)malloc(*pSize); }
  void OnPaint(HDC hdc, LPPAINTSTRUCT lpps) {     BITMAPINFOHEADER bmh;     COLORREF color;     LPBYTE lpBits, p;     int i, j;     int padding, size;
      ZeroMemory(&bmh, sizeof(bmh));     bmh.biSize = sizeof(bmh);     bmh.biBitCount = 24; // 真彩色     bmh.biPlanes = 1; // 颜色平面数必须为1     bmh.biWidth = lpps->rcPaint.right - lpps->rcPaint.left;     bmh.biHeight = lpps->rcPaint.top - lpps->rcPaint.bottom; // 使height为负数的目的是使位图数据的方向为从上到下
      // 生成DIB位图数据     lpBits = AllocateBits(bmh.biWidth, bmh.biHeight, bmh.biBitCount, &size); // 为位图分配内存     padding = (4 - (bmh.biWidth * bmh.biBitCount / 8) % 4) % 4; // 计算每行后的保留字节     p = lpBits;     for (j = lpps->rcPaint.top; j < lpps->rcPaint.bottom; j++)     {         for (i = lpps->rcPaint.left; i < lpps->rcPaint.right; i++)         {             color = i * j * i * j; // 算法和之前一样             *p++ = (color >> 16) & 0xff;             *p++ = (color >> 8) & 0xff;             *p++ = color & 0xff;         }         p += padding;     }
      SetDIBitsToDevice(hdc, lpps->rcPaint.left, lpps->rcPaint.top, bmh.biWidth, -bmh.biHeight, 0, 0, 0, -bmh.biHeight, lpBits, (LPBITMAPINFO)&bmh, DIB_RGB_COLORS);     free(lpBits); }
  
       | 
    
    
        | 
      
        
          7樓
          巨大八爪鱼
          2016-6-25 16:09
          
          
           
         
        【消息处理部分】 case WM_ERASEBKGND:     // 防止改变窗口大小时窗口内容被擦除导致闪烁     break;
  case WM_PAINT:     hdc = BeginPaint(hWnd, &ps);     OnPaint(hdc, &ps);     EndPaint(hWnd, &ps);     break; 
       | 
    
    
        | 
      
        
          8樓
          巨大八爪鱼
          2016-6-25 16:10
          
          
           
         
        
       | 
    
    
        | 
      
        
          9樓
          巨大八爪鱼
          2016-6-25 16:14
          
          
           
         
        本人推荐使用方案3。因为方案3创建位图时是系统自动分配和释放内存,此外,不但可以直接操作DIB位图数据,还可以将该位图选入HDC进行图形绘制,非常方便。 不过如果是纯裸位图数据,可以考虑使用方案4的方法不创建位图直接输出到显示器。
  
       | 
    
    
        | 
      
        
          10樓
          巨大八爪鱼
          2016-6-25 16:16
          
          
           
         
        方案4所说的位图对象,是指HBITMAP,不是指位图数据。 方案4的代码里完全没有出现hdcMem和HBITMAP,以及BitBlt(也就是不使用双缓冲技术)
  
       |