Click here to Skip to main content
6,937,593 members and growing! (18,837 online)
Email Password   helpLost your password?
 
Desktop Development » Tree Controls » Custom Tree Controls     Intermediate License: The Code Project Open License (CPOL)

MultiSelect DragImage in CTreeCtrl

By Sudheesh.P.S

This article describes how to create a multiselect drag image in CTreeCtrl.
VC6WinXP, MFC, Dev
Posted:21 Dec 2004
Views:52,277
Bookmarked:29 times
printPrint Friendly   add Share
      Discuss Discuss   Broken Article?Report  
9 votes for this article.
Popularity: 3.84 Rating: 4.03 out of 5

1

2
2 votes, 22.2%
3
4 votes, 44.4%
4
3 votes, 33.3%
5

Sample screenshot

Introduction

This article describes how to create a multi select drag image in CTreeCtrl. I have created a custom tree control CDragDropTreeCtrl (derived from CTreeCtrl) for adding drag and drop support. CreateDragImageEx() is the core function, it creates the drag image list.

CDragDropTreeCtrl

This class implements multiple selection with mouse, with the Ctrl or Shift key down. The DragDetect() API is used to detect the start of drag. Once the dragging is detected, the OnDrag() function is invoked. The OnDrag() function invokes CreateImageEx() to create the drag image list. The rest is the same as single selection drag. BeginDrag() and DragEnter() functions are used to prepare the image list for dragging. In the mouse move event, the drag image is moved.

CreateDragImageEx

This is the core function, which creates the drag image list. Steps in creating drag image list are:

  1. Get the image list associated with the tree control
  2. Get the icon size with the help of the API ImageList_GetIconSize()
  3. Calculate the bounding rect of the drag image
    1. Calculate the maximum width
    2. Calculate the height of single item and multiply it with list size to get the total height
  4. Create a memory device context
  5. Prepare the memory DC
  6. Create and prepare bitmap object
  7. Select Bitmap into the memory DC
  8. For each element in the list, extract the icon and associated text and draw them to the memory DC
  9. Create a new image list
  10. Add the bitmap to the image list
// 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));

Conclusion

This CDragDropTreeCtrl implements multiple selection with mouse only. The keyboard support will be updated later. With this method for creating drag image list, we can create drag image for list controls also.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Sudheesh.P.S


Member
Working as a software engineer in an MNC at Trivandrum. I can be reached at sudheesh_perumbilli@yahoo.com
Occupation: Web Developer
Location: India India

Other popular Tree Controls articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 2 of 2 (Total in Forum: 2) (Refresh)FirstPrevNext
GeneralI am in china.My English is poor,but I need you help urgently. PinmemberPlainzeng17:15 29 Mar '07  
GeneralFantastic contribution :) [modified] PinmemberBaldelicious8211:43 6 Mar '07  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+PgUp/PgDown to switch pages.

PermaLink | Privacy | Terms of Use
Last Updated: 21 Dec 2004
Editor: Rinish Biju
Copyright 2004 by Sudheesh.P.S
Everything else Copyright © CodeProject, 1999-2010
Web20 | Advertise on the Code Project