2010-06-30 5 views
3

C++로 작성된 목록보기 컨트롤 (보고서 모드)이있는 일반 Win32 대화 상자를 고려하십시오. 특정 이벤트가 발생하면 모든 항목과 모든 열이 삭제되고 새 열과 항목이 만들어집니다. 기본적으로 콘텐츠가 변경되면 콘텐츠를 기반으로 열이 자동으로 생성됩니다.모든 항목과 모든 열을 제거하고 다시 추가 할 때 Win32 대화 상자에서 목록보기가 깜박임

오래된 항목/열을 제거하고 새 항목을 추가하면 목록보기가 지옥처럼 깜박입니다. WM_SETREDRAWLockWindowUpdate()을 사용하여 시각적 경험을 변경하지 않았습니다.

확장 목록보기 스타일을 LVS_EX_DOUBLEBUFFER으로 설정해도 전혀 도움이되지 않습니다.

부모 대화 상자에 WS_CLIPCHILDREN 세트가 있습니다.

가능한 한 작은 깜박임으로 어떻게 작동합니까? 두 개의 listviews, 가시성 번갈아, 백 버퍼로 숨겨진 하나를 사용하여 생각하고 있지만 이것은 과도한 소리처럼 들리 네. 쉬운 길이 있어야합니다.

+0

+1. 나는 VB 목록 상자에서도 이것을 보았다. 숨겨진 두 번째 목록 상자가 도움이 될지 잘 모르겠습니다. 그것을 교체하기 위해 깜박 거리면 언제 알 수 있습니까? –

+0

쉽습니다. 항목 및 열 삽입 중에 깜박임이 발생합니다. 마지막 항목이 추가되자 마자 깜박임이 멈 춥니 다. 항목 및 열이 보이지 않는 목록보기에 추가되면 깜박임이 발생할 수 없습니다. 마지막 단계는 숨겨진 내용을 표시하고 보이는 목록보기를 숨기는 것입니다. – wpfwannabe

답변

7

기본 목록 컨트롤 페인팅에는 결함이 있습니다. 이 비트 맵에 목록 컨트롤을 그리는 기본 창 프로 시저를 비트 맵을 만든 다음 호출합니다

CMyListCtrl::OnPaint() 
{ 
    CRect rcClient; 
    GetClientRect(rcClient); 

    CPaintDC dc(this); 
    CDC dcMem; 
    dcMem.CreateCompatibleDC(&dc); 

    CBitmap bmMem; 
    bmMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height()); 
    CBitmap* pbmOld = dcMem.SelectObject(&bmMem); 

    dcMem.FillSolidRect(rcClient, ::GetSysColor(COLOR_WINDOW)); 

    this->DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, (LPARAM)0); 

    dc.BitBlt(0,0,rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY); 
    dcMem.SelectObject(pbmOld); 

    CHeaderCtrl* pCtrl = this->GetHeaderCtrl(); 
    if (::IsWindow(pCtrl->GetSafeHWnd()) 
    { 
     CRect aHeaderRect; 
     pCtrl->GetClientRect(&aHeaderRect); 
     pCtrl->RedrawWindow(&aHeaderRect); 
    } 
} 

다음 비트 맵의 ​​내용을 블리트 : 그러나 간단한 트릭은 자신의 이중 버퍼링 기술을 구현할 수있다 페인트 DC에.

또한 WM_ERASEBKGND에 대한 처리기를 추가해야합니다 :

BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC) 
{ 
    return TRUE; 
} 

이 항상 다시 그리기 전에 배경을 삭제에서 컨트롤을 중지합니다. 비트 맵에 대한 멤버 변수를 추가하고 창 크기가 변경 될 때만 (다시 작성해야) 항상 OnPaint를 최적화 할 수 있습니다. 비트 맵을 만들면 항상 창의 크기에 따라 비용이 많이 들기 때문입니다.

꽤 잘 작동합니다.

+0

ListViews를 사용하여 작업 한 적이 있습니다. 더 나은 작업을하기 위해 지름길이 없습니다. 실제로 깜박이지 않게하려면 버퍼를 두 번 버퍼해야합니다. – Mordachai

+0

MFC에서 일반 Win32로 모든 것을 변환 한 후에이 방법을 시도했지만 부분적으로 만 작동합니다. 나는 두 가지 문제가있다.사소한 단점은 열이 제거되고 추가 될 때 가로 스크롤 막대가 깜박입니다. 하지만 대부분의 깜박임 문제가 해결되면서 함께 살 수있었습니다. 두 번째 주요 문제점은 열의 크기를 조정할 때 listview가 다시 표시되지 않는다는 것입니다. 적절한 방법으로 적절한 알림을 듣고 수동으로 다시 칠하는 것이 좋습니다. – wpfwannabe

+0

이 트릭과 함께 깜박 거리는 유일한 것은 헤더 컨트롤입니다. 다시 그리기 문제가 발생할 수있는 자신의 헤더를 하위 클래스로 만들었습니까? – humbagumba

1

많은 것을 시도한 후에 대부분 humbagumba 님의 제안을 듣고 나는 매우 간단한 결론에 도달했습니다. LockWindowUpdate은 이런 상황에서 모두의 친구입니다. 나는 그것이 처음으로 나를 위해 일하지 못했지만 어떻게 된 것인지 확신 할 수는 없다. 그러나 모든 상황에서 맞춤식 그림을 전달하지 못한 후에 나는 다시 한번 LockWindowUpdate을 시도했다.

기본적으로 모든 작업을 LockWindowUpdate(hWnd)LockWindowUpdate(NULL)으로 정리하면 모든 작업이 아름답게 처리됩니다. 더 이상 스크롤 막대 깜박임조차 없습니다.

한 번에 하나의 창만 잠글 수 있으므로 LockWindowUpdate을 중첩하지 않도록하십시오.

+0

사용자가 마우스로 무엇인가 드래그하지 않는 한 LockWindowUpdate는 친구가 아닙니다. http://blogs.msdn.com/b/oldnewthing/archive/2007/02/21/1735472.aspx 및 http : // blogs를 참조하십시오. msdn.com/b/oldnewthing/archive/2007/02/22/1742084.aspx – Anders