|  | 
          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(也就是不使用雙緩衝技術)
 
 |