Thread: Double-buffered listview

  1. #1
    Registered User
    Join Date
    Sep 2004
    Posts
    8

    Double-buffered listview

    Hi. I'm having some problems making a listview (in report view) double-buffered. The code I have works fine (if you overlook the fact that it's allocating everything each time WM_PAINT is called,) but I can't seem to figure out how to draw the column headers. I'm assuming they're not actually part of the client area, but I've also tried various things involving WM_PRINTing PRF_NONCLIENT and similiar without much luck.

    I'd really appreciate any hints!

    The following is the code I currently have to paint the client area:

    Code:
    LRESULT CALLBACK LvPaintProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch(uMsg)
        {
            case WM_PAINT:
                {
                    HDC hdc, hdcNew;
                    HBITMAP hbm, hbmOld;
                    HBRUSH hbr;
                    PAINTSTRUCT ps;
            
                    hdc = BeginPaint(hWnd, &ps);
        
                    hdcNew = CreateCompatibleDC(hdc);
                    hbm = CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom);
                    hbmOld = SelectObject(hdcNew, hbm);
        
                    hbr = CreateSolidBrush(GetBkColor(hdc));
                    FillRect(hdcNew, &ps.rcPaint, hbr);
        
                    SendMessage(hWnd, WM_PRINTCLIENT, (WPARAM)hdcNew, (LPARAM)PRF_CLIENT|PRF_CHILDREN);
                    BitBlt(hdc, 0, 0, ps.rcPaint.right, ps.rcPaint.bottom, hdcNew, 0, 0, SRCCOPY);
        
                    SelectObject(hdcNew, hbmOld);
                    DeleteObject(hbm);
                    DeleteObject(hbr);
                    DeleteDC(hdcNew);
    
                    EndPaint(hWnd, &ps);
    
                    return TRUE;
                }
            case WM_ERASEBKGND:
                return TRUE;
        }
    
        return CallWindowProc((WNDPROC)GetWindowLong(hWnd, GWL_USERDATA), hWnd, uMsg, wParam, lParam);
    }

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Default List-View Message Processing
    Look at how WM_PAINT is handled. Just pass along WM_PAINT to the control and with your memory DC in wParam.

    >> hbm = CreateCompatibleBitmap(hdc, ps.rcPaint.right, ps.rcPaint.bottom);
    Don't assume that left and top will always be 0. Same goes for the BitBlt() call.

    Using this method you don't have to bother with FillRect(), the control knows how to render itself. Once you get it working you'll want to create a cached memory DC that's the same size as the client rect - this will eliminate creation and deletion overhead in WM_PAINT. You would then have to subclass the header control and have it paint to your memory DC as well.

    The header control is included in the control's client rect - that's why you don't see the header with your current code.

    gg

  3. #3
    Registered User
    Join Date
    Sep 2004
    Posts
    8
    Ah, yes.. I completely overlooked the fact that the listview header is a seperate control. Doh!

    So what I'm doing now is getting the window handle with LVM_GETHEADER on creation, and then re-creating the bitmap everytime the window gets WM_SIZE, so it'll always be the correct size. I then paint both the header and listview control into it on WM_PAINT, then blit it to the real DC. This seems like the best way to do it, but I might be wrong.. Anyway, it appears to work fine!

    And good point about the coordinates. I fixed that too, even though it
    seems to always be at 0,0, but we all know that you can never really rely on things like that.

    The only real issue is the amount of resources the bitmap cloning takes, but that's pretty much unavoidable if you want double-buffering, I guess.

    Thanks for your help.

  4. #4
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    That's exactly what I do.
    I doubt there's any better way to get all that rendering down to a single bit-blit.

    Welcome to the boards.

    gg

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Copying 2-d arrays
    By Holtzy in forum C++ Programming
    Replies: 11
    Last Post: 03-14-2008, 03:44 PM
  2. Conversion From C++ To C
    By dicon in forum C++ Programming
    Replies: 2
    Last Post: 06-10-2007, 02:54 PM
  3. need some help with last part of arrays
    By Lince in forum C Programming
    Replies: 3
    Last Post: 11-18-2006, 09:13 AM
  4. newbie needs help with code
    By compudude86 in forum C Programming
    Replies: 6
    Last Post: 07-23-2006, 08:54 PM
  5. Unknown Math Issues.
    By Sir Andus in forum C++ Programming
    Replies: 1
    Last Post: 03-06-2006, 06:54 PM