VC中CTreeView控件的使用
.NET4.0 使用GridView控件

4.0 使用GridView控件在Visual Studio 2010中,用户可以采用可视化的方式为页面插入GridView控件,也可以通过代码的方式插入GridView控件。
1.添加GridView控件在页面的【设计】视图中选择任意一个段落,然后即可从【工具箱】中选择【GridView控件】,将其插入到页面中,如图10-2所示。
图10-2 插入的GridView控件2.更改控件外观通过可视化的方法,可以方便地改变GridView控件的外观,为其应用各种模板样式。
选中GridView控件或将鼠标滑至GridView控件上方,然后即可单击控件右上角的【GridView 任务】按钮,如图10-3所示。
图10-3 单击任务按钮在弹出的【GridView 任务】菜单中执行【自动套用格式】命令,如图10-4所示。
图10-4 执行【自动套用格式】命令然后,即可在弹出的【自动套用格式】对话框中选择GridView控件的格式架构,如图10-5所示。
图10-5 选择套用的格式3.添加数据源数据绑定控件的最大特点就是允许方便地与数据库中的数据进行绑定,快速显示数据内容。
用同样的方式选择GridView控件,单击其右上角的【GridView 任务】按钮,打开【GridView 任务】菜单。
如果当前的项目已绑定了数据源,则在该菜单中【选择数据源】的菜单中即可显示这些数据源。
否则,开发者可以在【选择数据源】的菜单中选择“<新建数据源>”选项,连接一个新的数据源,如图10-6所示。
图10-6 新建数据源在弹出的【数据源配置向导】对话框中选择对应的数据源类型,然后即可设置数据源的编号索引,单击【确定】按钮,如图10-7所示。
图10-7 选择数据源在弹出的【配置数据源】对话框中单击【新建连接】按钮,建立一个新的数据源连接,如图10-8所示。
图10-8 新建数据源连接在弹出的【添加连接】对话框中,输入数据库服务器的名称,并选择服务器安全的验证方式,如图10-9所示。
C#Winform中treeView控件使用总结

C#Winform中treeView控件使⽤总结1.如何展开结点时改变图标(注意:不是选中时)要在⽬录中使⽤图标⾸先要加⼊⼀个控件ImageList(命名为imageList1),然后可以按图⽚的index或名称引⽤图⽚.然后需要在TreeView控件的ImageList属性中指向imageList1.TreeView有两个属性:SelectImageIndex:选中该结点时显⽰的图⽚的索引ImageIndex:未选中该结点时显⽰的图⽚的索引可以实现的效果是,选中某个结点时该结点的图⽚进⾏改变,如果我们的⽬标也是如此,万事已经⼤吉了.但我希望的效果是:展开某个结点时该结点的图⽚改变(如显⽰为打开的盒⼦),折叠时该结点的图⽚改变(如包装好的盒⼦).直接使⽤属性⽆法实现该效果.实现原理是:展开某个结点时将SelectImageIndex和ImageIndex统统指向打开盒⼦的图⽚折叠某个结点时将SelectImageIndex和ImageIndex统统指向包装盒⼦的图⽚⾃然需要⽤到两个事件:TreeView的AfterExpand和AfterCollapse事件private void treeView1_AfterExpand(object sender, TreeViewEventArgs e){e.Node.ImageIndex = 1; //指向展开的图标e.Node.SelectedImageIndex = 1;//指向展开的图标}private void treeView1_AfterCollapse(object sender, TreeViewEventArgs e){e.Node.ImageIndex = 0; //指向关闭的图标e.Node.SelectedImageIndex = 0;//指向关闭的图标}PS:当对某个结点的属性ImageIndex和SelectedImageIndex赋值后,向它添加的⼦结点如未指定该属性,似乎会沿⽤⽗结点的属性,所以通常我会对⼦结点单独设置该值 .2.重命名结点名称重命名结点的功能很好实现,只要将TreeView的LabelEdit属性改为True即可.选中某个结点后再单击(提⽰:间隔短的话算做双击),然后结点名称变成可以编辑状态,修改⽂本后即可完成.但我的程序设计是这样的:结点的名称会在后⾯⾃动加⼊⼦结点的数量(注:树的深度为2).效果如图:这样就会带来⿇烦(我们总是擅长给⾃⼰制造⿇烦?),因为我在重命名的时候并不想在编辑状态下名称中包含后⾯数字(它只在显⽰的时候出现).假设我希望将"新建分组"重命名为"我的分组",我希望进⼊编辑状态时,名称为"新建分组",修改后的名称为"我的分组",退出编辑状态时显⽰为"我的分组[1]".那实际的逻辑就是这样:1.进⼊编辑状态时将名称的数字去掉2.退出编辑状态时将名称加⼊数字.so easy!那如何获取进⼊编辑状态时的事件呢?我没有找到,或者可能就没有,但我们可以在结点的单击事件中进⾏捕获,再判断结点的⽂本是否为选中状态private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e){if (e.Node.IsSelected){e.Node.Text = "替换掉数字,请⾃⼰实现";}}然后捕捉编辑结束事件,实现加数字的⽅法private void treeView1_AfterLabelEdit(object sender, NodeLabelEditEventArgs e){if (!e.CancelEdit){ e.Node.Text=bel+string.Format(" [{0}]", e.Node.Nodes.Count.ToString()); e.CancelEdit = true; //注意这⾥ } }以下是重点:在上⾯的代码没加⼊ e.CancelEdit = true 之前,会有⼀个奇怪的现象,当我将结点的名称修改后不会出现后⾯的数字.假设我修改的顺序是这样:将A->B->B很有趣的现象:当从A变成B时后⾯的数字不会出现,当从B变成B时(实际没有发⾏变动),数字⼜出现了.跟踪了很久的程序加上了很长的时间分析,终于明⽩原因了.当我们修改结点的⽂本时是这样的⼀个顺序:结点进⼊编辑状态->触发BeforeLabelEdit事件->触发AterLabelEdit事件->刷新界⾯⽤新值代替旧值.在 treeView1_AfterLabelEdit事件的参数中有两个属性:bel 修改之后的值(新值,可能为null,只读) 和s.Node.Text 修改之前的值(旧值,可读写).仔细分析后可以理解上⾯的现象:当从A->修改为B时,我们的代码对e.Node.Text(旧值)进⾏了赋值加⼊数字,最后程序刷新界⾯时会⽤新值代替旧值.这时我们加⼊的数字被新值Label覆盖了(代码做了⽆⽤功)⽽我们从B->修改为B时,由于新值(Label)为null,则系统不会执⾏最后⼀步,所以我们添加的数字得到了保留.最终的做法,就是将参数的e.CancelEdit改为true,告诉系统我们就当我们没有编辑过吧.这样系统就不会执⾏最后⼀步了,我们代码的修改得到了保留.。
【转】VC常用控件的使用

【转】VC常⽤控件的使⽤4.1.1控件基础知识控件(Control)是⼀种⼦窗⼝,应⽤程序⽤它来与其他窗⼝⼀起完成简单地输⼊输出操作。
这些控件各⾃有不同的⽤途,但总的来说分成两⼤类:⼀类只⽤于输出,另⼀类⽤于输⼊和输出,具体的功能如表4-1所⽰。
表4-1 MFC常⽤控件控件名称⽤途MFC对应的类静态⽂本框⼀般显⽰⼀段固定不变的⽂字CStatic图⽚控件显⽰图形CButton群组控件将⼀组控件圈起来,这样看起来美观得多CEdit编辑控件⽤户可以任意输⼊各种⽂本,同时可以查看已有内容CSpinButtonCtrl数字滚选按钮提供两个⽅向相反的箭头按钮,⽤来正向或反向逐次改变选项按键按钮⽤来产⽣某些命令CButton复选框复选框的外形是⼀个空⼼⽅框,当它被选中时,复选框中就加上了⼀个“√”单选框单选按钮的外形是⼀个图圈,当它被选中时,按钮中⼼会出现⼀个⿊点。
⼀组单选按钮最多只能有⼀个被选上CListBox列表框显⽰⼀个列表让⽤户选择⼀项或多项CComboBox组合框将列表框和编辑框有机的结合起来,⽤户可以选择已有的项,也可以增加新项CScrollBar滚动条滚动条可以是⼀个单独的控件,也可以是窗⼝的⼀部分。
当滚动条作为其他窗⼝的⼀部分时,由系统⾃动处理。
按滚动条的⾛向,可分为竖直滚动条和⽔平滚动条两种类型,其组成部分是⼀样的,两端是箭头按钮,中间是⼀个可沿滚动条移动的滚动块进度条显⽰任务完成的进度情况CProgressCtrlCSliderCtrl滑标控件与滚动条类似,但滑槽两侧可标上刻度树状控件显⽰树状分层结构CTreeCtrl多功能编辑框编辑框的加强版,功能更加全⾯CRichEditCtrl4.1.4控件的公共函数所有的控件都继承于窗⼝类(CWnd),所以我们⽤CWnd类的函数来控制控件,CWnd类与控件有关的函数如下:BOOL EnableWindow( BOOL bEnable = TRUE );此函数⽤于禁⽤(或启⽤)窗⼝。
VC中如何使用CTreeCtrl控件-春天的事业-草根IT工作者谢春业的博客,探讨...

VC中如何使用CTreeCtrl控件-春天的事业-草根IT工作者谢春业的博客,探讨...1.取得或设定项目的信息.BOOL CTreeCtrl::GetItem(TV_ITEM* pItem);BOOL CTreeCtrl::SetItem(TV_ITEM* pItem);BOOL CTreeCtrl::SetItem(HTREEITEM hItem,UINTnMask,LPCTSTR lpszItem,int Image,int nSelectedImage,UINT nState,UINT nStateMask,LPARAME lParam);2.取得与设定项目的状态UINT CTreeCtrl::GetItemState(HTREEITEM hItem,UINT sStateMask)const;BOOL CTree Ctrl::SetItemState(HTREEITEM hItem,UINT nState,UINT nStateMask);3.取得与设定项目的图形BOOL CTreeCtrl::GetItemImage(HTREEITEM hItem,int& nImage,int& nSelectedImage)const;BOOL CTreeCtrl::SetItemImage(HTREEITEM hItem,int nImage,int nSelectedImage);4. 取得与设定项目的文本CString CTreeCtrl::GetItemText(HTREEITEM,hItem)const;BOOL CTreeCtrl::SetItemText(HTREEITEM hItem,LPCTSTR lpszItem);5. 查询 CTreeCtrl 中项目的个数UINT CTreeCtrl::GetCount();6.查询hItem 的父项目的句柄HTREEITEM CTreeCtrl::GetparenItem(HTREEITEM hItem);7.查询hItem是否有子项BOOL CTreeCtrl::ItemHasChildren(HTREEITEM hItem);8.取得hItem 第一个子项的句柄HTREEITEM CTreeCtrl::GetChildItem(HTREEITEM hItem);9.查询排在hItem前后的兄弟项HTREEITEM CTreeCtrl::GetPrevSiblingItem(HTREEITEM hItem);HTREEITEM CTreeCtrl::GetNextSiblingItem(HTREEITEM hItem);10.取得选中项的句柄取得根项的句柄HTREEITEM CTreeCtrl::GetSelectedItem();HTREEITEM CTreeCtrl::GetRootItem();HTREEITEM hItem=GetRootItem(); //获取根结点,可能会有多个根结点ItemHasChildren(hParent) //判断结点是否有孩子结点hItem=GetChildItem(hParent); //获取第一个子结点hItem=GetNextSiblingItem(hItem)); //获取下一个兄弟结点结点Expand(hItem,bExpand?TVE_EXPAND:TVE_COLLAPSE);//展开/叠起结点Select(hItem,TVGN_FIRSTVISIBLE); //设置选中结点CString str=GetItemText(hChild); //获取结点字符串信息HTREEITEM hCurrSel = GetSelectedItem(); //获取当前选中结点SelectItem(hNewSel);HTREEITEM hNewSel = HitTest(pt, &nFlags); //判断坐标是否在当前结点范围内HTREEITEMhItem=InsertItem(dlg.m_strItemText,hItemParent); //插入结点。
C++关于CMFCPropertyGridCtrl的使用方法之二(原创)

C++关于CMFCPropertyGridCtrl的使⽤⽅法之⼆(原创)接上⼀节所讲,这⼀节咱们重点讲⼀下CMFCPropertyGridCtrl 所⽀持的数据表格的建⽴过程在上⼀节中,咱们已经了解到了 CMFCPropertyGridCtrl 是要⽤到实例函数:AddProperty()。
现在咱们来具体分析⼀下过程要想建⽴⼀个属性⼀般来讲我们先建⽴⼀个项⽬:如上⼀节中提到的 “概述”项⽬属性。
这个属于的⼀个⼤的特点,就是这个属性并没有⼀个对应的值,也就是说这个也是⼀个属性,但是却不是⽤来表达⼀个具体的属性值,⽽仅是为了表⽰⼀个“组Group”的。
所以,对于属性的创建,有两种构造函数:⼀种是构造⼀个组属性,⼀种是构造⼀个值属性。
先来看构造⼀个组属性CMFCPropertyGridProperty(const CString& strGroupName, DWORD_PTR dwData = 0, BOOL bIsValueList = FALSE);在这个参数列表中第⼀个参数是⼀个字符串值,这是⽤于指定组的名称,也就是组名。
⽤于显⽰⽤的。
所以⼀般情况下,我们来构造⼀个组的时候,只需要指定第⼀个参数就可以了,因为第⼆、三个参数有默认值,具体的参数说明,可以参考下⾯的⽹址:举个例⼦,如下⾯这句话CMFCPropertyGridProperty* pGroup1 = new CMFCPropertyGridProperty(_T("概述"));有了这个组属性后,那们就需要在组属性⾥⾯添加⼀个值属性:值属性的构造函数如下CMFCPropertyGridProperty(const CString& strName, const COleVariant& varValue, LPCTSTR lpszDescr = NULL, DWORD_PTR dwData = 0,LPCTSTR lpszEditMask = NULL, LPCTSTR lpszEditTemplate = NULL, LPCTSTR lpszValidChars = NULL);在这⾥也有很多的参数,我们最关⼼的是前⾯⼏个属性strName :表⽰属性的名称varValue:表⽰属性的值lpszDescr :此属性的描述内容,⽤于在下⽅的描述框内显⽰的描述内容。
VCMFC之ListCtrl控件使用经验总结(转)

VCMFC之ListCtrl控件使用经验总结(转)以下未经说明,listctrl默认view 风格为report相关类及处理函数MFC:CListCtrl类SDK:以“ListView_”开头的一些宏。
如ListView_InsertColumn--------------------------------------------------------------------------------1. CListCtrl 风格LVS_ICON: 为每个item显示大图标LVS_SMALLICON: 为每个item显示小图标LVS_LIST: 显示一列带有小图标的itemLVS_REPORT: 显示item详细资料直观的理解:windows资源管理器,“查看”标签下的“大图标,小图标,列表,详细资料”--------------------------------------------------------------------------------2. 设置listctrl 风格及扩展风格LONG lStyle;lStyle = GetWindowLong(m_list.m_hWnd, GWL_STYLE);//获取当前窗口stylelStyle &= ~LVS_TYPEMASK; //清除显示方式位lStyle |= LVS_REPORT; //设置styleSetWindowLong(m_list.m_hWnd, GWL_STYLE, lStyle);//设置styleDWORD dwStyle = m_list.GetExtendedStyle();dwStyle |= LVS_EX_FULLROWSELECT;//选中某行使整行高亮(只适用与report风格的listctrl)dwStyle |= LVS_EX_GRIDLINES;//网格线(只适用与report风格的listctrl)dwStyle |= LVS_EX_CHECKBOXES;//item前生成checkbox控件m_list.SetExtendedStyle(dwStyle); //设置扩展风格注:listview的style请查阅msdn/library/default.asp?url=/library/ en-us/wceshellui5/html/wce50lrflistviewstyles.asp--------------------------------------------------------------------------------3. 插入数据m_list.InsertColumn( 0, "ID", LVCFMT_LEFT, 40 );//插入列m_list.InsertColumn( 1, "NAME", LVCFMT_LEFT, 50 );int nRow = m_list.InsertItem(0, “11”);//插入行m_list.SetItemText(nRow, 1, “jacky”);//设置数据--------------------------------------------------------------------------------4. 一直选中item选中style中的Show selection always,或者在上面第2点中设置LVS_SHOWSELALWAYS--------------------------------------------------------------------------------5. 选中和取消选中一行int nIndex = 0;//选中m_list.SetItemState(nIndex, LVIS_SELECTED|LVIS_FOCUSED, LVIS_SELECTED|LVIS_FOCUSED);//取消选中m_list.SetItemState(nIndex, 0, LVIS_SELECTED|LVIS_FOCUSED);--------------------------------------------------------------------------------6. 得到listctrl中所有行的checkbox的状态m_list.SetExtendedStyle(LVS_EX_CHECKBOXES);CString str;for(int i=0; i<m_list.GetItemCount(); i++){if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED || m_list.GetCheck(i)){str.Format(_T("第%d行的checkbox为选中状态"), i);AfxMessageBox(str);}}--------------------------------------------------------------------------------7. 得到listctrl中所有选中行的序号方法一:CString str;for(int i=0; i<m_list.GetItemCount(); i++){if( m_list.GetItemState(i, LVIS_SELECTED) == LVIS_SELECTED ) {str.Format(_T("选中了第%d行"), i);AfxMessageBox(str);}}方法二:POSITION pos = m_list.GetFirstSelectedItemPosition();if (pos == NULL)TRACE0("No items were selected!\n");else{while (pos){int nItem = m_list.GetNextSelectedItem(pos);TRACE1("Item %d was selected!\n", nItem);// you could do your own processing on nItem here}}--------------------------------------------------------------------------------8. 得到item的信息TCHAR szBuf[1024];LVITEM lvi;lvi.iItem = nItemIndex;lvi.iSubItem = 0;lvi.mask = LVIF_TEXT;lvi.pszText = szBuf;hTextMax = 1024;m_list.GetItem(&lvi);关于得到设置item的状态,还可以参考msdn文章Q173242: Use Masks to Set/Get Item States in CListCtrl/kb/173242/en-us--------------------------------------------------------------------------------9. 得到listctrl的所有列的header字符串内容LVCOLUMN lvcol;char str[256];int nColNum;CString strColumnName[4];//假如有4列nColNum = 0;lvcol.mask = LVCF_TEXT;lvcol.pszText = str;hTextMax = 256;while(m_list.GetColumn(nColNum, &lvcol)){strColumnName[nColNum] = lvcol.pszText;nColNum++;}--------------------------------------------------------------------------------10. 使listctrl中一项可见,即滚动滚动条m_list.EnsureVisible(i, FALSE);--------------------------------------------------------------------------------11. 得到listctrl列数int nHeadNum = m_list.GetHeaderCtrl()->GetItemCount();--------------------------------------------------------------------------------12. 删除所有列方法一:while ( m_list.DeleteColumn (0))因为你删除了第一列后,后面的列会依次向上移动。
MFCGridCtrl控件_使用说明(中英文)

3.2.2
初使化 GridCtrl 控件..........................................................................................25
3.2.3
设置固定行和列 .................................................................................................26
2.3.1 CGridCtrl 类...............................................................................................................3
2.3.2 CGridCellCheck 类 ....................................................................................................4
3.2.6
设置 ComboBox 列.............................................................................................29
3.2.7
设置行背景颜色和列背景颜色 .........................................................................30
图1 Grid 单元格可以是任何类型,这些类型都是从 CGridCell 派生下来的,基类中定义了 基本的数据存储和编辑操作。扩充的两个类 CgridCellCombo 和 CGridLCellCheck 示范了如 何创建自己的单元格类。
setcontrolvisibility的用法

SetControlVisibility是一个用于设置控件可见性的方法,它通常用于Windows
窗体应用程序中的控件。
该方法允许您在运行时控制控件的可见性,使其可见或隐藏。
以下是SetControlVisibility方法的一般用法:
csharp复制代码
// 假设有一个名为 myControl 的控件
myControl.SetControlVisibility(true); // 显示控件
myControl.SetControlVisibility(false); // 隐藏控件
其中,true表示将控件设置为可见,false表示将控件设置为隐藏。
请注意,SetControlVisibility方法是特定于某些控件库或框架的方法,并不是标准的 .NET Framework 方法。
因此,它的可用性和具体实现可能因不同的控件库或框架而有所不同。
在使用SetControlVisibility方法之前,请确保您已经正确引入了包含该方法的命名空间或引用了相应的库。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
VC中CTreeView控件的使用1.清空TreeView里的所有内容,并重新填充刚开始的时候,能用DeleteAllItems()方法把节点都给删除,但是留下了一片空白,重新添加的内容就看不到了。
这个问题郁闷了很久,但思想无非是一样的,删除节点,重新填充。
偶然间发现别人的代码里用到了SetRedraw()。
哈,问题解决。
2.获取选中节点的文字内容以及获得当前节点的父节点HTREEITEM hSelectedItem=m_TreeCtrl.GetSelectedItem();CString strSelectedItemText=m_TreeCtrl.GetItemText(hSelectedItem);HTREEITEM hParentItem=m_TreeCtrl.GetParentItem(hSelectedItem);3.添加一个节点到TreeView控件中TV_ITEM tvItem;_variant_t vClass;vClass= m_pRecordset->GetCollect("名称");tvItem.mask=TVIF_TEXT|TVIF_PARAM;CString temp;temp=(char*)_bstr_t(vClass);tvItem.pszText=(LPTSTR)(LPCTSTR)temp;TV_INSERTSTRUCT tvInsert;hTextMax=2;tvInsert.hParent=TVI_ROOT;//当作根节点tvInsert.hInsertAfter=TVI_LAST;tvInsert.item=tvItem;HTREEITEM hRoot=m_TreeCtrl.InsertItem(&tvInsert);这段代码从数据库中读取“名称”字段来填充控件。
最值得注意的就是红色的那句话,这里吧CString的字符串添加到TreeView 中需要进行复杂的转化,CSDN中有篇文章详细地讲述了CString 的操作。
地址是:/article/53/53729.shtm这个是英文的/blog/more.asp?name=njucs&id=7350这个是中文的对于上面操作的解释:当你向控件写数据时,文本指针实际上被当成LPCTSTR,而当你从控件读数据时,你必须有一个可写的字符串。
这个结构无法区分它是用来读还是用来写。
因此,你会常常在我的代码中看到如下的用法:tvi.item.pszText = (LPTSTR)(LPCTSTR)s;它把CString 强制类型转化成LPCTSTR,也就是说先获得改字符串的地址,然后再强制类型转化成LPTSTR,以便可以对之进行赋值操作。
注意这只有在使用Set 或Insert 之类的方法才有效!如果你试图获取数据,则不能这么做。
本文来自CSDN博客,转载请标明出处:/hohowu/archive/2005/08/22/461467.aspxCTreeViewExt是MFC使用者可重用的类,该类由CTreeView派生,可以用在文档-视结构的应用程序中,并且支持Drag&Drop。
使用者所需要做的仅仅是将文件加到AppWizard产生的工程中,(CTreeView为基类)并且将CTreeView替换为CTreeViewExt。
并重载三个Virtual Function。
(WenYY:这很简单吧,下面是源代码,我会在必要的地方加上注释,但由于原作者并未加,所以如果有出入请原谅,作者定义了三处虚拟函数,其作用是让使用者重载后,加入自己的判断条件和结果处理的功能,很巧妙的思想:CopyItemPropertiesIsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget);BOOL ItemCanBeDragged(HTREEITEM hItem);//检查是否可以对该ITEM实施Drag&Drop)Header file#if !defined(AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_)#define AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_#if _MSC_VER >= 1000#pragma once#endif // _MSC_VER >= 1000// TreeViewExt.h : header file///////////////////////////////////////////// CTreeViewExt viewclass CTreeViewExt : public CTreeView{protected:CTreeViewExt(); // protected constructor used by dynamic creationDECLARE_DYNCREATE(CTreeViewExt)// Attributespublic:// Operationspublic:// Overrides// ClassWizard generated virtual function overrides//{{AFX_VIRTUAL(CTreeViewExt)protected:virtual void OnDraw(CDC* pDC); // overridden to draw this view//}}AFX_VIRTUAL// Implementationprotected:HTREEITEM m_hDraggedItem;BOOL m_bDraggingNow; //标记CImageList *m_pDragImageList;virtual ~CTreeViewExt();#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;#endif// Generated message map functionsprotected:virtual void CopyItemProperties(HTREEITEM hNewItem, HTREEITEM hDraggedItem);virtual BOOL IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget);virtual BOOL ItemCanBeDragged(HTREEITEM hItem);//检查是否可以对该ITEM实施Drag&Drop //{{AFX_MSG(CTreeViewExt)afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult);//必须重载的函数afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnLButtonUp(UINT nFlags, CPoint point);//}}AFX_MSGDECLARE_MESSAGE_MAP()};///////////////////////////////////////////{{AFX_INSERT_LOCATION}}// Microsoft Developer Studio will insert additional declarations immediately before the previous line.#endif // !defined(AFX_TREEVIEWEXT_H__99D8F6F8_79F0_11D1_8DC6_0000E8125FE5__INCLUDED_) Implementation file// TreeViewExt.cpp : implementation file//#include "stdafx.h"#include "TreeViewExt.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif/////////////////////////////////////////// CTreeViewExtIMPLEMENT_DYNCREATE(CTreeViewExt, CTreeView)CTreeViewExt::CTreeViewExt(){m_bDraggingNow = FALSE;m_hDraggedItem = NULL;m_pDragImageList = NULL;}CTreeViewExt::~CTreeViewExt(){}BEGIN_MESSAGE_MAP(CTreeViewExt, CTreeView)//{{AFX_MSG_MAP(CTreeViewExt)ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag)ON_WM_MOUSEMOVE()ON_WM_LBUTTONUP()//}}AFX_MSG_MAPEND_MESSAGE_MAP()/////////////////////////////////////////// CTreeViewExt drawingvoid CTreeViewExt::OnDraw(CDC* pDC){CDocument* pDoc = GetDocument();// TODO: add draw code here}/////////////////////////////////////////// CTreeViewExt diagnostics#ifdef _DEBUGvoid CTreeViewExt::AssertValid() const{CTreeView::AssertValid();}void CTreeViewExt::Dump(CDumpContext& dc) const{CTreeView::Dump(dc);}#endif //_DEBUG/////////////////////////////////////////// CTreeViewExt message handlersvoid CTreeViewExt::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) {NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;if (!m_bDraggingNow){//先检查是否正在过程中if (ItemCanBeDragged(pNMTreeView->itemNew.hItem)){//查询条件,是否允许Drag&DropCTreeCtrl& tree = GetTreeCtrl();tree.SetCapture();m_bDraggingNow = TRUE;m_hDraggedItem = pNMTreeView->itemNew.hItem;//保存变量tree.Select(m_hDraggedItem, TVGN_CARET);m_pDragImageList = tree.CreateDragImage(m_hDraggedItem);m_pDragImageList->DragEnter(&tree, pNMTreeView->ptDrag);m_pDragImageList->BeginDrag(0, CPoint(0, 0));}}*pResult = 0;}void CTreeViewExt::OnMouseMove(UINT nFlags, CPoint point){if (m_bDraggingNow){CTreeCtrl& tree = GetTreeCtrl();m_pDragImageList->DragEnter(&tree, point);m_pDragImageList->DragMove(point);}CTreeView::OnMouseMove(nFlags, point);}void CTreeViewExt::OnLButtonUp(UINT nFlags, CPoint point){if (m_bDraggingNow){ReleaseCapture();m_bDraggingNow = FALSE;m_pDragImageList->EndDrag();delete m_pDragImageList;m_pDragImageList = NULL;CTreeCtrl& tree = GetTreeCtrl();UINT flags;HTREEITEM hTargetItem = tree.HitTest(point, &flags);//得到目标if (hTargetItem != NULL && IsItemCanBeDroppedOn(m_hDraggedItem, hTargetItem)){//查询是否可以成功完成,条件是开始时选中的Item和结束使选中的ITEM是否满足你的条件HTREEITEM hNewItem = tree.InsertItem("Untitled", hTargetItem);CopyItemProperties(hNewItem, m_hDraggedItem);//进行处理if (nFlags != MK_CONTROL)tree.DeleteItem(m_hDraggedItem);}m_hDraggedItem = NULL;}CTreeView::OnLButtonUp(nFlags, point);}BOOL CTreeViewExt::ItemCanBeDragged(HTREEITEM hItem){//作用为决定现在是否能开始,可以作为一种运行时的选项return FALSE;}BOOL CTreeViewExt::IsItemCanBeDroppedOn(HTREEITEM hSource, HTREEITEM hTarget){//决定现在结束条件是否正常,如不正常则放弃这次操作return FALSE;}void CTreeViewExt::CopyItemProperties(HTREEITEM hNewItem, HTREEITEM hDraggedItem){//按照你的需要对两个ITEM进行处理。