CListCtrl透明完美实现
转载请注明来源:http://www.cnblogs.com/xuesongshu/
网上找过很多资料,左不行右不通,你抄我抄大家抄的不管了,但是某些解释的详细的资料也不行,或许还有MFC版本的原因。咬咬牙,决定自己实现一个。虽然粗枝大叶,但是网友们如果按照这里的方法,应该能行。照着葫芦画瓢仍行不通的网友们请留言。说明一下,我用VS2010+MFC10环境。运行效果如下:
实现步骤如下:
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透明的。