2012-09-19 41 views
3

我正在嘗試重新編寫使用C++和WinAPI編寫的Windows屏幕保護程序以在多臺顯示器上工作。我發現this article給出了基本知識。但是當我在自己的代碼中實現它時,我得到了一個奇怪的結果。看看這個代碼:似乎無法使用多臺顯示器製作雙緩衝繪畫

case WM_PAINT: 
{ 
    PAINTSTRUCT ps = {0}; 
    HDC hdcE = BeginPaint(hWnd, &ps); 

    EnumDisplayMonitors(hdcE, NULL, MyPaintEnumProc, 0); 

    EndPaint(hWnd, &ps); 
} 
break; 

BOOL CALLBACK MyPaintEnumProc(
     HMONITOR hMonitor, // handle to display monitor 
     HDC hdc1,  // handle to monitor DC 
     LPRECT lprcMonitor, // monitor intersection rectangle 
     LPARAM data  // data 
    ) 
{ 
    MONITORINFO mi = {0}; 
    mi.cbSize = sizeof(mi); 
    if(GetMonitorInfo(hMonitor, &mi)) 
    { 
     //Is it a primary monitor? 
     BOOL bPrimary = mi.dwFlags & MONITORINFOF_PRIMARY; 

     DoDrawing(bPrimary, hdc1, &mi.rcMonitor); 
    } 

    return 1; 
} 

void DoDrawing(BOOL bPrimaryMonitor, HDC hDC, RECT* pRcMonitor) 
{ 
//#define DIRECT_PAINT   //Comment out for double-buffering 

    int nMonitorW = abs(pRcMonitor->right - pRcMonitor->left); 
    int nMonitorH = abs(pRcMonitor->bottom - pRcMonitor->top); 

    HDC hMemDC = ::CreateCompatibleDC(hDC); 
    if(hMemDC) 
    { 
     HBITMAP hMemBmp = ::CreateCompatibleBitmap(hDC, nMonitorW, nMonitorH); 
     if(hMemBmp) 
     { 
      HBITMAP hOldBmp = (HBITMAP)SelectObject(hMemDC, hMemBmp); 

      COLORREF clr, clrBorder; 
      if(bPrimaryMonitor) 
      { 
       clr = RGB(0, 128, 0);   //Green 
       clrBorder = RGB(255, 0, 0); 
      } 
      else 
      { 
       clr = RGB(128, 0, 0);   //Red 
       clrBorder = RGB(0, 255, 0); 

      } 

      RECT rcRect; 
#ifndef DIRECT_PAINT 
      //With double-buffering 
      rcRect.left = 0; 
      rcRect.top = 0; 
      rcRect.right = nMonitorW; 
      rcRect.bottom = nMonitorH; 
#else 
      rcRect = *pRcMonitor; 
#endif 

      HBRUSH hBrush = ::CreateSolidBrush(clr); 

#ifndef DIRECT_PAINT 
      //With double-buffering 
      ::FillRect(hMemDC, &rcRect, hBrush); 
#else 
      ::FillRect(hDC, &rcRect, hBrush); 
#endif 


#ifndef DIRECT_PAINT 
      //With double-buffering 
      ::BitBlt(hDC, pRcMonitor->left, pRcMonitor->top, nMonitorW, nMonitorH, hMemDC, 0, 0, SRCCOPY); 
#endif 

//Debugging output 
CString _s; 
_s.Format(_T("%s\n") 
      _T("%s\n") 
      _T("hDC=0x%X\n") 
      _T("hMemDC=0x%X\n") 
     _T("RcMonitor: L=%d, T=%d, R=%d, B=%d") 
      , 
      bPrimaryMonitor ? _T("Primary") : _T("Secondary"), 
#ifndef DIRECT_PAINT 
      _T("Double-buffering"), 
#else 
      _T("Direct paint"), 
#endif 
      hDC, 
      hMemDC, 
      pRcMonitor->left, 
      pRcMonitor->top, 
      pRcMonitor->right, 
      pRcMonitor->bottom); 
::DrawText(hDC, _s, _s.GetLength(), pRcMonitor, DT_NOCLIP | DT_NOPREFIX); 


      SelectObject(hMemDC, hOldBmp); 
      ::DeleteObject(hMemBmp); 
     } 

     ::DeleteDC(hMemDC); 
    } 

} 

繪畫總是在主監視器上工作。但是,當我繪製輔助顯示器時,我只能直接繪製其DC。當我使用雙緩衝技術(DIRECT_PAINT預處理器指令註釋掉)時,在輔助監視器上它應該是紅色時,我只會看到一個黑屏。

我在這裏附上兩張截圖。

首先一個直接畫的作品: enter image description here

然後失敗的一個具有雙緩衝: enter image description here

任何想法,我究竟做錯了什麼?

+0

您是否檢查'FillRect()'和/或'BitBlt()'是否返回錯誤? –

+0

剛剛選中,它們都不在屏幕保護程序生命週期的任何點返回0。 – c00000fd

+0

大多數GDI函數對於返回錯誤是完全不可靠的。這甚至不值得檢查。 –

回答