Кажется, что я не могу сделать рисование с двойной буферизацией с несколькими мониторами.

Я пытаюсь переделать свою заставку Windows, написанную на C ++ и WinAPI, для работы на нескольких мониторах. я нашел Эта статья это дает основы. Но когда я реализую это в своем собственном коде, я получаю странный результат. Посмотрите на этот код:

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), на дополнительном мониторе черный экран появляется только тогда, когда он должен был быть красным.

Я прилагаю два скриншота здесь.

Первый с прямой покраской, которая работает:
введите описание изображения здесь

И затем тот с двойной буферизацией, которая терпит неудачу:
введите описание изображения здесь

Есть идеи, что я здесь делаю не так?

3

Решение

Заменить код для WM_PAINT из

case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EnumDisplayMonitors(hdc, NULL, MyPaintEnumProc, 0);
EndPaint(hWnd, &ps);

с

case WM_PAINT:
hdc = GetDC(NULL);
EnumDisplayMonitors(hdc, NULL, MyPaintEnumProc, 0);
ReleaseDC(NULL, hdc);

и это будет работать.

Видеть это http://msdn.microsoft.com/en-us/library/windows/desktop/dd162610(v=vs.85).aspx.

2

Другие решения

Других решений пока нет …