CListCtrl solve flashes and drag the horizontal scroll bar can not keep track of issues (MFC)

       A screen used in the project as shown below, have on CPropertySheet View, on which the CPropertyPage a few, have a property CListCtrl per page for the user to view the information. Since the information in the CListCtrl will refresh once every 200ms, leading to stop flashing the region. At the same time, due to the lack of space, there is a horizontal scroll bar on CListCtrl, when we want to scroll down to the middle of the back to see several columns of data, you just pull over and pulled back due to the refresh starting point, it makes it difficult to see behind columns of data we referred to this problem horizontal scroll bar can not track the problem. This review focuses on these two points to record relevant solutions.

(1) fixes flicker

      We know that the reason is because graphics flashing before each redraw calls OnEraseBkgnd with the background color of the erased area (default is white), resulting in too much contrast between before and after image, causing flickering visual. To remove the flashing is to reduce this contrast. A better method is to use a double buffering graphics, i.e. open a canvas in memory for graphics, and then to draw graphics good copy display device ( http://www.diybl.com/course/3_program/ ++ c / cppjs / 200867 / 123361.html ). In addition, to prevent CListCtrl flicker problems, users also summarized ( http://blog.sina.com.cn/s/blog_5ee42ba30100g50j.html ).

     In the access to the above information, combined with the problem itself, the design of the following solutions to solve the flicker problem.

    First, since all data is updated on the display CListCtrl, for View, CPropertySheet, CPropertyPage, and nothing changes, it may prohibit erase area with the background color each time you redraw, reduce the contrast. Overload message respectively OnEraseBkgnd these three functions, change return FALSE; .

    Second, for CListCtrl flicker problem can be solved using double buffering. As follows:

void CMyListCtrl::OnPaint()
{
	//使用双缓冲的方法绘制背景
	CPaintDC dc(this); // device context for painting
	CRect rect;
	CRect headerRect;
	CDC MenDC;		//内存DC   
	CBitmap MemMap;

	GetClientRect(&rect);    
	GetDlgItem(0)->GetWindowRect(&headerRect);   
	MenDC.CreateCompatibleDC(&dc);   
	MemMap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); 
	MenDC.SelectObject(&MemMap);
	MenDC.FillSolidRect(&rect,RGB(255,255,255));   

	//调用默认的OnPaint(),把图形画在内存DC表上   
	DefWindowProc(WM_PAINT,(WPARAM)MenDC.m_hDC,(LPARAM)0);   

	//输出到显示设备
	dc.BitBlt(0,
		headerRect.Height(),   
		rect.Width(),   
		rect.Height(),   
		&MenDC,   
		0,     
		headerRect.Height(),   
		SRCCOPY);   
	MenDC.DeleteDC();
	MemMap.DeleteObject();
}

BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC)
{
	// TODO: Add your message handler code here and/or call default

	//return CListCtrl::OnEraseBkgnd(pDC);
	return FALSE;
}
     At this point, solve the overall problem of flicker.

(2) horizontal scroll bar can not solve the problem tracking

      For this problem, I started more confused, do not know how to solve, from online search, I was raised with GetScrollPos + Scroll, it was suggested by EnsureVisible. The first method I tried, mainly records the current position of the scroll bar, and then set to the position recorded after a refresh, this method is not a good record back position, and to do so would reintroduce the flicker problem ( from the position of the scroll bar to the starting position and then to record the recording position, a great contrast). The second approach looks only be used for multi-line, multi-column for it seems not.

     So, I rethink this issue. When I was in the program's approach is refreshed each time, first delete all of the line item, and then re-insert the line item that contains the new data information. In fact, the number of lines still remain the same, each update only some of the Item's contents only, so I can not always just wanted to be able to update the data without erasing the line item and re-insert operations, unless there is a new line item Join before this operation. If you can not return to the position of the scroll bar, then you can view the size of the current view based on the calculated need to update the current Item CListCtrl item that is updated each time the data are not all the Item column item, only the area within view of the current View the content is updated (later found to not have to do this has been the first point has been able to solve the problem).

      After changes are made to the program, tracking the horizontal scroll bar can be achieved.

void UpdateItem()
{
   //......
     CString str;
     BOOL bInsertItem = FALSE;
     if(m_bInsertItem)
     {
        m_bInsertItem = FALSE;
	bInsertItem = TRUE;
	m_listInfo.DeleteAllItems();		//删除原有的数据
     }
     for(i=0; i<CNT; i++)
     {  
        str.Format(_T("%d"), i+1);			//序号
	if(bInsertItem)
	    m_listInfo.InsertItem(i, str);		//插入行,显示序号
	str.Format(_T("ID=%d"), xxx);
	m_listInfo.SetItemText(i, 1, str);
       //插入其他内容......
       //......
     }
} 



发布了37 篇原创文章 · 获赞 204 · 访问量 44万+

Guess you like

Origin blog.csdn.net/zwgdft/article/details/7394318