mfc tree control 添加任意多个节点 比如说,一个对话框,我有一个编辑框,一个

mfc tree control 添加任意多个节点 比如说,一个对话框,我有一个编辑框,一个,第1张

你这是在给自己找麻烦,这样的 *** 作逻辑,拆分倒是好说,字符串拆分后循环设置为父节点即可,但维护太困难了,甚至一个录入错误会造成大量需要删除的节点,而增加子节点的节点也多输入很多内容。

通常这样的界面,是看树形列表中是否选取了节点,如果选取了,就以选中的为父节点,否则就是默认根为父节点,这样一个一个增加就可以了,不会出现歧义,录入错误也会少些。

很简单:

第一步:在向导中给你的树形控件关联一个CTreeCtrl的变量(就像你代码中的m_Mess)

第二步:在向导中,添加该树形控件的NM_Click消息(就是鼠标单击消息,以下假设函数名为OnClickTree)

第三步:在代码中添加你的数据(主要是在初始化树形控件的数据的函数中,如你代码中的OnInitDialog()就可以)

HTREEITEM hRoot = m_ctrlTree.InsertItem("北京")

m_ctrlTree.SetItemData(hRoot, 1)

HTREEITEM hChild = m_ctrlTree.InsertItem("朝阳区", hRoot)

m_ctrlTree.SetItemData(hChild, 2)

hChild = m_ctrlTree.InsertItem("海淀区", hRoot)

m_ctrlTree.SetItemData(hChild, 3)

注意:我在上面用了SetItemData函数,主要是给不同的节点添加不同的标记

,在下面的单击消息函数中就可以看出它的作用

第四步:在OnClickTree函数中添加鼠标单击消息响应代码

CPoint pt = GetCurrentMessage()->pt //获取当前鼠标点击消息的坐标点

m_ctrlTree.ScreenToClient(&pt) //将鼠标的屏幕坐标,转换成树形控件的客户区坐标

UINT uFlags = 0

HTREEITEM hItem = m_ctrlTree.HitTest(pt, &uFlags)//然后做点击测试

if ((hItem != NULL) &&(TVHT_ONITEM &uFlags))//如果点击的位置是在节点位置上面

{

m_ctrlTree.SelectItem(hItem)

//获取开始我们设置的数据,注意这就是我为什么开始要每个节点设置不同的数据的原因。当然,如果你的数据节点比较少,你也可以通过获取节点的文字,如上面设置的"海淀区",然后通过字符串比较来判断点击了哪个节点

int nDat = m_ctrlTree.GetItemData(hItem)

//然后根据不同的节点,你完成不同的动作即可

switch (nDat)

{

case 1:

AfxMessageBox("北京")

break

case 2:

AfxMessageBox("北京->朝阳区")

break

case 3:

AfxMessageBox("北京->海淀区")

break

default:

AfxMessageBox("ERROR")

}

// TreeCtrlTestDlg.h : 头文件

//

#pragma once

#include "afxcmn.h"

#include "afxwin.h"

// CTreeCtrlTestDlg 对话框

class CTreeCtrlTestDlg : public CDialog

{

// 构造

public:

CTreeCtrlTestDlg(CWnd* pParent = NULL)// 标准构造函数

// 对话框数据

enum { IDD = IDD_TREECTRLTEST_DIALOG }

protected:

virtual void DoDataExchange(CDataExchange* pDX)// DDX/DDV 支持

// 实现

public:

CString GetSelectedDir()

protected:

HICON m_hIcon

// 生成的消息映射函数

virtual BOOL OnInitDialog()

afx_msg void OnSysCommand(UINT nID, LPARAM lParam)

afx_msg void OnPaint()

afx_msg HCURSOR OnQueryDragIcon()

DECLARE_MESSAGE_MAP()

public:

CTreeCtrl m_tree

void OutTreeToList(HTREEITEM node)

CImageList m_ImageList

afx_msg void OnNMDblclkTreeFile(NMHDR *pNMHDR, LRESULT *pResult)

afx_msg void OnBnClickedButton1()

CListBox m_name_lst

afx_msg void OnBnClickedButton2()

CString m_dir_str

afx_msg void OnNMClickTreeFile(NMHDR *pNMHDR, LRESULT *pResult)

}

// TreeCtrlTestDlg.cpp : 实现文件

//

#include "stdafx.h"

#include "TreeCtrlTest.h"

#include "TreeCtrlTestDlg.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// 用于应用程序“关于”菜单项的 CAboutDlg 对话框

class CAboutDlg : public CDialog

{

public:

CAboutDlg()

// 对话框数据

enum { IDD = IDD_ABOUTBOX }

protected:

virtual void DoDataExchange(CDataExchange* pDX) // DDX/DDV 支持

// 实现

protected:

DECLARE_MESSAGE_MAP()

}

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX)

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

END_MESSAGE_MAP()

// CTreeCtrlTestDlg 对话框

CTreeCtrlTestDlg::CTreeCtrlTestDlg(CWnd* pParent /*=NULL*/)

: CDialog(CTreeCtrlTestDlg::IDD, pParent)

, m_dir_str(_T(""))

{

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME)

}

void CTreeCtrlTestDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX)

DDX_Control(pDX, IDC_TREE_FILE, m_tree)

DDX_Control(pDX, IDC_LIST1, m_name_lst)

DDX_Text(pDX, IDC_DIR_STR, m_dir_str)

}

BEGIN_MESSAGE_MAP(CTreeCtrlTestDlg, CDialog)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

//}}AFX_MSG_MAP

ON_NOTIFY(NM_DBLCLK, IDC_TREE_FILE, &CTreeCtrlTestDlg::OnNMDblclkTreeFile)

ON_BN_CLICKED(IDC_BUTTON1, &CTreeCtrlTestDlg::OnBnClickedButton1)

ON_BN_CLICKED(IDC_BUTTON2, &CTreeCtrlTestDlg::OnBnClickedButton2)

ON_NOTIFY(NM_CLICK, IDC_TREE_FILE, &CTreeCtrlTestDlg::OnNMClickTreeFile)

END_MESSAGE_MAP()

// CTreeCtrlTestDlg 消息处理程序

BOOL CTreeCtrlTestDlg::OnInitDialog()

{

CDialog::OnInitDialog()

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。

ASSERT((IDM_ABOUTBOX &0xFFF0) == IDM_ABOUTBOX)

ASSERT(IDM_ABOUTBOX <0xF000)

CMenu* pSysMenu = GetSystemMenu(FALSE)

if (pSysMenu != NULL)

{

CString strAboutMenu

strAboutMenu.LoadString(IDS_ABOUTBOX)

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR)

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu)

}

}

// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动

// 执行此 *** 作

SetIcon(m_hIcon, TRUE) // 设置大图标

SetIcon(m_hIcon, FALSE) // 设置小图标

// TODO: 在此添加额外的初始化代码

/*TVINSERTSTRUCT tvInsert

tvInsert.hParent = NULL

tvInsert.hInsertAfter = NULL

tvInsert.item.mask = TVIF_TEXT

tvInsert.item.pszText = TEXT("United States")

HTREEITEM hCountry = m_tree.InsertItem(&tvInsert)

// Insert subitems of that root. Pennsylvania is

// a state in the United States, so its item will be a child

// of the United States item. We won't set any image or states,

// so we supply only the TVIF_TEXT mask flag. This

// override provides nearly complete control over the

// insertion operation without the tedium of initializing

// a structure. If you're going to add lots of items

// to a tree, you might prefer the structure override

// as it affords you a performance win by allowing you

// to initialize some fields of the structure only once,

// outside of your insertion loop.

HTREEITEM hPA = m_tree.InsertItem(TVIF_TEXT,

TEXT("Pennsylvania"), 0, 0, 0, 0, 0, hCountry, NULL)

// Insert the "Washington" item and assure that it is

// inserted after the "Pennsylvania" item. This override is

// more appropriate for conveniently inserting items with

// images.

HTREEITEM hWA = m_tree.InsertItem(_T("Washington"),

0, 0, hCountry, hPA)

// We'll add some cities under each of the states.

// The override used here is most appropriate

// for inserting text-only items.

m_tree.InsertItem(TEXT("Pittsburgh"), hPA, TVI_SORT)

m_tree.InsertItem(TEXT("Harrisburg"), hPA, TVI_SORT)

m_tree.InsertItem(TEXT("Altoona"), hPA, TVI_SORT)

m_tree.InsertItem(TEXT("Seattle"), hWA, TVI_SORT)

m_tree.InsertItem(TEXT("Kalaloch"), hWA, TVI_SORT)

m_tree.InsertItem(TEXT("Yakima"), hWA, TVI_SORT)*/

m_ImageList.Create(16,16,ILC_COLOR32|ILC_MASK,0,0)//图形列表

//关联树形控件与图标控件

m_tree.SetImageList(&m_ImageList,TVSIL_NORMAL)

m_tree.ModifyStyle(0L,TVS_HASLINES|TVS_LINESATROOT)

size_t alldriver=::GetLogicalDriveStrings(0,NULL)//获得逻辑驱动器字串长度

TCHAR *driverstr=NULL

driverstr=new TCHAR[alldriver+sizeof(TCHAR)]

if(GetLogicalDriveStrings(alldriver,driverstr)!=alldriver-1)//获得逻辑驱动器字串

{

return FALSE

}

TCHAR *pdriverstr=driverstr

size_t driversize=wcslen(pdriverstr)

HTREEITEM disktree

SHFILEINFO fileinfo

memset(&fileinfo,0,sizeof(SHFILEINFO))

while(driversize>0)

{

//用盘符获得驱动器类型

UINT tType=::GetDriveType(pdriverstr)

//用盘符得到驱动器信息

SHGetFileInfo(pdriverstr,0,&fileinfo,sizeof(SHFILEINFO),SHGFI_ICON)

//判断驱动器类型

if(tType!=DRIVE_REMOVABLE&&tType!=DRIVE_CDROM )

{

//把图标加入图形控件列表

int imindex=m_ImageList.Add(fileinfo.hIcon)

//增加树形控件列表节点

disktree=m_tree.InsertItem(pdriverstr,imindex,imindex,TVI_ROOT,TVI_LAST)

}

pdriverstr+=driversize+1

driversize=wcslen(pdriverstr)

}

return TRUE // 除非将焦点设置到控件,否则返回 TRUE

}

void CTreeCtrlTestDlg::OnSysCommand(UINT nID, LPARAM lParam)

{

if ((nID &0xFFF0) == IDM_ABOUTBOX)

{

CAboutDlg dlgAbout

dlgAbout.DoModal()

}

else

{

CDialog::OnSysCommand(nID, lParam)

}

}

// 如果向对话框添加最小化按钮,则需要下面的代码

// 来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,

// 这将由框架自动完成。

void CTreeCtrlTestDlg::OnPaint()

{

if (IsIconic())

{

CPaintDC dc(this)// 用于绘制的设备上下文

SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0)

// 使图标在工作区矩形中居中

int cxIcon = GetSystemMetrics(SM_CXICON)

int cyIcon = GetSystemMetrics(SM_CYICON)

CRect rect

GetClientRect(&rect)

int x = (rect.Width() - cxIcon + 1) / 2

int y = (rect.Height() - cyIcon + 1) / 2

// 绘制图标

dc.DrawIcon(x, y, m_hIcon)

}

else

{

CDialog::OnPaint()

}

}

//当用户拖动最小化窗口时系统调用此函数取得光标

//显示。

HCURSOR CTreeCtrlTestDlg::OnQueryDragIcon()

{

return static_cast<HCURSOR>(m_hIcon)

}

void CTreeCtrlTestDlg::OnNMDblclkTreeFile(NMHDR *pNMHDR, LRESULT *pResult)

{

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

CFileFind filefd

HTREEITEM parent

//当前选中节点

HTREEITEM item=m_tree.GetSelectedItem()

//是否有字节点 可用ItemHasChildren(hmyItem)判断

HTREEITEM h=m_tree.GetChildItem(item)

//如果已经有根节点,说明遍历过了,不再遍历

if(h)

{

return

}

parent =item

//得到当前节点的名字串

CString rootstr=m_tree.GetItemText(item)

CString temp

CString lstr

if(rootstr.Find(TEXT("\\"))==2)//判断是否是盘根目录

{

lstr.Format(TEXT("%s*.*"),rootstr)

}

else

{

//非根目录要重组查找字串

CString strparent

while(1)

{

parent=m_tree.GetParentItem(parent)

strparent=m_tree.GetItemText(parent)

if(strparent.Find(TEXT("\\"))==2)

{

break

}

temp+=strparent

temp+=TEXT("\\")

}

CString root=m_tree.GetItemText(parent)

lstr.Format(TEXT("%s%s%s\\*.*"),root,temp,rootstr)

}

//遍历文件

SHFILEINFO fileinfo

BOOL bfind=filefd.FindFile(lstr)

while(bfind)

{

bfind=filefd.FindNextFile()

CString filepath

//是目录,并且 不是 .和..文件夹

if(filefd.IsDirectory() &&!filefd.IsDots())

{

//文件图标信息

SHGetFileInfo(filefd.GetFilePath(),0,&fileinfo,sizeof(SHFILEINFO),SHGFI_ICON)

//加入到图标列表

int imindex=m_ImageList.Add(fileinfo.hIcon)

//加入到树形控件中

m_tree.InsertItem(filefd.GetFileName(),imindex,imindex,item)

}

}

*pResult = 0

}

void CTreeCtrlTestDlg::OnBnClickedButton1()

{

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

CString StrDisktype

switch( ::GetDriveType(TEXT("G:")) )

{

case DRIVE_REMOVABLE:

StrDisktype=TEXT("软驱")

break

case DRIVE_FIXED:

StrDisktype=TEXT("固定硬盘")

break

case DRIVE_REMOTE:

StrDisktype=TEXT("网络驱动器")

break

case DRIVE_CDROM:

StrDisktype=TEXT("光驱")

break

case DRIVE_RAMDISK:

StrDisktype=TEXT("RAM驱动器")

break

default:

StrDisktype=TEXT("未知")

break

}

MessageBox(TEXT("G:盘为:")+StrDisktype,TEXT("信息提示"),MB_OK)

}

void CTreeCtrlTestDlg::OnBnClickedButton2()

{

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

m_name_lst.ResetContent()

HTREEITEM hChild

CString Str

//HTREEITEM node=m_tree.GetRootItem()

HTREEITEM node=m_tree.GetSelectedItem()

if(node)

{

Str=m_tree.GetItemText(node)

m_name_lst.AddString(Str)

OutTreeToList(node)

}

}

CString CTreeCtrlTestDlg::GetSelectedDir()

{

CString Str

//HTREEITEM node2=m_tree.GetSelectedItem()//用这个不稳定

CPoint pt

GetCursorPos(&pt)

m_tree.ScreenToClient(&pt)

HTREEITEM node2 = m_tree.HitTest(pt)//下当于得到当前选中项

Str=m_tree.GetItemText(node2)

node2=m_tree.GetParentItem(node2)

while(node2!=NULL)

{

CString tStr

tStr=m_tree.GetItemText(node2)

if(tStr.Find('\\')>=0)

{

Str=tStr+Str

}

else

{

Str=tStr+TEXT("\\")+Str

}

node2=m_tree.GetParentItem(node2)

}

return Str

}

void CTreeCtrlTestDlg::OutTreeToList(HTREEITEM node)

{

HTREEITEM child

CString Str

node=m_tree.GetChildItem(node)

if(node)

{

while(node)

{

Str=m_tree.GetItemText(node)

m_name_lst.AddString(Str)

child=node

OutTreeToList(child)//递归调用

node=m_tree.GetNextItem(node,TVGN_NEXT)

}

}

}

void CTreeCtrlTestDlg::OnNMClickTreeFile(NMHDR *pNMHDR, LRESULT *pResult)

{

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

m_dir_str=GetSelectedDir()

m_name_lst.ResetContent()

CFileFind fFind

CString Str

Str=m_dir_str+TEXT("\\*.wdf")

BOOL bMore=fFind.FindFile(Str)

while(bMore)

{

bMore=fFind.FindNextFile()

m_name_lst.AddString(fFind.GetFileName())

}

UpdateData(FALSE)

/*CPoint pt

GetCursorPos(&pt)

m_tree.ScreenToClient(&pt)

HTREEITEM node = m_tree.HitTest(pt)

m_dir_str=m_tree.GetItemText(node)

UpdateData(FALSE)*/

*pResult = 0

}

以上代码是用树形控件来显示磁盘文件,你拿去研究下吧


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/bake/7837695.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-10
下一篇2023-04-10

发表评论

登录后才能评论

评论列表(0条)

    保存