CListCtrl透明完美实现

转载请注明来源:http://www.cnblogs.com/xuesongshu/

  网上找过很多资料,左不行右不通,你抄我抄大家抄的不管了,但是某些解释的详细的资料也不行,或许还有MFC版本的原因。咬咬牙,决定自己实现一个。虽然粗枝大叶,但是网友们如果按照这里的方法,应该能行。照着葫芦画瓢仍行不通的网友们请留言。说明一下,我用VS2010+MFC10环境。运行效果如下:

CListCtrl透明完美实现

  实现步骤如下:

  1、把CListCtrl子类化

  2、在IDE中把CListCtrl的Transparent复选框勾上。

  3、实现WM_PARENTNOTIFY,代码如下:

void CMyListCtrl::OnParentNotify(UINT message, LPARAM lParam)

{

	

	if (message==IDC_TREE_FILE)

	{

		LPTSTR lp=(LPTSTR)calloc(MAX_PATH,sizeof(TCHAR));

		lstrcpy(lp,(LPTSTR)lParam);

		memset(m_szFileFullName,0,MAX_PATH*sizeof(TCHAR));

		lstrcpy(m_szFileFullName,lp);

		lstrcat(lp,L"\\*.*");

		CFileFind ff;

		DeleteAllItems();

		GetParent()->InvalidateRect(&m_rc);

		SetRedraw(FALSE);

		BOOL bFind=ff.FindFile(lp);

		CString szFileName=L"";

		do 

		{

			bFind=ff.FindNextFile();

			if (ff.IsDots())

			{

				continue;

			}

			szFileName=ff.GetFileName();

			if (szFileName.IsEmpty())

			{

				break;

			}

			if (!ff.IsDirectory())

			{

				InsertItem(0,szFileName.GetBuffer(szFileName.GetLength()));

			}

		} while (bFind);

		SetRedraw(TRUE);

		GetParent()->InvalidateRect(&m_rc);

		delete lp;

	}

	else if (message==WM_USER+1&&lParam==0)

	{

		SetBkColor(CLR_NONE);

		SetTextBkColor(CLR_NONE);

		SetClassLong(GetSafeHwnd(),GCL_HBRBACKGROUND,(LONG)GetStockObject(NULL_BRUSH));

		GetWindowRect(&m_rc);

		GetParent()->ScreenToClient(&m_rc);

		::SendMessage(GetHeaderCtrl()->GetSafeHwnd(),WM_PARENTNOTIFY,WM_USER+1,0);

	}

	else

	{

		CListCtrl::OnParentNotify(message, lParam);

	}

}

  4、实现LVN_ITEMCHANGED,代码如下:

void CMyListCtrl::OnLvnItemchanged(NMHDR *pNMHDR, LRESULT *pResult)

{

	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);

	// TODO: 在此添加控件通知处理程序代码

	//要刷新旧列表项。用一个变量把旧列表项记录下来。

	GetParent()->InvalidateRect(&m_rc);

	//异或用于追加,与用于判断

	if (pNMLV->uNewState&LVIS_SELECTED)

	{

		LPTSTR lp=(LPTSTR)calloc(MAX_PATH,sizeof(TCHAR));

		lstrcpy(lp,m_szFileFullName);

		lstrcat(lp,L"\\");

		lstrcat(lp,GetItemText(pNMLV->iItem,pNMLV->iSubItem));

		GetParent()->SetDlgItemText(IDC_EDIT_FILE,lp);

		delete lp;

	}

	*pResult = 0;

}

  5、分别实现LVN_DELETEALLITEMS、LVN_DELETEITEM、WM_HSCROLL、WM_VSCROLL、WM_MOUSEWHEEL,在每个调用CListCtrl默认处理之后追加一行代码:

	GetParent()->InvalidateRect(&m_rc);

	*pResult = 0;

 

  6、用类向导新建一个继承CHeaderCtrl类的新类,实现WM_PAINT,代码如下:

void CMyHeaderCtrl::OnPaint()

{

	CPaintDC dc(this); // device context for painting

	// TODO: 在此处添加消息处理程序代码

	// 不为绘图消息调用 CHeaderCtrl::OnPaint()

	HDC dcMem=::CreateCompatibleDC(GetParent()->GetParent()->GetDC()->GetSafeHdc());

	SelectObject(dcMem,m_bmp);

	BitBlt(dc.GetSafeHdc(),0,0,m_rc.right-m_rc.left,m_rc.bottom-m_rc.top,dcMem,m_rc.left,m_rc.top,SRCCOPY);

	dc.SetBkMode(TRANSPARENT);

	dc.SetTextColor(RGB(255,0,0));

	dc.SelectObject(CreatePen(PS_DOT,1,RGB(255,0,255)));

	dc.SelectObject(GetStockObject(NULL_BRUSH));

	dc.SelectObject(m_font);

	dc.Rectangle(0,0,m_rc.right-m_rc.left,m_rc.bottom-m_rc.top);

	HDITEM col;

	GetItem(0,&col);

	if (lstrlen(col.pszText))

	{

		dc.TextOut(0,3,col.pszText,lstrlen(col.pszText));

	} 

	else

	{

		dc.TextOut(0,3,L"文件名",3);

	}

	

}

  

  7、重载PreSubclassWindow,代码如下:

void CMyListCtrl::PreSubclassWindow()

{

	// TODO: 在此添加专用代码和/或调用基类

	

	CListCtrl::PreSubclassWindow();

	m_headerFile.SubclassWindow(GetHeaderCtrl()->GetSafeHwnd());

}

  好了,到此完成。网友们一定发现界面上的CEdit、CButton、CStatic、CTreeCtrl全是透明的。下一篇博客我将介绍我是怎么做到CTreeCtrl透明的。

你可能感兴趣的:(list)