1.首先MFC向导生成一个单文档项目.
2.使用类向导从CDockablePane中派生出一个类.这里起名为CFileView
并且在stdafx.h中添加
#include "FileView.h"
3.在主框架类中(MainFrame.h)添加对象
protected:
CFileView m_wndFileView; //浮动框
4.创建浮动窗口在MainFrane.cpp中添加
// 利用这里的CBRS_RIGHT来设置最初的窗口停靠的位置, 可以的取值是
// CBRS_NOALIGN, CBRS_LEFT, CBRS_TOP, CBRS_RIGHT, CBRS_BOTTOM
DWORD style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CBRS_LEFT | CBRS_FLOAT_MULTI;
if (!m_wndFileView.Create(
_T("Dock1"),// 该dock窗口的标题(如果可以有的话...)
this,// 该dock窗口的parent, 设置为this
CRect(0, 0, 200, 200),// 窗口的大小, 注意是"悬浮"的情况下的大小, 处于dock状态时大小与该值无关
TRUE,// 该dock窗口是否有标题, 如果为FALSE, 则第一个字符串参数显示不出来
56,// 该dock窗口的ID值. 注意: 如果希望dock窗口的状态可以保存在注册表中(这样下次启动程序时仍保持该状态), 则该值必须的唯一的
//
style))
{
TRACE0("未能创建浮动框\n");
return -1; // 未能创建
}
5.设置窗口悬浮方式
// TODO: 如果您不希望工具栏和菜单栏可停靠,请删除这五行
m_wndMenuBar.EnableDocking(CBRS_ALIGN_ANY); //自动生成的菜单栏
m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); //自动生成的工具
m_wndFileView.EnableDocking(CBRS_ALIGN_ANY); //后添加的悬浮框
EnableDocking(CBRS_ALIGN_ANY);
DockPane(&m_wndMenuBar); //自动生成的菜单栏
DockPane(&m_wndToolBar); //自动生成的工具
DockPane(&m_wndFileView); //后添加的悬浮框
6.现在悬浮框添加好了,运行可以看到是个空框,下面CFileView加入内容.
(1)使用类向导派生出一个CFileTree类 基类为CTreeCtrl
在FileTree.h文件中添加
protected:
virtual BOOL OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult); //添加的语句
DECLARE_MESSAGE_MAP()
在FileTree.cpp中添加处理函数
/
// CViewTree 消息处理程序
BOOL CFileTree::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
BOOL bRes = CTreeCtrl::OnNotify(wParam, lParam, pResult);
NMHDR* pNMHDR = (NMHDR*)lParam;
ASSERT(pNMHDR != NULL);
if (pNMHDR && pNMHDR->code == TTN_SHOW && GetToolTips() != NULL)
{
GetToolTips()->SetWindowPos(&wndTop, -1, -1, -1, -1, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOSIZE);
}
return bRes;
}
(2) 再对CFileView类,使用类向导添加OnPaint,OnCreate,OnSize消息
(3)在FileView.h中添加如下内容
#include "FileTree.h" //头文件别忘记添加了
protected:
afx_msg void OnSize(UINT nType, int cx, int cy);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnItemexpandedTree(NMHDR* pNMHDR, LRESULT* pResult); // 展开树视图的某一项的响应函数
// afx_msg void OnSelchangedTree(NMHDR* pNMHDR, LRESULT* pResult);// 树视图选择改变的响应函数
afx_msg void OnPaint();
DECLARE_MESSAGE_MAP()
protected:
CFileTree m_Tree; //树控件
CImageList m_TreeImages; //图像列表控件
HTREEITEM m_hRoot; //节点句柄
// 获取本地逻辑驱动器
void GetLogicalDrives(HTREEITEM hParent);
// 在指定父节点下插入驱动盘下的所有子项
void InsertDriveDir(HTREEITEM hParent);
// 在指定父节点下插入目录下的所有子项
void AddSubDir(HTREEITEM hParent);
// 获取指定节点的全路径
CString GetFullPath(HTREEITEM hCurrent);
void AdjustLayout();
(4)在FileView.cpp中添加
a.OnPaint函数中
void CFileView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
CRect rectTree;
m_Tree.GetWindowRect(rectTree);
ScreenToClient(rectTree);
// dc.Draw3dRect(rectTree, ::GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DSHADOW));
// 不为绘图消息调用 CDockablePane::OnPaint()
}
b.OnSize函数中
void CFileView::OnSize(UINT nType, int cx, int cy)
{
CDockablePane::OnSize(nType, cx, cy);
// TODO: 在此处添加消息处理程序代码
AdjustLayout();
}
c.OnCreat函数中
int CFileView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDockablePane::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: 在此添加您专用的创建代码
CRect rectDummy;
rectDummy.SetRectEmpty();
// 创建视图:
const DWORD dwViewStyle = WS_CHILD | WS_VISIBLE | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;
if (!m_Tree.Create(dwViewStyle, rectDummy, this, 4))
{
TRACE0("未能创建文件视图\n");
return -1; // 未能创建
}
m_hRoot = m_Tree.InsertItem(L"我的电脑");
GetLogicalDrives(m_hRoot);
InsertDriveDir(m_hRoot);
AdjustLayout();
return 0;
}
d.
//调整大小
void CFileView::AdjustLayout()
{
if (GetSafeHwnd() == NULL)
{
return;
}
CRect rectClient;
GetClientRect(rectClient);
m_Tree.MoveWindow(rectClient);
}
e
// 获取本地逻辑驱动器
void CFileView::GetLogicalDrives(HTREEITEM hParent)
{
DWORD szAllDriveStrings = GetLogicalDriveStrings(0,NULL); //返回值的长度
LPWSTR pDriveStrings = new WCHAR[szAllDriveStrings + sizeof(_T(""))];
LPWSTR pDel = pDriveStrings;
GetLogicalDriveStrings(szAllDriveStrings, pDriveStrings);//szAllDriveStrings缓冲区大小,pDriveStrings接受字符
size_t szDriveString = wcslen(pDriveStrings);//返回字符数
while(szDriveString > 0)
{
m_Tree.InsertItem(pDriveStrings, hParent);
pDriveStrings += szDriveString + 1;
szDriveString = wcslen(pDriveStrings);
}
SAFE_DELETE_ARRAY (pDel);
}
这里使用到了一个宏添加到头文件中去
#define SAFE_DELETE_ARRAY(p) \
{ \
if ((p) != NULL) \
{ \
delete[] (p); \
(p) = NULL; \
} \
}
f.
// 在指定父节点下插入驱动盘下的所有子项
void CFileView::InsertDriveDir(HTREEITEM hParent)
{
HTREEITEM hChild = m_Tree.GetChildItem(hParent);
while(hChild)
{
CString strText = m_Tree.GetItemText(hChild);
if(strText.Right(1) != L"\\")
strText += L"\\";
strText += L"*.*";
CFileFind file;
BOOL bContinue = file.FindFile(strText);
while(bContinue)
{
bContinue = file.FindNextFile();
if(!file.IsDots())
m_Tree.InsertItem(file.GetFileName(), hChild);
}
InsertDriveDir(hChild);
hChild = m_Tree.GetNextItem(hChild, TVGN_NEXT);
file.Close();
}
}
g
// 在指定父节点下插入目录下的所有子项
void CFileView::AddSubDir(HTREEITEM hParent)
{
CString strPath = GetFullPath(hParent);
if(strPath.Right(1) != "\\")
strPath += "\\";
strPath += L"*.*";
CFileFind file;
BOOL bContinue = file.FindFile(strPath);
while(bContinue)
{
bContinue = file.FindNextFile();
if( !file.IsDots())
m_Tree.InsertItem(file.GetFileName(), hParent);
}
}
h
// 获取指定节点的全路径
CString CFileView::GetFullPath(HTREEITEM hCurrent)
{
CString strTemp;
CString strReturn = L"";
while(hCurrent != m_hRoot)
{
strTemp = m_Tree.GetItemText(hCurrent);
if(strTemp.Right(1) != "\\")
strTemp += L"\\";
strReturn = strTemp + strReturn;
hCurrent = m_Tree.GetParentItem(hCurrent);
}
return strReturn;
}
i
// 展开树视图的某一项的响应函数
void CFileView::OnItemexpandedTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
TVITEM item = pNMTreeView->itemNew;
if(item.hItem == m_hRoot)
return;
HTREEITEM hChild = m_Tree.GetChildItem(item.hItem);
while(hChild)
{
AddSubDir(hChild);
hChild = m_Tree.GetNextItem(hChild,TVGN_NEXT);
}
*pResult = 0;
}
这里需要加一个消息映射
BEGIN_MESSAGE_MAP(CFileView, CDockablePane)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_SIZE()
ON_NOTIFY(TVN_ITEMEXPANDED, 4, OnItemexpandedTree)// 展开树视图的某一项的映射函数
END_MESSAGE_MAP()
效果图如下