Drag & Drop & Background Image Tree Control
发表于:2007-07-01来源:作者:点击数:
标签:
简介 此文章介绍了使用我 开发 的cTree类来完成树控件中条目的拖拽和为树控件设置图片(bmp)背景的功能。示例程序中只允许非主节点中条目的拖拽。 代码细节 所有的实现过程都在文件cTree.cpp和cTree.h中. 拖拽实现主要在OnBeginDrag()和OnLButtonUp()函数中
简介
此文章介绍了使用我
开发的cTree类来完成树控件中条目的拖拽和为树控件设置图片(bmp)背景的功能。示例程序中只允许非主节点中条目的拖拽。
代码细节
所有的实现过程都在文件cTree.cpp和cTree.h中.
拖拽实现主要在OnBeginDrag()和OnLButtonUp()函数中完成. 在OnBeginDrag函数中,我创建了一个NM_TREEVIEW 结构:
void cTree::OnBeginDrag(NMHDR* pNMHDR,
LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
*pResult = 0;
// So user cant drag root node
if (GetParentItem(pNMTreeView->itemNew.hItem) == NULL) return ;
// Item user started dragging ...
m_hitemDrag = pNMTreeView->itemNew.hItem;
m_hitemDrop = NULL;
// get the image list for dragging
m_pDragImage = CreateDragImage(m_hitemDrag);
// CreateDragImage() returns NULL if no image list
// associated with the tree view control
if( !m_pDragImage )
return;
m_bLDragging = TRUE;
m_pDragImage->BeginDrag(0, CPoint(-15,-15));
POINT pt = pNMTreeView->ptDrag;
ClientToScreen( &pt );
m_pDragImage->DragEnter(NULL, pt);
SetCapture();
}
在NM_TREEVIEW结构创建后,所做的第一件事情就是判断当前是否是根节点,如果是,就返回。当然如果需要的话,你可以注释掉这一行,使得根节点也可以拖拽。
然后我把选中的条目保存在我的HTREEITEM型成员变量var m_itemDrag中 。在拖拽开始时,m_itemDrop值为NULL。CreateDragImage() 函数返回一个CImageList类型的指针,这个指针保存在变量m_pDragImage中。
接下来在拖拽开始时设置布尔值m_bLDraggingm为真,下面是鼠标拖拽子条目时的代码:
void cTree::OnMouseMove(UINT nFlags, CPoint point)
{
HTREEITEM hitem;
UINT flags;
if (m_bLDragging)
{
POINT pt = point;
ClientToScreen(&pt);
CImageList::DragMove(pt);
if ((hitem = HitTest(point, &flags)) != NULL)
{
CImageList::DragShowNolock(FALSE);
// Tests if dragged item is over another child !
if ((GetParentItem(hitem) != NULL) && (cursor_no != ::GetCursor()))
{
::SetCursor(cursor_no);
// Dont want last selected target highlighted after mouse
// has moved off of it, do we now ?
SelectDropTarget(NULL);
}
// Is item we@#re over a root node and not parent root node ?
if ((GetParentItem(hitem) == NULL) && (GetParentItem(m_hitemDrag) != hitem ))
{
if (cursor_arr != ::GetCursor()) ::SetCursor(cursor_arr);
SelectDropTarget(hitem);
}
m_hitemDrop = hitem;
CImageList::DragShowNolock(TRUE);
}
}
else
{
// Set cursor to arrow if not dragged
// Otherwise, cursor will stay hand or arrow depen. on prev setting
::SetCursor(cursor_arr);
}
CTreeCtrl::OnMouseMove(nFlags, point);
}
在OnMouseMove()函数的开始,我们检查布尔值m_bLDragging确定当前是否是拖拽的条目。如果是,我们取得当前鼠标的位置并把当天拖拽的条目移动到此位置。
接下来我们调用HitTest()函数,判断当前鼠标的位置是否在一个条目的上方。如果不是,传递NULL,如果是,传递该条目的HTREEITEM结构。
然后我们通过HitTest()函数的返回值判断该条目是否为子条目。如果是,我们把鼠标设置为cursor_no,这样用户可以根据鼠标的形状知道这个时候是不允许拖拽放置的。如果这个条目是一个根节点,那么鼠标形状被设置为箭头,允许CImageList去画被拖拽的条目。
在CMainFrame中,你可以很容易的创建一个Treectrl,并为其加入根节点和子条目。
void CMainFrame::CreateTreeCtrl()
{
if (tree_ctrl) tree_ctrl.DestroyWindow() ;
CRect rect;
GetClientRect(&rect);
tree_ctrl.Create( /*|| TVS_EDITLABELS |*/ WS_VISIBLE |
WS_TABSTOP | WS_CHILD /*| WS_BORDER | LBS_NOTIFY*/
/*| TVS_LINESATROOT | TVS_HASLINES */
/*& TVS_NOTOOLTIPS & TVS_HASBUTTONS*/,
CRect(10,10,rect.right-5,rect.bottom),this,ID_TREELISTBOX);
CFont listBoxFont ;
listBoxFont.CreateFont(
16, // nHeight
0, // nWidth
0, // nEscapement
0, // nOrientation
FW_BOLD, // nWeight
FALSE, // bItalic
FALSE, // bUnderline
0, // cStrikeOut
ANSI_CHARSET, // nCharSet
OUT_DEFAULT_PRECIS, // nOutPrecision
CLIP_DEFAULT_PRECIS, // nClipPrecision
DEFAULT_QUALITY, // nQuality
DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily
"Arial");
tree_ctrl.SetFont(&listBoxFont,FALSE);
COLORREF acolor=RGB(0,0,0);
tree_ctrl.SetTextColor(acolor);
CBitmap bmp;
// normal tree images
tree_imageList.Create(IDB_TREE_IMAGELIST,18,7, RGB(255, 0 ,255));
ASSERT(tree_imageList.m_hImageList);
bmp.LoadBitmap(IDB_TREE_IMAGELIST);
tree_imageList.Add( &bmp, RGB(255,255,255));
bmp.DeleteObject();
//TVSIL_STATE
tree_ctrl.SetImageList(&tree_imageList,TVSIL_NORMAL);
tree_ctrl.AddGroup("CodeProject") ;
tree_ctrl.AddGroup("DanCclark.com") ;
tree_ctrl.AddGroup("Peeps") ;
tree_ctrl.AddGroup("Folders") ;
tree_ctrl.AddChild("danclark","Other Contacts") ;
tree_ctrl.AddChild("fugazi","Other Contacts") ;
}
首先我们在MainFrm.h文件中声明了cTree类型变量tree_ctrl,并且在CreateTreeCtrl()中我们调用Create()函数和SetFont()函数创建我们需要的树控件。然后我们创建一个bitmap,这样我们可以加载与图片列表相关联的资源,用于树控件的图片列表。然后我们把它传递给TreeCtrl对象的SetImageList()方法。
我们也可以在cTree的构造函数中使用函数SetDefaultCursor(),这样在创建控件时自动加载锁型鼠标和箭头鼠标。
其他一些有用的函数
AddGroup(CString groupname) - 为树控件加入一个根节点
DeleteGroup(CString groupname) - 输出一个根节点
AddChild(CString childname,CString groupname) - 为指定的根节点(组)加入子条目
DeleteChild(CString childname,CString groupname) - 为指定的根节点(组)删除子条目
GetChildCountInGroup(CString groupname) - 得到一个根节点(组)中子条目的个数
SetBkImage(UINT) - 通过资源ID设置树控件背景图片
SetBkImage(LPCTSTR) - 通过加载字符串设置树控件背景图片
原文转自:http://www.ltesting.net