이전 섹션에서는 트리 컨트롤 트리 컨트롤의 소개, 알림 메시지 및 관련 데이터 구조에 대해 설명했습니다. 이 섹션에서는 CTreeCtrl 클래스의 주요 멤버 기능인 트리 컨트롤 생성을 포함하여 후반부에 대해 계속 설명합니다. 및 적용 사례.
트리 제어 생성
MFC는 트리 제어의 모든 작업을 캡슐화하는 트리 제어용 CTreeCtrl 클래스를 제공합니다.
트리 컨트롤을 만드는 방법에는 두 가지가 있습니다. 하나는 트리 컨트롤을 대화 상자 템플릿으로 직접 드래그하는 것이고, 다른 하나는 CTreeCtrl 클래스의 멤버 만들기 기능을 통해 만드는 것입니다. 다음에서는 주로 후자에 대해 이야기한다.
CTreeCtrl 클래스의 Create 멤버 함수의 프로토타입은 다음과 같습니다.
virtual BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
이 함수의 프로토타입은 모든 컨트롤의 Create 함수와 유사합니다. 앞서 언급한 수업. dwStyle은 트리 컨트롤 스타일의 조합을 지정하고, ect는 트리 컨트롤 창의 위치와 크기를 지정하고, pParentWnd는 트리 컨트롤의 부모 창에 대한 포인터이고, nID는 트리 컨트롤의 ID를 지정합니다. 다음으로 트리 컨트롤의 주요 스타일과 의미에 대해 주로 설명하겠습니다.
TVS_DISABLEDRAGDROP: 트리 제어에서 TVN_BEGINDRAG 알림 메시지를 보내는 것을 금지합니다. 즉, 드래그 작업이 지원되지 않습니다.
TVS_EDITLABELS: 사용자가 노드의 레이블 텍스트를 편집할 수 있습니다.
TVS_HASBUTTONS: 표시 항목을 확장할 수 있는지 여부를 나타내는 " +" 또는 "-" 작은 상자
TVS_HASLINES: 상위 노드와 하위 노드를 연결하여 트리 구조를 보다 명확하게 표시합니다
TVS_LINESATROOT: 루트 노드에 선을 연결합니다
TVS_SHOWSEALWAYS: 컨트롤이 입력 포커스를 잃어도 항목의 선택 상태는 계속 표시됩니다
마찬가지로 트리 컨트롤을 동적으로 생성할 때 위의 사항을 지정할 수 있는 것 외에도 스타일 조합 외에도 일반적으로 WS_CHILD 및 WS_VISIBLE 스타일이 지정됩니다.
트리 컨트롤을 대화 상자 템플릿으로 직접 드래그하여 트리 컨트롤을 생성하는 경우 트리 컨트롤의 속성 페이지에서 위 스타일에 해당하는 스타일을 설정할 수 있습니다. Has Lines는 TVS_HASLINES 스타일에 해당합니다.
CTreeCtrl 클래스의 주요 멤버 함수
CImageList* SetImageList(CImageList * pImageList,int nImageListType);
트리 노드가 아이콘을 표시해야 하는 경우 먼저 CImageList 클래스의 개체를 생성하고 여러 개체를 추가하면 이미지가 이미지 시퀀스를 형성한 다음 SetImageList 함수를 호출하여 트리 컨트롤에 대한 이미지 시퀀스를 설정합니다. InsertItem을 사용하여 노드를 삽입할 때 이미지 시퀀스에 원하는 이미지의 인덱스를 전달하면 됩니다. 이는 이후 예제에서 설명됩니다. pImageList 매개변수는 이미지 시퀀스 클래스 CImageList의 개체에 대한 포인터입니다. NULL인 경우 트리 컨트롤의 모든 이미지가 삭제됩니다. nImageListType 매개변수는 TVSIL_NORMAL(일반 이미지 시퀀스) 또는 TVSIL_STATE(이미지를 사용하여 노드 상태를 나타내는 상태 이미지 시퀀스)일 수 있는 이미지 시퀀스 유형을 지정합니다.
UINT GetCount( ) const;
트리 컨트롤의 노드 수를 가져옵니다.
DWORD_PTR GetItemData(HTREEITEM hItem) const;
트리 컨트롤에서 지정된 노드의 추가 32비트 데이터를 가져옵니다. 매개변수 hItem은 지정된 트리 노드의 핸들입니다.
BOOL SetItemData(HTREEITEM hItem,DWORD_PTR dwData);
트리 컨트롤에서 지정된 노드에 대한 추가 32비트 데이터를 설정합니다. hItem 파라미터는 위와 같으며, dwData 는 설정할 32비트 데이터입니다.
CString GetItemText(HTREEITEM hItem) const;
트리 컨트롤에서 지정된 노드의 레이블 텍스트를 가져옵니다. hItem 매개변수는 위와 동일합니다. 반환 값은 레이블 텍스트가 포함된 문자열입니다.
BOOL SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);
트리 컨트롤의 지정된 노드에 대한 레이블 텍스트를 설정합니다. 매개변수 hItem은 위와 동일하며 lpszItem은 레이블 텍스트가 포함된 문자열에 대한 포인터입니다.
HTREEITEM GetNextSiblingItem(HTREEITEM hItem) const;
트리 컨트롤에서 지정된 노드의 다음 형제 노드를 가져옵니다. hItem 매개변수는 위와 동일합니다. 반환 값은 다음 형제 노드에 대한 핸들입니다.
HTREEITEM GetPrevSiblingItem(HTREEITEM hItem) const;
트리 컨트롤에서 지정된 노드의 이전 형제 노드를 가져옵니다. hItem 매개변수는 위와 동일합니다. 반환 값은 이전 형제 노드의 핸들입니다.
HTREEITEM GetParentItem(HTREEITEM hItem) const;
트리 컨트롤에서 지정된 노드의 상위 노드를 가져옵니다. hItem 매개변수는 위와 동일합니다. 반환 값은 상위 노드에 대한 핸들입니다.
HTREEITEM GetRootItem( ) const;
트리 컨트롤의 루트 노드 핸들을 가져옵니다.
HTREEITEM GetSelectedItem( ) const;
트리 컨트롤의 현재 선택된 노드의 핸들을 가져옵니다.
BOOL DeleteAllItems( );
트리 컨트롤의 모든 노드를 삭제합니다. 삭제에 성공하면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환합니다.
BOOL DeleteItem(HTREEITEM hItem);
트리 컨트롤에서 노드를 삭제합니다. hItem 매개변수는 삭제할 노드의 핸들입니다. 삭제에 성공하면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환합니다.
HTREEITEM InsertItem(LPCTSTR lpszItem,int nImage,int nSelectedImage,HTREEITEM hParent = TVI_ROOT,HTREEITEM hInsertAfter = TVI_LAST);
트리 컨트롤에 새 노드를 삽입합니다. lpszItem 매개변수는 새 노드의 레이블 텍스트 문자열에 대한 포인터이고, nImage 매개변수는 트리 제어 이미지 시퀀스에서 새 노드 아이콘의 인덱스이며, nSelectedImage 매개변수는 이미지 시퀀스에서 새 노드 아이콘의 인덱스입니다. hParent 매개변수는 삽입된 노드의 상위 노드 핸들입니다. hInsertAfter 매개변수는 새 노드의 이전 노드 핸들입니다. 즉, 새 노드는 hInsertAfter 노드 뒤에 삽입됩니다.
BOOL SelectItem(HTREEITEM hItem);
지정된 트리 노드를 선택합니다. hItem 매개변수는 선택할 노드의 핸들입니다. 성공하면 TRUE를 반환하고, 그렇지 않으면 FALSE를 반환합니다.
트리 컨트롤 적용 예
마지막으로 CListCtrl 클래스의 여러 멤버 함수와 트리 컨트롤 알림 메시지를 사용하는 방법을 설명하기 위한 간단한 예제를 작성하겠습니다.
此实例实现的功能:在一个树形控件中显示网站的简单结构分层,共有三层,分别为网站、各个分类和文章。用鼠标左键单击改变选中节点后,将选中节点的文本显示到编辑框中。另外,还要实现一个常见的效果,就是鼠标划过除根节点外的某个树节点时,显示相应的Tip提示信息。下面是具体实现步骤:
1. 创建一个基于对话框的MFC工程,名称设置为“Example31”。
2. 在自动生成的对话框模板IDD_EXAMPLE31_DIALOG中,删除“TODO: Place dialog controls here.”静态文本框、“OK”按钮和“Cancel”按钮。添加一个Tree Control控件,ID设置为IDC_WEB_TREE,属性Has Buttons、Has Lines和Lines At Root都设为True,为了在鼠标划过某个节点时显示提示信息还需要将Info Tip属性设为True。再添加一个静态文本框和一个编辑框,静态文本框的Caption属性设为“您选择的节点:”,编辑框的ID设为IDC_ITEM_SEL_EDIT,Read Only属性设为True。此时的对话框模板如下图:
3. 导入需要为树形控件的节点添加的图标。在这里找了三个32x32的Icon图标,保存到工程的res目录下。然后在Resource View资源视图中,右键点击Icon节点,在右键菜单中选择“Add Resource...”,弹出“Add Resource”对话框,再从左边“Resource type”列表中选择“Icon”,点击右边的“Import...”按钮,就可以选择三个图标文件进行导入了。导入成功后,分别修改它们ID为IDI_WEB_ICON、IDI_CATALOG_ICON和IDI_ARTICLE_ICON。
4. 为树形控件IDC_WEB_TREE添加CTreeCtrl类型的控件变量m_webTree。并在Example31Dlg.h文件中为CExample31Dlg类添加成员对象:CImageList m_imageList;。
5. 在对话框初始化时,我们在树形控件中添加网站的树形结构,那么需要修改CExample31Dlg::OnInitDialog()函数为:
BOOL CExample31Dlg::OnInitDialog() { CDialogEx::OnInitDialog(); ......略 // TODO: Add extra initialization here HICON hIcon[3]; // 图标句柄数组 HTREEITEM hRoot; // 树的根节点的句柄 HTREEITEM hCataItem; // 可表示任一分类节点的句柄 HTREEITEM hArtItem; // 可表示任一文章节点的句柄 // 加载三个图标,并将它们的句柄保存到数组 hIcon[0] = theApp.LoadIcon(IDI_WEB_ICON); hIcon[1] = theApp.LoadIcon(IDI_CATALOG_ICON); hIcon[2] = theApp.LoadIcon(IDI_ARTICLE_ICON); // 创建图像序列CImageList对象 m_imageList.Create(32, 32, ILC_COLOR32, 3, 3); // 将三个图标添加到图像序列 for (int i=0; i<3; i++) { m_imageList.Add(hIcon[i]); } // 为树形控件设置图像序列 m_webTree.SetImageList(&m_imageList, TVSIL_NORMAL); // 插入根节点 hRoot = m_webTree.InsertItem(_T("鸡啄米"), 0, 0); // 在根节点下插入子节点 hCataItem = m_webTree.InsertItem(_T("IT互联网"), 1, 1, hRoot, TVI_LAST); // 为“IT互联网”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hCataItem, 1); // 在“IT互联网”节点下插入子节点 hArtItem = m_webTree.InsertItem(_T("百度文章1"), 2, 2, hCataItem, TVI_LAST); // 为“百度文章1”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 2); // 在“IT互联网”节点下插入另一子节点 hArtItem = m_webTree.InsertItem(_T("谷歌文章2"), 2, 2, hCataItem, TVI_LAST); // 为“谷歌文章2”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 3); // 在根节点下插入第二个子节点 hCataItem = m_webTree.InsertItem(_T("数码生活"), 1, 1, hRoot, TVI_LAST); // 为“数码生活”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hCataItem, 4); // 在“数码生活”节点下插入子节点 hArtItem = m_webTree.InsertItem(_T("智能手机文章1"), 2, 2, hCataItem, TVI_LAST); // 为“智能手机文章1”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 5); // 在“数码生活”节点下插入另一子节点 hArtItem = m_webTree.InsertItem(_T("平板电脑文章2"), 2, 2, hCataItem, TVI_LAST); // 为“平板电脑文章2”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 6); // 在根节点下插入第三个子节点 hCataItem = m_webTree.InsertItem(_T("软件开发"), 1, 1, hRoot, TVI_LAST); // 为“软件开发”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hCataItem, 7); // 在“软件开发”节点下插入子节点 hArtItem = m_webTree.InsertItem(_T("C++编程入门系列1"), 2, 2, hCataItem, TVI_LAST); // 为“C++编程入门系列1”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 8); // 在“软件开发”节点下插入另一子节点 hArtItem = m_webTree.InsertItem(_T("VS2010/MFC编程入门2"), 2, 2, hCataItem, TVI_LAST); // 为“VS2010/MFC编程入门2”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 9); // 在根节点下插入第四个子节点 hCataItem = m_webTree.InsertItem(_T("娱乐休闲"), 1, 1, hRoot, TVI_LAST); // 为“娱乐休闲”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hCataItem, 10); // 在“娱乐休闲”节点下插入子节点 hArtItem = m_webTree.InsertItem(_T("玛雅文明文章1"), 2, 2, hCataItem, TVI_LAST); // 为“玛雅文明文章1”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 11); // 在“娱乐休闲”节点下插入另一子节点 hArtItem = m_webTree.InsertItem(_T("IT笑话2"), 2, 2, hCataItem, TVI_LAST); // 为“IT笑话2”节点添加附加的编号数据,在鼠标划过该节点时显示 m_webTree.SetItemData(hArtItem, 12); return TRUE; // return TRUE unless you set the focus to a control }
6. 我们希望在选中节点改变时,将最新的选择项实时显示到编辑框中,那么可以响应TVN_SELCHANGED通知消息。为树形控件IDC_WEB_TREE的通知消息TVN_SELCHANGED添加消息处理函数CExample31Dlg::OnTvnSelchangedWebTree,并修改函数体如下:
void CExample31Dlg::OnTvnSelchangedWebTree(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR); // TODO: Add your control notification handler code here *pResult = 0; CString strText; // 树节点的标签文本字符串 // 获取当前选中节点的句柄 HTREEITEM hItem = m_webTree.GetSelectedItem(); // 获取选中节点的标签文本字符串 strText = m_webTree.GetItemText(hItem); // 将字符串显示到编辑框中 SetDlgItemText(IDC_ITEM_SEL_EDIT, strText); }
7. 还有一个功能需要实现,那就是鼠标划过除根节点外的某个树节点时,显示相应的Tip提示信息,本实例中提示信息为节点的编号。这需要响应TVN_GETINFOTIP通知消息。为树形控件IDC_WEB_TREE的通知消息TVN_GETINFOTIP添加消息处理函数CExample31Dlg::OnTvnGetInfoTipWebTree,并修改函数体如下:
void CExample31Dlg::OnTvnGetInfoTipWebTree(NMHDR *pNMHDR, LRESULT *pResult) { LPNMTVGETINFOTIP pGetInfoTip = reinterpret_cast<LPNMTVGETINFOTIP>(pNMHDR); // TODO: Add your control notification handler code here *pResult = 0; NMTVGETINFOTIP* pTVTipInfo = (NMTVGETINFOTIP*)pNMHDR; // 将传入的pNMHDR转换为NMTVGETINFOTIP指针类型 HTREEITEM hRoot = m_webTree.GetRootItem(); // 获取树的根节点 CString strText; // 每个树节点的提示信息 if (pTVTipInfo->hItem == hRoot) { // 如果鼠标划过的节点是根节点,则提示信息为空 strText = _T(""); } else { // 如果鼠标划过的节点不是根节点,则将该节点的附加32位数据格式化为字符串 strText.Format(_T("%d"), pTVTipInfo->lParam); } // 将strText字符串拷贝到pTVTipInfo结构体变量的pszText成员中,这样就能显示内容为strText的提示信息 wcscpy(pTVTipInfo->pszText, strText); }
8. 运行程序,弹出结果对话框。效果如下图:
树形控件的知识就讲到这里了,相比之前的控件可能稍有复杂。不过用的多了,就会觉得得心应手了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。
更多VS2010/MFC编程(常用控件:树形控件Tree Control控件创建h和实例)相关文章请关注PHP中文网!