Felix Nawothnig : comctl32: Implement LVS_EX_DOUBLEBUFFER.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Mar 12 08:28:30 CDT 2007


Module: wine
Branch: master
Commit: 79d4dfb601a12239a610c6fabcbde988da8dc742
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=79d4dfb601a12239a610c6fabcbde988da8dc742

Author: Felix Nawothnig <flexo at holycrap.org>
Date:   Sat Mar 10 18:42:28 2007 +0100

comctl32: Implement LVS_EX_DOUBLEBUFFER.

---

 dlls/comctl32/listview.c |   84 ++++++++++++++++++++++++++++++++++++---------
 1 files changed, 67 insertions(+), 17 deletions(-)

diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 3e8ee59..113845d 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -4030,31 +4030,68 @@ static void LISTVIEW_RefreshList(LISTVIEW_INFO *infoPtr, ITERATOR *i, HDC hdc, D
  * PARAMETER(S):
  * [I] infoPtr : valid pointer to the listview structure
  * [I] hdc : device context handle
+ * [I] prcErase : rect to be erased before refresh (may be NULL)
  *
  * RETURN:
  * 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;
-    COLORREF oldTextColor, oldBkColor, oldClrTextBk, oldClrText;
+    COLORREF oldTextColor = 0, oldBkColor = 0, oldClrTextBk, oldClrText;
     NMLVCUSTOMDRAW nmlvcd;
-    HFONT hOldFont;
+    HFONT hOldFont = 0;
     DWORD cdmode;
-    INT oldBkMode;
+    INT oldBkMode = 0;
     RECT rcClient;
     ITERATOR i;
+    HDC hdcOrig = hdc;
+    HBITMAP hbmp = NULL;
 
     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;
 
-    /* save dc values we're gonna trash while drawing */
-    hOldFont = SelectObject(hdc, infoPtr->hFont);
-    oldBkMode = GetBkMode(hdc);
-    oldBkColor = GetBkColor(hdc);
-    oldTextColor = GetTextColor(hdc);
+    if (prcErase) {
+        LISTVIEW_FillBkgnd(infoPtr, hdc, prcErase);
+    } else if (infoPtr->dwLvExStyle & LVS_EX_DOUBLEBUFFER) {
+        /* If no erasing was done (usually because RedrawWindow was called
+         * 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;
     oldClrText   = infoPtr->clrText;
    
@@ -4110,10 +4147,21 @@ enddraw:
     infoPtr->clrTextBk = oldClrTextBk;
     infoPtr->clrText = oldClrText;
 
-    SelectObject(hdc, hOldFont);
-    SetBkMode(hdc, oldBkMode);
-    SetBkColor(hdc, oldBkColor);
-    SetTextColor(hdc, oldTextColor);
+    if(hbmp) {
+        BitBlt(hdcOrig, infoPtr->rcList.left, infoPtr->rcList.top,
+               infoPtr->rcList.right - infoPtr->rcList.left,
+               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;
 }
 
@@ -7884,6 +7932,9 @@ static inline BOOL LISTVIEW_EraseBkgnd(LISTVIEW_INFO *infoPtr, HDC hdc)
 
     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);
 }
 	
@@ -8803,15 +8854,14 @@ static LRESULT LISTVIEW_Paint(LISTVIEW_INFO *infoPtr, HDC hdc)
     UpdateWindow(infoPtr->hwndHeader);
 
     if (hdc) 
-	LISTVIEW_Refresh(infoPtr, hdc);
+        LISTVIEW_Refresh(infoPtr, hdc, NULL);
     else
     {
 	PAINTSTRUCT ps;
 
 	hdc = BeginPaint(infoPtr->hwndSelf, &ps);
 	if (!hdc) return 1;
-	if (ps.fErase) LISTVIEW_FillBkgnd(infoPtr, hdc, &ps.rcPaint);
-	LISTVIEW_Refresh(infoPtr, hdc);
+	LISTVIEW_Refresh(infoPtr, hdc, ps.fErase ? &ps.rcPaint : NULL);
 	EndPaint(infoPtr->hwndSelf, &ps);
     }
 




More information about the wine-cvs mailing list