轉載請注明來源:http://www.cnblogs.com/xuesongshu/
這幾天有點忙,寫完CListCtrl背景透明的實現后沒有接着寫,今天終於抽個空寫上了。程序運行效果請查看我的上篇一博客。、
1、把CTreeCtrl控件子類化。
void CAlphaTreeListDlg::PreInitDialog()
{
// TODO: 在此添加專用代碼和/或調用基類
//其它代碼......
m_tree.SubclassDlgItem(IDC_TREE1,this);
CDialogEx::PreInitDialog();
}
2、在InitDialog里給CTreeCtrl以做一些初始化的動作
BOOL CAlphaTreeListDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 將“關於...”菜單項添加到系統菜單中。
// IDM_ABOUTBOX 必須在系統命令范圍內。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 設置此對話框的圖標。當應用程序主窗口不是對話框時,框架將自動
// 執行此操作
SetIcon(m_hIcon, TRUE); // 設置大圖標
SetIcon(m_hIcon, FALSE); // 設置小圖標
// TODO: 在此添加額外的初始化代碼
SendDlgItemMessage(IDC_BUTTON1,WM_PARENTNOTIFY,WM_USER+1);
SendDlgItemMessage(IDC_STATIC1,WM_PARENTNOTIFY,WM_USER+1);
SendDlgItemMessage(IDC_TREE1,WM_PARENTNOTIFY,WM_USER+1);
return TRUE; // 除非將焦點設置到控件,否則返回 TRUE
}
3、增加成員:
class CMyTreeCtrl : public CTreeCtrl
{
DECLARE_DYNAMIC(CMyTreeCtrl)
public:
CMyTreeCtrl();
virtual ~CMyTreeCtrl();
protected:
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnPaint();
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
afx_msg void OnParentNotify(UINT message, LPARAM lParam);
afx_msg void OnTvnItemChanging(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnTvnItemexpanded(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult);
int m_nLeftMargin;
RECT m_rcWindow;
RECT m_rcClient;
afx_msg void OnNMClick(NMHDR *pNMHDR, LRESULT *pResult);
int m_nItemTextMargin;
};
4、新建一個類CMyListCtrl,實現WM_PAINT消息
void CMyTreeCtrl::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此處添加消息處理程序代碼
// 不為繪圖消息調用 CTreeCtrl::OnPaint()
CDC dcMem;
CClientDC dcParent(GetParent());
dcMem.CreateCompatibleDC(&dcParent);
dcMem.SelectObject(theBmp);
dc.SelectObject(GetStockObject(HOLLOW_BRUSH));
dc.SelectObject(theFont);
dc.SetBkColor(CLR_NONE);
dc.SetBkMode(TRANSPARENT);
CRgn rgn;
rgn.CreateRectRgnIndirect(&m_rcClient);
dc.SelectClipRgn(&rgn);
dc.BitBlt(0,0,m_rcClient.right,m_rcClient.bottom,&dcMem,m_rcWindow.left,m_rcWindow.top,SRCCOPY);
HTREEITEM hItem=GetFirstVisibleItem();
HTREEITEM hItemTmp=hItem;
RECT rcItemText;
CString strItem;
do
{
if (!hItem)
{
break;
}
hItemTmp=hItem;
GetItemRect(hItem,&rcItemText,FALSE);
strItem=GetItemText(hItem);
rcItemText.left+=m_nItemTextMargin;
rcItemText.right+=m_nItemTextMargin;
while (hItemTmp=GetParentItem(hItemTmp))
{
rcItemText.left+=GetIndent();
rcItemText.right+=GetIndent();
}
rcItemText.left-=m_nLeftMargin;
rcItemText.right-=m_nLeftMargin;
dc.DrawText(strItem,&rcItemText,DT_LEFT|DT_SINGLELINE|DT_VCENTER);
} while(hItem=GetNextVisibleItem(hItem));
}
5、實現TVN_SELCHANGED消息:
void CMyTreeCtrl::OnTvnSelchanged(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知處理程序代碼
Invalidate(FALSE);
CString strSelPath=L"";
strSelPath=GetItemText(GetSelectedItem());
HTREEITEM hItem=pNMTreeView->itemNew.hItem;
while (hItem=GetParentItem(hItem))
{
strSelPath.Insert(0,L"\\");
strSelPath.Insert(0,GetItemText(hItem));
}
LPTSTR lp=(LPTSTR)calloc(MAX_PATH,sizeof(TCHAR));
lstrcpy(lp,strSelPath.GetBuffer());
if (!ItemHasChildren(pNMTreeView->itemNew.hItem))
{
strSelPath+=L"\\*.*";
CFileFind ff;
CString strFileName=L"";
BOOL bFind=ff.FindFile(strSelPath);
do
{
bFind=ff.FindNextFile();
if (ff.IsDots())
{
continue;
}
strFileName=ff.GetFileName();
if (strFileName.IsEmpty())
{
break;
}
if (ff.IsDirectory())
{
InsertItem(strFileName,pNMTreeView->itemNew.hItem);
}
} while (bFind);
Expand(pNMTreeView->itemNew.hItem,TVE_EXPAND);
Invalidate(FALSE);
}
*pResult = 0;
}
6、實現WM_PARENTNOTIFY消息:
本代碼暫不處理瀏覽文件信處息之后文件增刪以及文件重命名等問題。
void CMyTreeCtrl::OnParentNotify(UINT message, LPARAM lParam)
{
if (message==WM_USER+1&&lParam==0)
{
DWORD dwDriveFlag=GetLogicalDrives();
int i=0,nMask=0;
LPTSTR lp=(LPTSTR)malloc(32);
for (i=0;i<32;i++)
{
nMask=(int)pow(2.0,i);
if (nMask&dwDriveFlag)
{
memset(lp,0,32);
wsprintf(lp,L"%C:",65+i);
InsertItem(lp);
}
}
GetClientRect(&m_rcClient);
GetWindowRect(&m_rcWindow);
GetParent()->ScreenToClient(&m_rcWindow);
m_nItemTextMargin=GetIndent();
}
else
{
CTreeCtrl::OnParentNotify(message, lParam);
}
// TODO: 在此處添加消息處理程序代碼
}
7、實現WM_HSCROLL、WM_VSCROLL、WM_MOUSEWHEEL、TVN_ITEMCHANGING、TVN_ITEMEXPANDED等消息,代碼樣板如下:
void CMyTreeCtrl::OnTvnItemChanging(NMHDR *pNMHDR, LRESULT *pResult)
{
NMTVITEMCHANGE *pNMTVItemChange = reinterpret_cast<NMTVITEMCHANGE *>(pNMHDR);
// TODO: 在此添加控件通知處理程序代碼
*pResult = 0;
}
void CMyTreeCtrl::OnTvnItemexpanded(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
// TODO: 在此添加控件通知處理程序代碼
Invalidate(FALSE);
*pResult = 0;
}
在處理鼠標、鍵盤消息時注意調用Invalidate(FALSE)。至此,一個透明的樹形控件出現在您的眼前了。
