SftTree/DLL 7.5 - Tree Control
SftBox/OCX 5.0 - Combo Box Control
SftButton/OCX 3.0 - Button Control
SftMask/OCX 7.0 - Masked Edit Control
SftTabs/OCX 6.5 - Tab Control (VB6 only)
SftTree/OCX 7.5 - Tree Control
SftPrintPreview/DLL 2.0 - Print Preview Control (discontinued)
SftTree/DLL 7.5 - Tree Control
SftBox/OCX 5.0 - Combo Box Control
SftButton/OCX 3.0 - Button Control
SftDirectory 3.5 - File/Folder Control (discontinued)
SftMask/OCX 7.0 - Masked Edit Control
SftOptions 1.0 - Registry/INI Control (discontinued)
SftPrintPreview/OCX 1.0 - Print Preview Control (discontinued)
SftTabs/OCX 6.5 - Tab Control (VB6 only)
SftTree/OCX 7.5 - Tree Control
SftTabs/NET 6.0 - Tab Control (discontinued)
SftTree/NET 2.0 - Tree Control
This sample illustrates drag & drop (using OLE mechanisms) within a tree control and with Windows Explorer.
The source code is located at C:\Program Files (x86)\Softelvdm\SftTree DLL 7.5\Samples\MFC\OLEDrag\SamplVw.cpp or C:\Program Files\Softelvdm\SftTree DLL 7.5\Samples\MFC\OLEDrag\SamplVw.cpp (on 32-bit Windows versions).
/****************************************************************************/ /* SftTree/DLL 7.5 - Tree Control for C/C++ */ /* Copyright (C) 1995, 2016 Softel vdm, Inc. All Rights Reserved. */ /****************************************************************************/ #include "stdafx.h" #include "OLEDrag.h" #include "sampldoc.h" #include "samplvw.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSampleView IMPLEMENT_DYNCREATE(CSampleView, CView) BEGIN_MESSAGE_MAP(CSampleView, CView) //{{AFX_MSG_MAP(CSampleView) ON_WM_CREATE() ON_WM_SIZE() //}}AFX_MSG_MAP ON_SFTTREEN_LBUTTONDBLCLK_TEXT(IDC_TREE, OnLButtonExpandCollapse) ON_SFTTREEN_LBUTTONDOWN_BUTTON(IDC_TREE, OnLButtonExpandCollapse) ON_SFTTREEN_LBUTTONDBLCLK_BUTTON(IDC_TREE, OnLButtonExpandCollapse) ON_SFTTREEN_EXPANDALL(IDC_TREE, OnExpandAll) ON_SFTTREEN_LBUTTONDBLCLK_COLUMNRES(IDC_TREE, OnLButtonDblClkColumnResize) ON_SFTTREEN_LBUTTONDBLCLK_PLUSMIN(IDC_TREE, OnLButtonExpandCollapse) ON_SFTTREEN_LBUTTONDOWN_PLUSMIN(IDC_TREE, OnLButtonExpandCollapse) ON_SFTTREEN_BEGINDRAG(IDC_TREE, OnBeginDrag) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSampleView construction/destruction CSampleView::CSampleView() { } CSampleView::~CSampleView() { } ///////////////////////////////////////////////////////////////////////////// // CSampleView drawing void CSampleView::OnDraw(CDC* pDC) { CSampleDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); } ///////////////////////////////////////////////////////////////////////////// // CSampleView diagnostics #ifdef _DEBUG void CSampleView::AssertValid() const { CView::AssertValid(); } void CSampleView::Dump(CDumpContext& dc) const { CView::Dump(dc); } CSampleDoc* CSampleView::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSampleDoc))); return (CSampleDoc*)m_pDocument; } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CSampleView message handlers int CSampleView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; if (!m_Tree.CreateEx( WS_EX_CLIENTEDGE, SFTTREESTYLE_NOTIFY | /* Notify parent window */ SFTTREESTYLE_DRAGDROP | /* Drag & drop enabled */ SFTTREESTYLE_LEFTBUTTONONLY | /* Only respond to left mouse button */ SFTTREESTYLE_SCROLL | /* Honor WS_H/VSCROLL */ SFTTREESTYLE_DISABLENOSCROLL | /* Disable scrollbars instead of hiding */ WS_HSCROLL | WS_VSCROLL | /* Vertical and horizontal scrollbars */ WS_VISIBLE | WS_CHILD, /* Visible, child window */ CRect(0,0,0,0), /* Location */ this, /* Parent window */ IDC_TREE)) /* Tree control ID */ return -1; m_Tree.SetShowHeader(TRUE); /* Show column headers */ SFT_PICTURE Pic; /* Used for certain pictures */ /* Register the item pictures. These pictures are used */ /* for all items in the tree control. All three pictures */ /* must be the same size. */ { SFT_PICTURE aPic[3]; Sft_InitPicture(&aPic[0]); Sft_InitPicture(&aPic[1]); Sft_InitPicture(&aPic[2]); m_aThreeItemBitmaps[0].LoadBitmap(IDB_EXPANDABLE);/* Expandable bitmap */ Sft_SetPictureBitmap(&aPic[0], m_aThreeItemBitmaps[0]);/* Assign bitmap */ m_aThreeItemBitmaps[1].LoadBitmap(IDB_EXPANDED);/* Expanded bitmap */ Sft_SetPictureBitmap(&aPic[1], m_aThreeItemBitmaps[1]);/* Assign bitmap */ m_aThreeItemBitmaps[2].LoadBitmap(IDB_LEAF);/* Leaf bitmap */ Sft_SetPictureBitmap(&aPic[2], m_aThreeItemBitmaps[2]);/* Assign bitmap */ m_Tree.SetPictures(aPic); /* Use item pictures */ } m_Tree.SetItemBitmapAlign(TRUE); /* Align item bitmaps */ /* Register the cell picture size. All cell pictures used */ /* must be the same size. Only one picture needs to be */ /* registered, even if several are used. */ { SFTTREE_CELLINFOPARM CellInfo; CellInfo.version = 7; CellInfo.index = -1; /* Registering picture size */ m_CellBitmap.LoadBitmap(IDB_SMILE);/* Cell picture */ Sft_InitPicture(&CellInfo.Cell.CellPicture1); Sft_SetPictureBitmap(&CellInfo.Cell.CellPicture1, m_CellBitmap);/* Assign bitmap */ m_Tree.SetCellInfo(&CellInfo); /* Register use of cell pictures */ } m_Tree.SetTreeLineStyle(SFTTREE_TREELINE_DOT);/* Dotted tree lines */ m_Tree.SetShowButtons(FALSE); /* Expand/collapse buttons (level 1..n) */ m_Tree.SetShowGrid(TRUE); /* Show grid */ m_Tree.SetGridStyle(SFTTREE_GRID_BOTH_DOT);/* Dotted grid lines */ m_Tree.SetShowTruncated(TRUE); /* Show ... if truncated */ m_Tree.SetNoFocusStyle(SFTTREE_NOFOCUS_FRAME);/* No focus, show frame */ m_Tree.SetSelectionStyle(SFTTREE_SELECTION_CELL1 | SFTTREE_SELECTION_OUTLINE);/* Select first cell only using outline */ m_Tree.SetSelectionArea(SFTTREE_SELECTIONAREA_ALL);/* Selection changes by clicking anywhere on an item */ m_Tree.SetFlyby(TRUE); /* Flyby highlighting */ m_Tree.SetCrossColumnResize(TRUE); /* Resize multiple columns */ m_Tree.SetReorderColumns(TRUE); /* Column reordering */ m_Tree.SetOpenEnded(TRUE); /* Last column width */ m_Tree.SetShowHeaderButtons(TRUE); /* Show column header as buttons */ /* Define columns */ { SFTTREE_COLUMN_EX aCol[2] = { { 0, 0, /* Reserved */ 100, /* Width (in pixels) */ ES_LEFT | SFTTREE_TOOLTIP, /* Cell alignment */ ES_LEFT | SFTTREE_HEADER_UP, /* Title style */ _T("First Column"), /* Column header title */ NULL, NULL, /* Reserved field and bitmap handle */ SFTTREE_BMP_RIGHT, /* Picture alignment */ 0, 0, 0, /* Reserved fields */ SFTTREE_NOCOLOR, /* Cell background color */ SFTTREE_NOCOLOR, /* Cell foreground color */ SFTTREE_NOCOLOR, /* Selected cell background color */ SFTTREE_NOCOLOR, /* Selected cell foreground color */ 0, /* Real column position (set by SetColumns call) */ 0, /* Display column number (display position) */ SFTTREE_COL_MERGE | /* Column can merge with next */ SFTTREE_COL_MERGEINTO | /* Previous column can merge into this column */ 0, /* Column flag */ 0, /* Minimum column width */ }, { 0, 0, /* Reserved */ 253, /* Width (in pixels) */ ES_LEFT | SFTTREE_TOOLTIP, /* Cell alignment */ ES_LEFT | SFTTREE_HEADER_UP, /* Title style */ _T("Second Column"), /* Column header title */ NULL, NULL, /* Reserved field and bitmap handle */ SFTTREE_BMP_RIGHT, /* Picture alignment */ 0, 0, 0, /* Reserved fields */ SFTTREE_NOCOLOR, /* Cell background color */ SFTTREE_NOCOLOR, /* Cell foreground color */ SFTTREE_NOCOLOR, /* Selected cell background color */ SFTTREE_NOCOLOR, /* Selected cell foreground color */ 0, /* Real column position (set by SetColumns call) */ 1, /* Display column number (display position) */ SFTTREE_COL_MERGE | /* Column can merge with next */ SFTTREE_COL_MERGEINTO | /* Previous column can merge into this column */ 0, /* Column flag */ 0, /* Minimum column width */ } }; m_Tree.SetColumns(2, aCol); /* Set column attributes */ } m_Tree.SetShowRowHeader(SFTTREE_ROWSTYLE_BUTTONCOUNT1);/* Row style */ m_Tree.SetRowColHeaderText(_T("?")); /* Row/column header text */ m_Tree.SetRowColHeaderStyle(ES_LEFT | SFTTREE_HEADER_UP);/* Row/column header style */ Sft_InitPicture(&Pic); /* Initialize */ Sft_SetPictureBitmap(&Pic, m_RowColBitmap); m_Tree.SetRowColHeaderPicture(&Pic); /* Row/column picture */ m_Tree.SetRowColHeaderPictureStyle(SFTTREE_BMP_RIGHT);/* Row/column picture alignment */ m_Tree.SetDragBitmaps(TRUE); /* Allow drag & drop from item, label pictures */ m_Tree.SetDragType(SFTTREE_DRAG_PIXELIMM);/* Select and move by a number of pixels to start drag */ m_Tree.SetDropHighlightStyle(SFTTREE_DROPHIGHLIGHT_ONTOP);/* Highlight drop target */ /*------------------------------------------------------------------------------*/ /* Add a few items. */ /*------------------------------------------------------------------------------*/ int i, index; index = m_Tree.AddString(_T("Items can be copied within this tree control.")); /* Add an item */ index = m_Tree.AddString(_T("Item text can be copied to other applications.")); /* Add an item */ index = m_Tree.AddString(_T("Files/folders can be dropped here (from Windows Explorer) and their names are added to the tree control.")); /* Add an item */ for (i = 0 ; i < 30 ; ) { CString str; str.Format(_T("Item %d"), i); index = m_Tree.AddString(str); /* Add an item */ ++i; str.Format(_T("Item %d"), i); index = m_Tree.AddString(str); /* Add another item */ m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */ /* Set an item's row header text using: */ m_Tree.SetRowText(index, _T(">")); /* Row header text */ ++i; str.Format(_T("Item %d"), i); index = m_Tree.AddString(str); /* Add another item */ m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */ ++i; str.Format(_T("Item %d"), i); index = m_Tree.AddString(str); /* Add another item */ m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */ /* Set a cell bitmap */ SFTTREE_CELLINFOPARM CellInfo; CellInfo.version = 7; CellInfo.index = index; CellInfo.iCol = 1; m_Tree.GetCellInfo(&CellInfo); Sft_SetPictureBitmap(&CellInfo.Cell.CellPicture1, m_CellBitmap); m_Tree.SetCellInfo(&CellInfo); ++i; } /*------------------------------------------------------------------------------*/ /* Once ALL TREE CONTROL ITEMS HAVE BEEN ADDED, you can set additional tree */ /* control attributes. */ /*------------------------------------------------------------------------------*/ /* Make all column widths optimal, so text and bitmaps are */ /* not clipped horizontally. */ m_Tree.MakeColumnOptimal(-1, 0, FALSE);/* Make column widths optimal */ /* Make row header width optimal, so text and bitmaps are */ /* not clipped horizontally. */ m_Tree.MakeRowHeaderOptimal(0, FALSE);/* Make row header width optimal */ m_Tree.RecalcHorizontalExtent(0, FALSE);/* Update horizontal scroll bar */ // Register this tree control as a possible drop target m_dropTarget.Register(&m_Tree); return 0; } void CSampleView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); m_Tree.MoveWindow(0, 0, cx, cy); } /* Respond to expand/collapse requests as the user clicks */ /* on different tree components. The events handled here */ /* can be changed to suit your application. */ void CSampleView::OnLButtonExpandCollapse() { /* get index of item to expand/collapse */ int index = m_Tree.GetExpandCollapseIndex(); /* get current expand/collapsed status */ BOOL fExpanded = m_Tree.GetItemExpand(index); /* if control key is used we'll expand all dependents */ BOOL fDepth = (::GetKeyState(VK_CONTROL)&0x8000); if (fExpanded) m_Tree.Collapse(index, TRUE); else m_Tree.Expand(index, TRUE, fDepth); } /* Respond to numeric keypad multiply key. */ void CSampleView::OnExpandAll() { /* get index of item to expand/collapse */ int index = m_Tree.GetExpandCollapseIndex(); m_Tree.Expand(index, TRUE, TRUE); } void CSampleView::OnLButtonDblClkColumnResize() { /* Resize column optimally */ int realCol = m_Tree.GetResizeColumn(); if (realCol >= 0) { m_Tree.MakeColumnOptimal(realCol);/* Make column width optimal */ m_Tree.RecalcHorizontalExtent(0, FALSE);/* Update horizontal scroll bar */ } } // Drag & drop support void CSampleView::OnBeginDrag() { /* Drag & drop started */ // determine what item is being dragged int index = m_Tree.GetCaretIndex(); CString str; m_Tree.GetText(index, 0, str);// get the item's text // turn off the tree's built-in drag & drop, we'll use OLE drag & drop instead m_Tree.SendMessage(WM_CANCELMODE); // use CacheData or CacheGlobalData to define the data to be moved/copied // In this example, the cell text of the source item is copied into a global // storage area m_dataSource.Empty(); HGLOBAL hGlobal = ::GlobalAlloc(GHND, (str.GetLength()+1)*sizeof(TCHAR)); if (!hGlobal) return; LPTSTR lpStr = (LPTSTR) GlobalLock(hGlobal); lstrcpy(lpStr, (LPCTSTR) str);// copy the cell text into the global area GlobalUnlock(hGlobal); m_dataSource.CacheGlobalData(CF_TEXT, hGlobal); // Initiate the OLE drag & drop, OLE mechanisms now take over (using COleDropSource // and COleDataSource classes defined here) and COleDropTarget in the target control/window m_dataSource.DoDragDrop( DROPEFFECT_COPY|DROPEFFECT_MOVE, NULL, &m_dropSource); } // The COleDropTarget class needs a little help so target highlighting works // correctly. Anytime a drag&drop ends up above the tree control, the // COleDropTarget class handles the events. DROPEFFECT CTreeDropTarget::OnDragEnter( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) { if (!pWnd->IsKindOf(RUNTIME_CLASS(CSftTree))) return DROPEFFECT_NONE; CSftTree* pTree = (CSftTree*) pWnd; // clear drop highlight pTree->SetDropHighlight(-1); return DROPEFFECT_NONE; } DROPEFFECT CTreeDropTarget::OnDragOver( CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) { if (!pWnd->IsKindOf(RUNTIME_CLASS(CSftTree))) return DROPEFFECT_NONE; CSftTree* pTree = (CSftTree*) pWnd; // find the index of the item at the cursor position int index = pTree->CalcIndexFromPointEx(&point); if (index < 0) { pTree->SetDropHighlight(-1); return DROPEFFECT_NONE; } // if the data being dragged into the control isn't in the proper format, // dropping isn't possible if (!pDataObject->IsDataAvailable(CF_TEXT) && !pDataObject->IsDataAvailable(CF_HDROP) ) return DROPEFFECT_NONE; // determine the desired "drop" effect // DROPEFFECT_NONE The data object cannot be dropped in this window. // DROPEFFECT_LINK for MK_CONTROL | MK_SHIFT Creates a linkage between the object and its server. // not used in this example // DROPEFFECT_COPY for MK_CONTROL Creates a copy of the dropped object. // DROPEFFECT_MOVE for MK_ALT Creates a copy of the dropped object and delete the original object. // This is typically the default drop effect, when the view can accept the data object. // not used in this example (as it might be too destructive for illustration purposes) DROPEFFECT effect = DROPEFFECT_COPY; // set the item's drop highlight indicator (start scrolling if it's // an item at the top or bottom of the control pTree->SetDropHighlight(index, TRUE); return effect; } void CTreeDropTarget::OnDragLeave( CWnd* pWnd ) { if (!pWnd->IsKindOf(RUNTIME_CLASS(CSftTree))) return; CSftTree* pTree = (CSftTree*) pWnd; // clear drop highlight pTree->SetDropHighlight(-1); return; } DROPEFFECT CTreeDropTarget::OnDropEx( CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropDefault, DROPEFFECT dropList, CPoint point ) { if (!pWnd->IsKindOf(RUNTIME_CLASS(CSftTree))) return DROPEFFECT_NONE; CSftTree* pTree = (CSftTree*) pWnd; // determine the drop-target item int dropIndex = pTree->GetDropHighlight(); // make sure InsertString adds AFTER the drop-target if (dropIndex >= 0) ++dropIndex; // clear drop highlight pTree->SetDropHighlight(-1); // extract the data that arrived here. This is just a sample // and is very application specific. STGMEDIUM StgMedium; CFile*pFile = pDataObject->GetFileData(CF_TEXT, NULL); if (pFile) { // the data is in CF_TEXT format, just add the text as a new item at // the insertion point TCHAR szBuffer[256]; pFile->Read(szBuffer, sizeof(szBuffer)/sizeof(TCHAR)); int index = pTree->InsertString(dropIndex, szBuffer); pTree->SetCaretIndex(index); pTree->SetCurSel(index); ++dropIndex; delete pFile; } else if (pDataObject->GetData(CF_HDROP, &StgMedium, NULL) && StgMedium.tymed == TYMED_HGLOBAL) { // the data is in CF_HDROP format (a list of files from Windows Explorer), // just add each new item at the insertion point TCHAR szBuffer[_MAX_PATH]; int nFiles = DragQueryFile((HDROP)StgMedium.hGlobal, -1, NULL, 0); // get # of files for (int i = 0 ; i < nFiles ; ++i) { // extract one file DragQueryFile((HDROP)StgMedium.hGlobal, i, szBuffer, sizeof(szBuffer)/sizeof(TCHAR)); // get file name // insert it as a new item in the tree control int index = pTree->InsertString(dropIndex, szBuffer); pTree->SetCaretIndex(index); pTree->SetCurSel(index); ++dropIndex; } } return DROPEFFECT_COPY; } // The COleDropSource default implementation works just fine. // The COleDropSource class can be used to control the // drag & drop behaviour when the tree control is the // origin of a drag & drop SCODE CTreeDropSource::GiveFeedback(DROPEFFECT dropEffect) { return COleDropSource::GiveFeedback(dropEffect); } BOOL CTreeDropSource::OnBeginDrag(CWnd* pWnd) { return COleDropSource::OnBeginDrag(pWnd); } SCODE CTreeDropSource::QueryContinueDrag(BOOL bEscapePressed, DWORD dwKeyState) { return COleDropSource::QueryContinueDrag(bEscapePressed, dwKeyState); }