comctl32: Implement LVS_EX_DOUBLEBUFFER.

This commit is contained in:
Felix Nawothnig 2007-03-10 18:42:28 +01:00 committed by Alexandre Julliard
parent 5cdcfbfaa0
commit 79d4dfb601
1 changed files with 67 additions and 17 deletions

View File

@ -4030,31 +4030,68 @@ static void LISTVIEW_RefreshList(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, D
* PARAMETER(S): * PARAMETER(S):
* [I] infoPtr : valid pointer to the listview structure * [I] infoPtr : valid pointer to the listview structure
* [I] hdc : device context handle * [I] hdc : device context handle
* [I] prcErase : rect to be erased before refresh (may be NULL)
* *
* RETURN: * RETURN:
* NoneX * NoneX
*/ */
static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc) static void LISTVIEW_Refresh(LISTVIEW_INFO *infoPtr, HDC hdc, RECT *prcErase)
{ {
UINT uView = infoPtr->dwStyle & LVS_TYPEMASK; UINT uView = infoPtr->dwStyle & LVS_TYPEMASK;
COLORREF oldTextColor, oldBkColor, oldClrTextBk, oldClrText; COLORREF oldTextColor = 0, oldBkColor = 0, oldClrTextBk, oldClrText;
NMLVCUSTOMDRAW nmlvcd; NMLVCUSTOMDRAW nmlvcd;
HFONT hOldFont; HFONT hOldFont = 0;
DWORD cdmode; DWORD cdmode;
INT oldBkMode; INT oldBkMode = 0;
RECT rcClient; RECT rcClient;
ITERATOR i; ITERATOR i;
HDC hdcOrig = hdc;
HBITMAP hbmp = NULL;
LISTVIEW_DUMP(infoPtr); LISTVIEW_DUMP(infoPtr);
if (infoPtr->dwLvExStyle & LVS_EX_DOUBLEBUFFER) {
TRACE("double buffering\n");
hdc = CreateCompatibleDC(hdcOrig);
if (!hdc) {
ERR("Failed to create DC for backbuffer\n");
return;
}
hbmp = CreateCompatibleBitmap(hdcOrig, infoPtr->rcList.right,
infoPtr->rcList.bottom);
if (!hbmp) {
ERR("Failed to create bitmap for backbuffer\n");
DeleteDC(hdc);
return;
}
SelectObject(hdc, hbmp);
SelectObject(hdc, infoPtr->hFont);
} else {
/* Save dc values we're gonna trash while drawing
* FIXME: Should be done in LISTVIEW_DrawItem() */
hOldFont = SelectObject(hdc, infoPtr->hFont);
oldBkMode = GetBkMode(hdc);
oldBkColor = GetBkColor(hdc);
oldTextColor = GetTextColor(hdc);
}
infoPtr->bIsDrawing = TRUE; infoPtr->bIsDrawing = TRUE;
/* save dc values we're gonna trash while drawing */ if (prcErase) {
hOldFont = SelectObject(hdc, infoPtr->hFont); LISTVIEW_FillBkgnd(infoPtr, hdc, prcErase);
oldBkMode = GetBkMode(hdc); } else if (infoPtr->dwLvExStyle & LVS_EX_DOUBLEBUFFER) {
oldBkColor = GetBkColor(hdc); /* If no erasing was done (usually because RedrawWindow was called
oldTextColor = GetTextColor(hdc); * with RDW_INVALIDATE only) we need to copy the old contents into
* the backbuffer before continuing. */
BitBlt(hdc, infoPtr->rcList.left, infoPtr->rcList.top,
infoPtr->rcList.right - infoPtr->rcList.left,
infoPtr->rcList.bottom - infoPtr->rcList.top,
hdcOrig, infoPtr->rcList.left, infoPtr->rcList.top, SRCCOPY);
}
/* FIXME: Shouldn't need to do this */
oldClrTextBk = infoPtr->clrTextBk; oldClrTextBk = infoPtr->clrTextBk;
oldClrText = infoPtr->clrText; oldClrText = infoPtr->clrText;
@ -4110,10 +4147,21 @@ enddraw:
infoPtr->clrTextBk = oldClrTextBk; infoPtr->clrTextBk = oldClrTextBk;
infoPtr->clrText = oldClrText; infoPtr->clrText = oldClrText;
SelectObject(hdc, hOldFont); if(hbmp) {
SetBkMode(hdc, oldBkMode); BitBlt(hdcOrig, infoPtr->rcList.left, infoPtr->rcList.top,
SetBkColor(hdc, oldBkColor); infoPtr->rcList.right - infoPtr->rcList.left,
SetTextColor(hdc, oldTextColor); infoPtr->rcList.bottom - infoPtr->rcList.top,
hdc, infoPtr->rcList.left, infoPtr->rcList.top, SRCCOPY);
DeleteObject(hbmp);
DeleteDC(hdc);
} else {
SelectObject(hdc, hOldFont);
SetBkMode(hdc, oldBkMode);
SetBkColor(hdc, oldBkColor);
SetTextColor(hdc, oldTextColor);
}
infoPtr->bIsDrawing = FALSE; infoPtr->bIsDrawing = FALSE;
} }
@ -7884,6 +7932,9 @@ static inline BOOL LISTVIEW_EraseBkgnd(LISTVIEW_INFO *infoPtr, HDC hdc)
if (!GetClipBox(hdc, &rc)) return FALSE; if (!GetClipBox(hdc, &rc)) return FALSE;
/* for double buffered controls we need to do this during refresh */
if (infoPtr->dwLvExStyle & LVS_EX_DOUBLEBUFFER) return FALSE;
return LISTVIEW_FillBkgnd(infoPtr, hdc, &rc); return LISTVIEW_FillBkgnd(infoPtr, hdc, &rc);
} }
@ -8803,15 +8854,14 @@ static LRESULT LISTVIEW_Paint(LISTVIEW_INFO *infoPtr, HDC hdc)
UpdateWindow(infoPtr->hwndHeader); UpdateWindow(infoPtr->hwndHeader);
if (hdc) if (hdc)
LISTVIEW_Refresh(infoPtr, hdc); LISTVIEW_Refresh(infoPtr, hdc, NULL);
else else
{ {
PAINTSTRUCT ps; PAINTSTRUCT ps;
hdc = BeginPaint(infoPtr->hwndSelf, &ps); hdc = BeginPaint(infoPtr->hwndSelf, &ps);
if (!hdc) return 1; if (!hdc) return 1;
if (ps.fErase) LISTVIEW_FillBkgnd(infoPtr, hdc, &ps.rcPaint); LISTVIEW_Refresh(infoPtr, hdc, ps.fErase ? &ps.rcPaint : NULL);
LISTVIEW_Refresh(infoPtr, hdc);
EndPaint(infoPtr->hwndSelf, &ps); EndPaint(infoPtr->hwndSelf, &ps);
} }