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 a tree control in virtual mode, used to display a list with 1 million items.
The source code is located at C:\Program Files (x86)\Softelvdm\SftTree DLL 7.5\Samples\MFC\Virtual\SamplVw.cpp or C:\Program Files\Softelvdm\SftTree DLL 7.5\Samples\MFC\Virtual\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 "Virtual.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() ON_COMMAND(IDM_RESIZE, OnResize) //}}AFX_MSG_MAP ON_SFTTREEN_LBUTTONDBLCLK_COLUMNRES(IDC_TREE, OnLButtonDblClkColumnResize) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSampleView construction/destruction CSampleView::CSampleView() { m_fFirstDone = FALSE; m_Item.LoadBitmap(IDB_ITEM);/* Item bitmap */ } 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_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; /* Resources, such as bitmaps, should be loaded and must remain */ /* valid until the tree control is destroyed or no longer uses */ /* these. */ /* Initialize "virtual" data callback routines. The */ /* routines used are defined below. The callbacks are */ /* static functions so they don't have a 'this' pointer. */ /* We pass the 'this' pointer as userdata for the call- */ /* back routine. */ { SFTTREE_VIRTUALDEF virt = { SFTTREE_VERSION_700, (SFTTREE_DWORD_PTR)(LPVOID)this, VirtualStorageGetItemCallback, VirtualStorageReleaseItemCallback, }; if (!m_Tree.VirtualInitialize(&virt)) return -1; /* error handling goes here */ /* Set current number of items in the control. */ if (!m_Tree.VirtualCount(1000000L, 1000000L)) return -1; /* error handling goes here */ } m_Tree.SetShowHeader(TRUE); /* Show column headers */ m_BgBitmap.LoadBitmap(IDB_BACKGROUND);/* Load a background bitmap */ m_Tree.SetBackgroundBitmap(m_BgBitmap, SFTTREE_BGBITMAP_HSCROLL, SFTTREE_BGBITMAP_CENTER);/* Define the background bitmap */ 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.SetItemPictureAlign(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 */ Sft_InitPicture(&CellInfo.Cell.CellPicture1);/* Initialize */ m_CellBitmap.LoadBitmap(IDB_SMILE1);/* Cell picture */ m_Tree.SetCellInfo(&CellInfo); /* Register use of cell pictures */ /* Set individual cell pictures using this sample code: */ // SFTTREE_CELLINFOPARM CellInfo; // CellInfo.version = 7; // CellInfo.index = cell_index_to_change; // CellInfo.iCol = column_number_to_change; // m_Tree.GetCellInfo(&CellInfo); // /* m_CellBitmap.LoadBitmap(IDB_your_bitmap); *//* Cell picture */ // Sft_SetPictureBitmap(&CellInfo.Cell.CellPicture1, m_CellBitmap); // CellInfo.Cell.flag = SFTTREE_BMP_RIGHT; // m_Tree.SetCellInfo(&CellInfo); } m_Tree.SetTreeLineStyle(SFTTREE_TREELINE_NONE);/* No 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.SetSelectionStyle(SFTTREE_SELECTION_CELL1);/* Select first cell only */ m_Tree.SetSelectionArea(SFTTREE_SELECTIONAREA_ALL);/* Selection changes by clicking anywhere on an item */ m_Tree.SetFlyby(TRUE); /* Flyby highlighting */ m_Tree.SetScrollTips(TRUE); /* Show Scrolltips */ m_Tree.SetReorderColumns(TRUE); /* Column reordering */ m_Tree.SetOpenEnded(TRUE, TRUE); /* Left tree open ended*/ m_Tree.SetOpenEnded(TRUE, FALSE); /* Right tree open ended */ m_Tree.SetShowHeaderButtons(TRUE); /* Show column header as buttons */ /* Define columns */ { SFTTREE_COLUMN_EX aCol[3] = { { 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 */ 30, /* Minimum column width */ }, { 0, 0, /* Reserved */ 110, /* 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 */ 30, /* Minimum column width */ }, { 0, 0, /* Reserved */ 110, /* Width (in pixels) */ ES_LEFT | SFTTREE_TOOLTIP, /* Cell alignment */ ES_LEFT | SFTTREE_HEADER_UP, /* Title style */ _T("Third 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) */ 2, /* Display column number (display position) */ 0, /* Column flag */ 30, /* Minimum column width */ } }; m_Tree.SetColumns(3, aCol); /* Set column attributes */ m_Tree.SetSplitColumn(1); /* Column split position */ } m_Tree.SetShowRowHeader(SFTTREE_ROWSTYLE_BUTTONCOUNT0);/* Row style */ /* Register the row header picture size. All row header */ /* pictures used must be the same size. Only one picture */ /* needs to be registered, even if several are used. */ { SFTTREE_ROWINFOPARM RowInfo; RowInfo.version = 7; RowInfo.index = -1; m_RowBitmap.LoadBitmap(IDB_ROW);/* Row header picture */ Sft_InitPicture(&RowInfo.Row.RowPicture1); Sft_SetPictureBitmap(&RowInfo.Row.RowPicture1, m_RowBitmap); m_Tree.SetRowInfo(&RowInfo); /* Set individual row header bitmaps using: */ // SFTTREE_ROWINFOPARM RowInfo; // RowInfo.version = 7; // RowInfo.index = index; // m_Tree.GetRowInfo(&RowInfo); // /* m_RowBitmap.LoadBitmap(IDB_your_bitmap); *//* Row header picture */ // Sft_SetPictureBitmap(&RowInfo.Row.RowPicture1, m_RowBitmap); // RowInfo.Row.flag = SFTTREE_BMP_RIGHT; // m_Tree.SetRowInfo(&RowInfo); } m_Tree.SetRowColHeaderText(_T("?")); /* Row/column header text */ m_Tree.SetRowColHeaderStyle(ES_LEFT | SFTTREE_HEADER_UP);/* Row/column header style */ m_RowColBitmap.LoadBitmap(IDB_SMILE1);/* Row/column header picture */ 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.SetCharSearchMode(SFTTREE_CHARSEARCH_ALLCHARS, -1);/* Consider all characters typed */ /* Use a ToolTips callback routine */ { SFTTREE_TOOLTIPSPARM Parm; /* Parameter list */ Parm.lpfnToolTips = (SFTTREE_TOOLTIPSPROC) CSampleView::ToolTipsCallback;/* User supplied routine */ Parm.UserData = (SFTTREE_DWORD_PTR)0;/* User supplied data */ m_Tree.SetToolTipsCallback(&Parm); } /* Change the default colors */ { SFTTREE_COLORS Colors; m_Tree.GetCtlColors(&Colors); /* Get current color settings */ Colors.colorTreeLines = COLOR_3DDKSHADOW | 0x80000000L;/* Tree line color */ Colors.colorSelBgNoFocus = COLOR_BTNFACE | 0x80000000L;/* Selection background color (no input focus) */ Colors.colorSelFgNoFocus = COLOR_BTNTEXT | 0x80000000L;/* Selection foreground color (no input focus) */ m_Tree.SetCtlColors(&Colors); /* Set new colors */ } // In our example, we only consider 50 items when MakeColumnOptimal, MakeRowHeaderOptimal or // MakeSplitterOptimal is used. Because our sample data is wider at the end of the list, // we'll change the TopIndex to the very last few items. // That way the last 50 items are analyzed. In a typical application this is not necessary. m_Tree.SetTopIndex(m_Tree.GetCount() - 50); /* Make all column widths optimal, so text and pictures are */ /* not clipped horizontally. */ m_Tree.MakeColumnOptimal(-1, 50, TRUE);/* Make column widths optimal */ /* Make row header width optimal, so text and pictures are */ /* not clipped horizontally. */ m_Tree.MakeRowHeaderOptimal(50, TRUE);/* Make row header width optimal */ m_Tree.RecalcHorizontalExtent(50, TRUE);/* Update horizontal scroll bar */ m_Tree.SetTopIndex(0); return 0; } void CSampleView::OnSize(UINT nType, int cx, int cy) { CView::OnSize(nType, cx, cy); m_Tree.MoveWindow(0, 0, cx, cy); // when the window is created initially, it has a size of CRect(0,0,0,0) // so we'll have to optimize the splitter when the window is resized the // first time if (!m_fFirstDone && cx != 0 && cy != 0) { m_fFirstDone = TRUE; m_Tree.MakeSplitterOptimal(); /* Optimal splitter position */ } } /* Respond to events as the user double-clicks on the */ /* column resizing area. The events handled here can be */ /* changed to suit your application. */ void CSampleView::OnLButtonDblClkColumnResize() { /* Resize column optimally */ int realCol = m_Tree.GetResizeColumn(); if (realCol >= 0) { m_Tree.MakeColumnOptimal(-1, 50, TRUE);/* Make column width optimal */ m_Tree.RecalcHorizontalExtent(50, TRUE);/* Update horizontal scroll bar */ } else { m_Tree.MakeSplitterOptimal(); /* Optimal splitter position */ } } // Callback of type SFTTREE_TOOLTIPSPROC void CALLBACK CSampleView::ToolTipsCallback(HWND hwnd, LPTSTR lpszBuffer, int type, int index, int column, SFTTREE_DWORD_PTR UserData, BOOL FAR* fInPlace) { switch (type) { case SFTTREE_TOOLTIP_VSCROLL: /* Vertical scrolling */ wsprintf(lpszBuffer, _T("Item %d is on top"), index); break; case SFTTREE_TOOLTIP_CELL: /* Cell tooltip */ // If lpszBuffer is left as-is, the cell tooltip will be displayed, otherwise // the text in lpszBuffer will be shown as an explanatory tooltip. // we don't modify lpszBuffer, so we get the default in-place tooltip //wsprintf(lpszBuffer, TEXT("An explanatory tooltip for cell %d/%d"), index, column); break; case SFTTREE_TOOLTIP_COLUMN_HEADER: /* Column header tooltip */ wsprintf(lpszBuffer, _T("A tooltip for column %d"), column); break; default: /* unhandled type (future expansion) */ return; } } // Callback of type LPFNSFTTREE_VGETITEM void CSampleView::VGetItem(int totCols, LONG index, LPSFTTREE_ITEM FAR* lplpItem) { // All item information (including all strings) MUST remain valid until VReleaseItem // is called. For this reason, the strings must be allocated using "new" or be static and CANNOT be // objects located on the stack (i.e., NO local variables). memset(&m_WorkingItem, 0, sizeof(m_WorkingItem)); m_WorkingItem.level = 0; // Provide the level number (must be 0) m_WorkingItem.fShown = TRUE; // Must be shown (it's a flat list) m_WorkingItem.fEnabled = TRUE; // Item is enabled (visually) m_WorkingItem.dwdData = 0; // Userdata for this item (can be 0) m_WorkingItem.lpszRowHeader = NULL; // Row header text (can be NULL) if ((index % 6) == 0) /* Randomly change item bitmap */ Sft_SetPictureBitmap(&m_WorkingItem.ItemPicture, m_Item); // Allocate string array for cell text m_WorkingItem.alpszString = new LPTSTR[totCols]; // Create cell strings CString str; str.Format(_T("Item %09ld"), index); m_WorkingItem.alpszString[0] = new TCHAR[str.GetLength()+1]; lstrcpy(m_WorkingItem.alpszString[0], str); int col; for (col = 1 ; col < totCols ; ++col) { str.Format(_T("Column %d(%ld)"), col, index); m_WorkingItem.alpszString[col] = new TCHAR[str.GetLength()+1]; lstrcpy(m_WorkingItem.alpszString[col], str); } // (Optional) Allocate and initialize cells m_WorkingItem.aCells = new SFTTREE_CELL[totCols]; memset(m_WorkingItem.aCells, 0, totCols*sizeof(SFTTREE_CELL)); for (col = 0 ; col < totCols ; ++col) { LPSFTTREE_CELL lpCell = &m_WorkingItem.aCells[col]; lpCell->colorBg = lpCell->colorFg = lpCell->colorBgSel = lpCell->colorFgSel = SFTTREE_NOCOLOR; lpCell->hFont = NULL; lpCell->flag = SFTTREE_BMP_LEFT; Sft_InitPicture(&lpCell->CellPicture1); if ((index % 5) == 0 && col == 1) {/* Randomly add bitmaps */ Sft_SetPictureBitmap(&lpCell->CellPicture1, m_CellBitmap);/* Cell bitmap */ lpCell->flag |= SFTTREE_BMP_RIGHT;/* Cell bitmap */ } if (col == 2 && (index % 5) == 0) {/* Randomly change colors */ lpCell->colorBg = 0x80000000 | COLOR_BTNFACE; lpCell->colorFg = 0x80000000 | COLOR_BTNTEXT; } } // (Optional) Create row header information m_WorkingItem.lpRow = new SFTTREE_ROW; memset(m_WorkingItem.lpRow, 0, sizeof(SFTTREE_ROW)); m_WorkingItem.lpRow->colorBg = m_WorkingItem.lpRow->colorFg = SFTTREE_NOCOLOR; m_WorkingItem.lpRow->colorBgSel = m_WorkingItem.lpRow->colorFgSel = SFTTREE_NOCOLOR; Sft_InitPicture(&m_WorkingItem.lpRow->RowPicture1); if ((index % 8) == 0) {/*randomly add bitmaps */ Sft_SetPictureBitmap(&m_WorkingItem.lpRow->RowPicture1, m_RowBitmap); m_WorkingItem.lpRow->flag = SFTTREE_BMP_LEFT; /* Row header bitmap alignment */ } *lplpItem = &m_WorkingItem; } // Callback of type LPFNSFTTREE_VRELEASEITEM void CSampleView::VReleaseItem(int totCols, LONG index, LPSFTTREE_ITEM lpItem) { // free storage allocated during previous VGetItem call int col; if (m_WorkingItem.alpszString) { // free string array previously allocated for (col = 0 ; col < totCols ; ++col) { if (m_WorkingItem.alpszString[col]) delete m_WorkingItem.alpszString[col]; } delete m_WorkingItem.alpszString; m_WorkingItem.alpszString = NULL; } if (m_WorkingItem.aCells) { // free {popup "cells" pop_cell} previously allocated delete m_WorkingItem.aCells; m_WorkingItem.aCells = NULL; } if (m_WorkingItem.lpRow) { // free row information previously allocated delete m_WorkingItem.lpRow; m_WorkingItem.lpRow = NULL; // row header } } void CALLBACK CSampleView::VirtualStorageGetItemCallback(HWND hwnd, SFTTREE_DWORD_PTR UserData, int totCols, LONG index, LPSFTTREE_ITEM FAR* lplpItem) { // This is a static function, so there is no this pointer, but userData contains // the object's this pointer, so a real member function can be called. CSampleView* pTHIS = (CSampleView*)(LPVOID)UserData; // Call the object's member function. pTHIS->VGetItem(totCols, index, lplpItem); } void CALLBACK CSampleView::VirtualStorageReleaseItemCallback(HWND hwnd, SFTTREE_DWORD_PTR UserData, int totCols, LONG index, LPSFTTREE_ITEM lpItem) { // This is a static function, so there is no this pointer, but userData contains // the object's this pointer, so a real member function can be called. CSampleView* pTHIS = (CSampleView*)(LPVOID)UserData; // Call the object's member function. pTHIS->VReleaseItem(totCols, index, lpItem); } void CSampleView::OnResize() { m_Tree.EnterResizeMode(); }