CreateDragImage for multiple selected items in CListCtrl | CodeGuru

CreateDragImage for multiple selected items in CListCtrl

Environment: VC6 SP2, NT4 SP4 Currently the CreateDragImage method from CListCtrl only supports the generation of drag images of a single selected item (at least I didn’t found an alternative in the Win API). Inspired by an article from Pel K Txnder I found one way to create drag images for multiple selections. The trick […]

Written By
CodeGuru Staff
CodeGuru Staff
Dec 21, 1999
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Sample Image

Environment: VC6 SP2, NT4 SP4

Currently the CreateDragImage method from CListCtrl only supports the generation of drag images of a single selected item (at least I didn’t found an alternative in the Win API).
Inspired by an article from Pel K Txnder I found one way to create drag images for multiple selections.

The trick is to create a bitmap in a memory dc and paint the drag image from each selected item into it.
This bitmap is added to the drag imagelist.
The code enhances a derived CListCtrl (CListCtrlEx) with the method CreateDragImageEx.
However, it should also work with a few modifications without subclassing the CListCtrl.

CImageList *CListCtrlEx::CreateDragImageEx( LPPOINT lpPoint )
{
	CRect	cSingleRect;
	CRect	cCompleteRect( 0,0,0,0 );
	int	nIdx;
	BOOL	bFirst = TRUE;
	//
	// Determine the size of the drag image
	//
	POSITION pos = GetFirstSelectedItemPosition();
	while (pos)
	{
		nIdx = GetNextSelectedItem( pos );
		GetItemRect( nIdx, cSingleRect, LVIR_BOUNDS );
		if (bFirst)
		{
			// Initialize the CompleteRect
			GetItemRect( nIdx, cCompleteRect, LVIR_BOUNDS );
			bFirst = FALSE;
		}
		cCompleteRect.UnionRect( cCompleteRect, cSingleRect );
	}

	//
	// Create bitmap in memory DC
	//
	CClientDC	cDc(this);
	CDC		cMemDC;
	CBitmap   	cBitmap;

	if(!cMemDC.CreateCompatibleDC(&cDc))
		return NULL;

	if(!cBitmap.CreateCompatibleBitmap(&cDc, cCompleteRect.Width(), cCompleteRect.Height()))
		return NULL;

	CBitmap* pOldMemDCBitmap = cMemDC.SelectObject( &cBitmap );
	// Here green is used as mask color
	cMemDC.FillSolidRect(0,0,cCompleteRect.Width(), cCompleteRect.Height(), RGB(0, 255, 0));

	//
	// Paint each DragImage in the DC
	//
	CImageList *pSingleImageList;
	CPoint		cPt;

	pos = GetFirstSelectedItemPosition();
	while (pos)
	{
		nIdx = GetNextSelectedItem( pos );
		GetItemRect( nIdx, cSingleRect, LVIR_BOUNDS );

		pSingleImageList = CreateDragImage( nIdx, &cPt);
		if (pSingleImageList)
		{
			pSingleImageList->DrawIndirect( &cMemDC,
							0,
							CPoint( cSingleRect.left-cCompleteRect.left,
							cSingleRect.top-cCompleteRect.top ),
							cSingleRect.Size(),
							CPoint(0,0));
			delete pSingleImageList;
		}
	}

	cMemDC.SelectObject( pOldMemDCBitmap );
	//
	// Create the imagelist	with the merged drag images
	//
	CImageList* pCompleteImageList = new CImageList;

	pCompleteImageList->Create(	cCompleteRect.Width(),
					cCompleteRect.Height(),
					ILC_COLOR | ILC_MASK, 0, 1);
	// Here green is used as mask color
	pCompleteImageList->Add(&cBitmap, RGB(0, 255, 0));

	cBitmap.DeleteObject();
	//
	// as an optional service:
	// Find the offset of the current mouse cursor to the imagelist
	// this we can use in BeginDrag()
	//
	if ( lpPoint )
	{
		CPoint cCursorPos;
		GetCursorPos( &cCursorPos );
		ScreenToClient( &cCursorPos );
		lpPoint->x = cCursorPos.x - cCompleteRect.left;
		lpPoint->y = cCursorPos.y - cCompleteRect.top;
	}

	return( pCompleteImageList );
}

Sample usage:

void CDialogWhichUsesListCtrl::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
	NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	POINT pt;

	m_pDragImage = m_ctlList.CreateDragImageEx( &pt );

	m_pDragImage->BeginDrag( 0, pt );
	m_pDragImage->DragEnter( GetDesktopWindow(), pNMListView->ptAction);
	SetCapture();
	*pResult = 0;
}

Downloads

Download source (same as above, but with proper formatting) – 1 Kb

CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.