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 within and between tree controls.
The source code is located at C:\Program Files (x86)\Softelvdm\SftTree DLL 7.5\Samples\MFC\DragDrop\Dlg.cpp or C:\Program Files\Softelvdm\SftTree DLL 7.5\Samples\MFC\DragDrop\Dlg.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 "DRAGDROP.h" #include "Dlg.h" ///////////////////////////////////////////////////////////////////////////// // CSampleDlg dialog CSampleDlg::CSampleDlg(CWnd* pParent /*=NULL*/) : CDialog(CSampleDlg::IDD, pParent) { //{{AFX_DATA_INIT(CSampleDlg) // NOTE: the ClassWizard will add member initialization here //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); // the remembered drop target m_lastDropTarget = NULL; } void CSampleDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSampleDlg) // NOTE: the ClassWizard will add DDX and DDV calls here //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CSampleDlg, CDialog) ON_SFTTREEN_LBUTTONDBLCLK_TEXT(IDC_LEFTTREE, OnLButtonExpandCollapseLeft) ON_SFTTREEN_LBUTTONDOWN_BUTTON(IDC_LEFTTREE, OnLButtonExpandCollapseLeft) ON_SFTTREEN_LBUTTONDBLCLK_BUTTON(IDC_LEFTTREE, OnLButtonExpandCollapseLeft) ON_SFTTREEN_EXPANDALL(IDC_LEFTTREE, OnExpandAllLeft) ON_SFTTREEN_AUTOEXPANDING(IDC_LEFTTREE, OnAutoExpandLeft) ON_SFTTREEN_ENDDRAG(IDC_LEFTTREE, OnEndDragLeft) ON_SFTTREEN_BEGINDRAG(IDC_LEFTTREE, OnDraggingLeft) ON_SFTTREEN_DRAGGING(IDC_LEFTTREE, OnDraggingLeft) ON_SFTTREEN_CANCELDRAG(IDC_LEFTTREE, OnCancelDrag) ON_SFTTREEN_LBUTTONDBLCLK_TEXT(IDC_RIGHTTREE, OnLButtonExpandCollapseRight) ON_SFTTREEN_LBUTTONDOWN_BUTTON(IDC_RIGHTTREE, OnLButtonExpandCollapseRight) ON_SFTTREEN_LBUTTONDBLCLK_BUTTON(IDC_RIGHTTREE, OnLButtonExpandCollapseRight) ON_SFTTREEN_EXPANDALL(IDC_RIGHTTREE, OnExpandAllRight) ON_SFTTREEN_AUTOEXPANDING(IDC_RIGHTTREE, OnAutoExpandRight) ON_SFTTREEN_ENDDRAG(IDC_RIGHTTREE, OnEndDragRight) ON_SFTTREEN_BEGINDRAG(IDC_RIGHTTREE, OnDraggingRight) ON_SFTTREEN_DRAGGING(IDC_RIGHTTREE, OnDraggingRight) ON_SFTTREEN_CANCELDRAG(IDC_RIGHTTREE, OnCancelDrag) //{{AFX_MSG_MAP(CSampleDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSampleDlg message handlers BOOL CSampleDlg::OnInitDialog() { CDialog::OnInitDialog(); // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // INITIALIZE the left side tree control /* Associate the tree control created from the dialog */ /* resource with the C++ object. */ m_LeftTree.SubclassDlgItem(IDC_LEFTTREE, this /* parent window */); /* You could use DDX/DDV instead and add the following */ /* line to the DoDataExchange function of the tree */ /* control's parent window (remove the //). */ // DDX_Control(pDX, IDC_LEFTTREE, m_LeftTree); m_BgBitmap.LoadBitmap(IDB_BACKGROUND);/* Load a background bitmap */ m_LeftTree.SetBackgroundBitmap(m_BgBitmap);/* Define the background bitmap */ /* 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_LeftTree.SetPictures(aPic); /* Use item pictures */ } m_LeftTree.SetItemBitmapAlign(TRUE); /* Align item bitmaps */ m_LeftTree.SetTreeLineStyle(SFTTREE_TREELINE_DOT0);/* Dotted tree lines (incl. level 0) */ m_LeftTree.SetShowButtons(TRUE); /* Expand/collapse buttons (level 1..n) */ m_LeftTree.SetShowButton0(TRUE); /* Show expand/collapse buttons (level 0) */ m_LeftTree.SetButtons(SFTTREE_BUTTON_SIMPLE);/* Button style */ m_LeftTree.SetShowTruncated(TRUE); /* Show ... if truncated */ m_LeftTree.SetSelectionStyle(SFTTREE_SELECTION_CELL1);/* Select first cell only */ m_LeftTree.SetSelectionArea(SFTTREE_SELECTIONAREA_ALL);/* Selection changes by clicking anywhere on an item */ m_LeftTree.SetFlyby(TRUE); /* Flyby highlighting */ m_LeftTree.SetScrollTips(TRUE); /* Show Scrolltips */ m_LeftTree.SetInheritBgColor(TRUE); /* Inherit background color of first cell */ m_LeftTree.SetOpenEnded(TRUE); /* Last column width */ /* Define columns */ { SFTTREE_COLUMN_EX aCol[1] = { { 0, 0, /* Reserved */ 49, /* Width (in pixels) */ ES_LEFT, /* Cell alignment */ ES_LEFT, /* Title style */ _T("Title"), /* 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) */ 0, /* Column flag */ 0, /* Minimum column width */ } }; m_LeftTree.SetColumns(1, aCol); /* Set column attributes */ } m_LeftTree.SetShowRowHeader(SFTTREE_ROWSTYLE_BUTTONCOUNT0);/* Row style */ m_LeftTree.SetRowHeaderStyle(ES_LEFT | SFTTREE_HEADER_UP);/* Row header style */ m_LeftTree.SetDragBitmaps(TRUE); /* Allow drag & drop from item, label pictures */ m_LeftTree.SetDragType(SFTTREE_DRAG_PIXELIMM);/* Select and move by a number of pixels to start drag */ m_LeftTree.SetDropHighlightStyle(SFTTREE_DROPHIGHLIGHT_BETWEEN);/* Draw line to represent drop target */ m_LeftTree.SetCharSearchMode(SFTTREE_CHARSEARCH_ALLCHARS, -1);/* Consider all characters typed */ /* Change the default colors */ { SFTTREE_COLORS Colors; m_LeftTree.GetCtlColors(&Colors);/* Get current color settings */ Colors.colorSelBgNoFocus = COLOR_BTNFACE | 0x80000000L;/* Selection background color (no input focus) */ Colors.colorSelFgNoFocus = COLOR_BTNTEXT | 0x80000000L;/* Selection foreground color (no input focus) */ m_LeftTree.SetCtlColors(&Colors);/* Set new colors */ } // Add a few items int index; for (index = 3 ; index <= 30 ; ++index) { int i; CString str; str.Format(_T("Item %d"), index-3); i = m_LeftTree.AddString(str); m_LeftTree.SetItemLevel(i, abs(3 - (index % 6))); } /* Make row header width optimal, so text and pictures are */ /* not clipped horizontally. */ m_LeftTree.MakeRowHeaderOptimal(0, FALSE);/* Make row header width optimal */ m_LeftTree.RecalcHorizontalExtent(0, FALSE);/* Update horizontal scroll bar */ // INITIALIZE the right side tree control /* Associate the tree control created from the dialog */ /* resource with the C++ object. */ m_RightTree.SubclassDlgItem(IDC_RIGHTTREE, this /* parent window */); /* You could use DDX/DDV instead and add the following */ /* line to the DoDataExchange function of the tree */ /* control's parent window (remove the //). */ // DDX_Control(pDX, IDC_RIGHTTREE, m_RightTree); m_RightTree.SetTreeLineStyle(SFTTREE_TREELINE_AUTOMATIC0);/* Dotted or invisible tree lines (incl. level 0) */ m_RightTree.SetShowButtons(TRUE); /* Expand/collapse buttons (level 1..n) */ m_RightTree.SetShowButton0(TRUE); /* Show expand/collapse buttons (level 0) */ m_RightTree.SetButtons(SFTTREE_BUTTON_AUTOMATIC3);/* Automatic button style 3 */ m_RightTree.SetShowTruncated(TRUE); /* Show ... if truncated */ m_RightTree.SetShowFocus(FALSE); /* Don't show focus rectangle (caret) */ m_RightTree.SetSelectionArea(SFTTREE_SELECTIONAREA_ALL);/* Selection changes by clicking anywhere on an item */ m_RightTree.SetSelectionStyle(SFTTREE_SELECTION_CELL1 | SFTTREE_SELECTION_OUTLINE);/* Select first cell only using outline */ m_RightTree.SetFlyby(TRUE); /* Flyby highlighting */ m_RightTree.SetScrollTips(TRUE); /* Show Scrolltips */ m_RightTree.SetOpenEnded(TRUE); /* Last column width */ /* Define columns */ { SFTTREE_COLUMN_EX aCol[1] = { { 0, 0, /* Reserved */ 100, /* Width (in pixels) */ ES_LEFT, /* Cell alignment */ ES_LEFT, /* Title style */ _T("Title"), /* 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) */ 0, /* Column flag */ 0, /* Minimum column width */ } }; m_RightTree.SetColumns(1, aCol); /* Set column attributes */ } m_RightTree.SetDragBitmaps(TRUE); /* Allow drag & drop from item, label pictures */ m_RightTree.SetDragType(SFTTREE_DRAG_PIXELIMM);/* Select and move by a number of pixels to start drag */ m_RightTree.SetDropHighlightStyle(SFTTREE_DROPHIGHLIGHT_ONTOP);/* Highlight drop target */ m_RightTree.SetCharSearchMode(SFTTREE_CHARSEARCH_ALLCHARS, -1);/* Consider all characters typed */ // Add a few items for (index = 3 ; index <= 30 ; ++index) { int i; CString str; str.Format(_T("Item %d"), index-3); i = m_RightTree.AddString(str); m_RightTree.SetItemLevel(i, abs(3 - (index % 6))); } m_RightTree.RecalcHorizontalExtent(0, FALSE);/* Update horizontal scroll bar */ CenterWindow(); return TRUE; // return TRUE unless you set the focus to a control } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CSampleDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CSampleDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } // LEFT SIDE TREE CONTROL EVENTS /* 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 CSampleDlg::OnLButtonExpandCollapseLeft() { /* get index of item to expand/collapse */ int index = m_LeftTree.GetExpandCollapseIndex(); /* get current expand/collapsed status */ BOOL fExpanded = m_LeftTree.GetItemExpand(index); /* if control key is used we'll expand all dependents */ BOOL fDepth = (::GetKeyState(VK_CONTROL)&0x8000); if (fExpanded) m_LeftTree.Collapse(index, TRUE); else m_LeftTree.Expand(index, TRUE, fDepth); } /* Respond to numeric keypad multiply key. */ void CSampleDlg::OnExpandAllLeft() { /* get index of item to expand/collapse */ int index = m_LeftTree.GetExpandCollapseIndex(); m_LeftTree.Expand(index, TRUE, TRUE); } void CSampleDlg::OnAutoExpandLeft() { /* get index of item to expand/collapse */ int index = m_LeftTree.GetExpandCollapseIndex(); m_LeftTree.Expand(index, TRUE, FALSE); } void CSampleDlg::OnEndDragLeft() { /* The user dropped something */ LPSFTTREE_DRAGINFO lpInfo; int index; CString str, text; lpInfo = m_LeftTree.GetDragInfo(); if (lpInfo->hwnd != m_LeftTree.m_hWnd) { // The target is another window // In this example the "other" control could be the right tree control if (lpInfo->hwnd == m_RightTree.m_hWnd) { // target is left tree index = m_RightTree.GetDropHighlight(); text = _T("The drop target is item %d in the right tree control"); } else { index = -1; text = _T("There is no valid drop target"); } } else { // target is the right tree control index = m_LeftTree.GetDropHighlight(); text = _T("The drop target is item %d in the left tree control"); } // always clear drop targets. If you forget, or do it too late, // the vertical scrolling may still be active if (m_lastDropTarget) { m_lastDropTarget->SetDropHighlight(-1); m_lastDropTarget->StopAutoExpandTimer(); } m_lastDropTarget = NULL; str.Format(text, index); AfxMessageBox(str); } void CSampleDlg::OnDraggingLeft() { /* Drag & drop in progress, which was started on the left side tree */ LPSFTTREE_DRAGINFO lpInfo; lpInfo = m_LeftTree.GetDragInfo(); if (lpInfo->hwnd != m_LeftTree.m_hWnd) { // The target is another window // clear old drop target if (m_lastDropTarget) { m_lastDropTarget->SetDropHighlight(-1); m_lastDropTarget->StopAutoExpandTimer(); } m_lastDropTarget = NULL; // the target is another control, we have to set the cursor and // also update the drop target // In this example the "other" control could be the right tree control if (lpInfo->hwnd == m_RightTree.m_hWnd) { // target is right tree // set the drop OK cursor lpInfo->fDropOK = TRUE; lpInfo->hCursor = AfxGetApp()->LoadCursor(IDC_DRAG); // update the drop target in the right tree CPoint pt = lpInfo->ptDrag; ::MapWindowPoints(HWND_DESKTOP, m_RightTree.m_hWnd, &pt, 1); int index = m_RightTree.CalcIndexFromPointEx(&pt); m_RightTree.SetDropHighlight(index, TRUE); m_RightTree.StartAutoExpandTimer(index, FALSE, 0); // remember who is the drop target m_lastDropTarget = &m_RightTree; } } else { // left side tree is the drop target // clear old drop target if different if (m_lastDropTarget && m_lastDropTarget != &m_LeftTree) { m_lastDropTarget->SetDropHighlight(-1); m_lastDropTarget->StopAutoExpandTimer(); } m_lastDropTarget = &m_LeftTree; m_lastDropTarget->StartAutoExpandTimer(lpInfo->index, FALSE, 0); } } // RIGHT SIDE TREE CONTROL EVENTS /* 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 CSampleDlg::OnLButtonExpandCollapseRight() { /* get index of item to expand/collapse */ int index = m_RightTree.GetCaretIndex(); /* get current expand/collapsed status */ BOOL fExpanded = m_RightTree.GetItemExpand(index); /* if control key is used we'll expand all dependents */ BOOL fDepth = (::GetKeyState(VK_CONTROL)&0x8000); if (fExpanded) m_RightTree.Collapse(index, TRUE); else m_RightTree.Expand(index, TRUE, fDepth); } /* Respond to numeric keypad multiply key. */ void CSampleDlg::OnExpandAllRight() { /* get index of item to expand/collapse */ int index = m_RightTree.GetExpandCollapseIndex(); m_RightTree.Expand(index, TRUE, TRUE); } void CSampleDlg::OnAutoExpandRight() { /* get index of item to expand/collapse */ int index = m_RightTree.GetExpandCollapseIndex(); m_RightTree.Expand(index, TRUE, FALSE); } void CSampleDlg::OnEndDragRight() { /* The user dropped something */ LPSFTTREE_DRAGINFO lpInfo; int index; CString str, text; lpInfo = m_RightTree.GetDragInfo(); if (lpInfo->hwnd != m_RightTree.m_hWnd) { // The target is another window // In this example the "other" control could be the left tree control if (lpInfo->hwnd == m_LeftTree.m_hWnd) { // target is left tree index = m_LeftTree.GetDropHighlight(); text = _T("The drop target is item %d in the left tree control"); } else { index = -1; text = _T("There is no valid drop target"); } } else { // target is the right tree control index = m_RightTree.GetDropHighlight(); text = _T("The drop target is item %d in the right tree control"); } // always clear drop targets. If you forget, or do it too late, // the vertical scrolling may still be active if (m_lastDropTarget) { m_lastDropTarget->SetDropHighlight(-1); m_lastDropTarget->StopAutoExpandTimer(); } m_lastDropTarget = NULL; str.Format(text, index); AfxMessageBox(str); } void CSampleDlg::OnDraggingRight() { /* Drag & drop in progress, which was started on the right side tree */ LPSFTTREE_DRAGINFO lpInfo; lpInfo = m_RightTree.GetDragInfo(); if (lpInfo->hwnd != m_RightTree.m_hWnd) { // The target is another window // clear old drop target if (m_lastDropTarget) { m_lastDropTarget->SetDropHighlight(-1); m_lastDropTarget->StopAutoExpandTimer(); } m_lastDropTarget = NULL; // the target is another control, we have to set the cursor and // also update the drop target // In this example the "other" control could be the left tree control if (lpInfo->hwnd == m_LeftTree.m_hWnd) { // target is left tree // set the drop OK cursor lpInfo->fDropOK = TRUE; lpInfo->hCursor = AfxGetApp()->LoadCursor(IDC_DRAG); // update the drop target in the left tree CPoint pt = lpInfo->ptDrag; ::MapWindowPoints(HWND_DESKTOP, m_LeftTree.m_hWnd, &pt, 1); int index = m_LeftTree.CalcIndexFromPointEx(&pt); m_LeftTree.SetDropHighlight(index, TRUE); m_LeftTree.StartAutoExpandTimer(index, FALSE, 0); // remember who is the drop target m_lastDropTarget = &m_LeftTree; } } else { // right side tree is the drop target // clear old drop target if different if (m_lastDropTarget && m_lastDropTarget != &m_RightTree) { m_lastDropTarget->SetDropHighlight(-1); m_lastDropTarget->StopAutoExpandTimer(); } m_lastDropTarget = &m_RightTree; m_lastDropTarget->StartAutoExpandTimer(lpInfo->index, FALSE, 0); } } void CSampleDlg::OnCancelDrag() { // always clear drop targets if (m_lastDropTarget) { m_lastDropTarget->SetDropHighlight(-1); /* Visually clear drop target */ m_lastDropTarget->StopAutoExpandTimer(); m_lastDropTarget = NULL; } AfxMessageBox(_T("Drag & drop cancelled.")); }