65.9K
CodeProject 正在变化。 阅读更多。
Home

CTreeCtrl 中的 MultiSelect DragImage

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.16/5 (16投票s)

2004年12月22日

CPOL

1分钟阅读

viewsIcon

96811

downloadIcon

4903

本文档描述了如何在 CTreeCtrl 中创建多选拖拽图像。

Sample screenshot

引言

本文档描述了如何在 CTreeCtrl 中创建多选拖拽图像。我创建了一个自定义树控件 CDragDropTreeCtrl(从 CTreeCtrl 派生)来添加拖放支持。CreateDragImageEx() 是核心函数,它创建拖拽图像列表。

CDragDropTreeCtrl

此类实现了使用鼠标,并按下 Ctrl 或 Shift 键进行多选。使用 DragDetect() API 检测拖拽的开始。一旦检测到拖拽,就会调用 OnDrag() 函数。OnDrag() 函数调用 CreateImageEx() 来创建拖拽图像列表。其余部分与单选拖拽相同。使用 BeginDrag()DragEnter() 函数为拖拽准备图像列表。在鼠标移动事件中,拖拽图像会被移动。

CreateDragImageEx

这是核心函数,用于创建拖拽图像列表。创建拖拽图像列表的步骤如下:

  1. 获取与树控件关联的图像列表
  2. 使用 API ImageList_GetIconSize() 获取图标大小
  3. 计算拖拽图像的边界矩形
    1. 计算最大宽度
    2. 计算单个项目的高度,并将其乘以列表大小以获得总高度
  4. 创建一个内存设备上下文
  5. 准备内存 DC
  6. 创建并准备位图对象
  7. 将位图选择到内存 DC 中
  8. 对于列表中的每个元素,提取图标和关联的文本,并将它们绘制到内存 DC 中
  9. 创建一个新的图像列表
  10. 将位图添加到图像列表中
// 1.Get the image list associated with the tree control
   CImageList *pImageList = GetImageList(TVSIL_NORMAL); 
// 2.Get the icon size with the help of the API ImageList_GetIconSize()
    int cx,cy;
    ImageList_GetIconSize(*pImageList, &cx, &cy); 
// 3.Calculate the bounding rect of the drag image
// a) Calculate the maximum width    
 
 for ( nIdx = 0; nIdx < nNumSelected; nIdx++) 
 {
   // Get the item's height and width one by one
   hItem = m_vSelItem[nIdx];
   strItemText = GetItemText(hItem);
   rectFirstItem.SetRectEmpty();
   pDragImageCalcDC->DrawText(strItemText, rectFirstItem, DT_CALCRECT);
   if(nMaxWidth < ( rectFirstItem.Width()+cx))
    nMaxWidth = rectFirstItem.Width()+cx;
 }
// b) Calculate the height of single item and multiply it
// with list size to get the total height
    hItem = m_vSelItem[0];
    strItemText = GetItemText(hItem);
    rectFirstItem.SetRectEmpty();
    pDragImageCalcDC->DrawText(strItemText, rectFirstItem, DT_CALCRECT);
    
    rectTextArea.SetRect(1, 1, nMaxWidth, rectFirstItem.Height());
    rectBounding.SetRect(0,0, nMaxWidth+2, 
                 (rectFirstItem.Height()+2)*nNumSelected);
    
// 4.Create a memory device context
   CDC MemoryDC;
// 5.Prepare the memory DC
  if(!MemoryDC.CreateCompatibleDC(&DraggedNodeDC))
    return NULL;
// 6.Create and prepare bitmap object
  CBitmap   DraggedNodeBmp;
  if(!DraggedNodeBmp.CreateCompatibleBitmap(&DraggedNodeDC, 
              rectBounding.Width(), rectBounding.Height()))
    return NULL;
// 7.Select Bitmap into the memory DC
  pBitmapOldMemDCBitmap = MemoryDC.SelectObject( &DraggedNodeBmp );
// 8.For each element in the list extract the icon
// and associated text and draw them to the memory DC
  for( nIdx = 0; nIdx < nNumSelected; nIdx++)
  {
    hItem = m_vSelItem[nIdx];
    int nImg = 0,nSelImg=0;
    GetItemImage(hItem,nImg,nSelImg);
    HICON hIcon = pImageList->ExtractIcon(nImg);
    //cdcMemory.DrawIcon(rectTextArea.left,rectTextArea.top,hIcon);
    MemoryDC.MoveTo(rectTextArea.left,rectTextArea.top);
    if( nIdx != nNumSelected-1 )
    {
      MemoryDC.LineTo(rectTextArea.left,rectTextArea.top+18);
    }
    else
    {
      MemoryDC.LineTo(rectTextArea.left,rectTextArea.top+8);
    }
    MemoryDC.MoveTo(rectTextArea.left,rectTextArea.top+8);
    MemoryDC.LineTo(rectTextArea.left+5,rectTextArea.top+8);
    int nLeft = rectTextArea.left;
    rectTextArea.left += 3;
    ::DrawIconEx(MemoryDC.m_hDC,rectTextArea.left,rectTextArea.top,hIcon,
                 16,16,0,NULL,DI_NORMAL);
    rectTextArea.left += cx;
    MemoryDC.Rectangle(rectTextArea);
    MemoryDC.DrawText(GetItemText(hItem), rectTextArea, 
                   DT_LEFT| DT_SINGLELINE|DT_NOPREFIX);
    rectTextArea.left = nLeft;
    rectTextArea.OffsetRect(0, rectFirstItem.Height()+2);
    DestroyIcon(hIcon);
  }
 
 // 9.Create a new image list
   pImageListDraggedNode = new CImageList;
   pImageListDraggedNode->Create(rectBounding.Width(), rectBounding.Height(), 
                                 ILC_COLOR | ILC_MASK, 0, 1);
 // 10.Add the bitmap to the image list
    pImageListDraggedNode->Add(&DraggedNodeBmp, RGB(255, 255,255));

结论

CDragDropTreeCtrl 仅实现使用鼠标进行多选。键盘支持将在以后更新。使用这种方法创建拖拽图像列表,我们也可以为列表控件创建拖拽图像。

© . All rights reserved.