MFC CListCtrl解决闪烁问题(采坑无数)

3 篇文章 0 订阅

https://blog.csdn.net/jiangqin115/article/details/44904085
https://my.oschina.net/laopiao/blog/99320
https://bbs.csdn.net/topics/100134274
此几处虽介绍了几种方法,但实际并不好用。中间踩坑过程我不赘述了。这里要注意CListCtrl与CMFCListCtrl有所区别,区别在于CListCtrl的GetHeaderCtrl()返回的是指针,而CMFCListCtrl的GetHeaderCtrl返回的是引用。此外,这里容易漏写消息的注册,需要特别注意。

第一步:在初始化时可设置style或者新建控件时候设置。OnInitDialog()中

DWORD style = list1_.GetExtendedStyle();
style |= LVS_EX_FULLROWSELECT;
style |= LVS_EX_GRIDLINES;
style |= LVS_EX_FLATSB;
style |= LVS_EX_DOUBLEBUFFER;
style |=LVS_REPORT ;
style |=LVS_OWNERDATA;
list1_.SetExtendedStyle(style);

第二步:重写此类,
//CMyListCtrl.h

#pragma once
#include "afxcmn.h"
class CMyListCtrl :
	public CListCtrl
{
	DECLARE_DYNAMIC(CMyListCtrl)
public:
	CMyListCtrl(void);
	~CMyListCtrl(void);
	DECLARE_MESSAGE_MAP()
	afx_msg void OnPaint();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
public:
	CString GetItemText(int nItem, int nSubItem) const;
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
private:
	CDC* m_pDC;
};

//CMyListCtrl.cpp

#include "StdAfx.h"
#include "MyListCtrl.h"
IMPLEMENT_DYNAMIC(CMyListCtrl, CListCtrl)
CMyListCtrl::CMyListCtrl(void)
{
	m_pDC = NULL;
}
CMyListCtrl::~CMyListCtrl(void)
{
	if (!m_pDC)
	{
		delete m_pDC;
		m_pDC = NULL;
	}
}
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
	ON_WM_PAINT()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()
void CMyListCtrl::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	CRect rect;
	CRect headerRect;
	CDC MenDC;        
	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));   
	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)
{
	return FALSE;
}
CString CMyListCtrl::GetItemText(int nItem, int nSubItem) const
{
	ASSERT(::IsWindow(m_hWnd));
	LVITEM lvi;
	memset(&lvi, 0, sizeof(LVITEM));
	lvi.iSubItem = nSubItem;
	CString str;
	int nLen = 512;
	int nRes;
	do
	{
		nLen *= 2;
		lvi.cchTextMax = nLen;
		lvi.pszText = str.GetBufferSetLength(nLen);
		nRes  = (int)::SendMessage(m_hWnd, LVM_GETITEMTEXT, (WPARAM)nItem,
			(LPARAM)&lvi);
	} while (nRes >= nLen-1);
	str.ReleaseBuffer();
	return str;
}
void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
	CRect rcItem(lpDrawItemStruct->rcItem);
	int nItem = lpDrawItemStruct->itemID;
	COLORREF clrTextSave, clrBkSave;
	static _TCHAR szBuff[1024];
	LV_ITEM lvi;
	lvi.mask = LVIF_TEXT | LVIF_STATE;//LVIF_IMAGE |
	lvi.iItem = nItem;
	lvi.iSubItem = 0;
	lvi.pszText = szBuff;
	lvi.cchTextMax = sizeof(szBuff);
	lvi.stateMask = 0xFFFF;
	GetItem(&lvi);
	BOOL bSelected = (lvi.state & LVIS_SELECTED);
	CRect rcAllLabels;
	GetItemRect(nItem, rcAllLabels, LVIR_BOUNDS);
	if (bSelected)
	{
		clrTextSave = pDC->SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
		clrBkSave = pDC->SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
		pDC->FillRect(rcAllLabels, &CBrush(::GetSysColor(COLOR_HIGHLIGHT)));
	}
	GetItemRect(nItem, rcItem, LVIR_LABEL);
	pDC->DrawText(szBuff, -1, rcItem, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
	LV_COLUMN lvc;
	lvc.mask = LVCF_FMT | LVCF_WIDTH;
	for (int nColumn = 1; GetColumn(nColumn, &lvc); nColumn++)
	{
		rcItem.left = rcItem.right;
		rcItem.right += lvc.cx;
		int nRetLen = CListCtrl::GetItemText(nItem, nColumn,
			szBuff, sizeof(szBuff));
		if (nRetLen == 0)
			continue;
		UINT nJustify = DT_LEFT;
		switch (lvc.fmt & LVCFMT_JUSTIFYMASK)
		{
		case LVCFMT_RIGHT:
			nJustify = DT_RIGHT;
			break;
		case LVCFMT_CENTER:
			nJustify = DT_CENTER;
			break;
		default:
			break;
		}
		pDC->DrawText(szBuff, -1, rcItem,
			nJustify | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
	}
	if (lvi.state & LVIS_FOCUSED)
		pDC->DrawFocusRect(rcAllLabels);
	if (bSelected)
	{
		pDC->SetTextColor(clrTextSave);
		pDC->SetBkColor(clrBkSave);
	}
}**

第三步、在更新数据的地方进行以下操作,例如,此处我在OnTimer中更新数据,以下为伪代码,可自行根据场景修改。

void CMyDlg::OnTimer(UINT_PTR nIDEvent)
{

	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if (nIDEvent==1)
	{
		listCtrl.SetRedraw(FALSE);
		LVFINDINFO lv; 
		lv.flags=LVFI_STRING; 
		lv.psz=pid.c_str(); 
		int nItem=list1_.FindItem(&lv,-1);

		if (nItem < 0)
		{
			list1_.InsertItem(i, str, i);
		}
		else if (nItem ==0)
		{
			continue;
		}

		listCtrl.SetItemText(i, 1, name.c_str());
		listCtrl.SetItemText(i, 2, pid.c_str());
		listCtrl.SetItemText(i, 3, ip.c_str());

		listCtrl.SetImageList(&m_imagelist_s, LVSIL_SMALL);   //把m_Imagelist 关联给列表框。
		vlistCtrl.SetRedraw(TRUE);
	}
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值