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 cell editing using an edit control and a combo box, with cell navigation and restricted cells.
The source code is located at C:\Program Files (x86)\Softelvdm\SftTree DLL 7.5\Samples\MFC\CellEditing\SamplVw.cpp or C:\Program Files\Softelvdm\SftTree DLL 7.5\Samples\MFC\CellEditing\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 "CellEditing.h" #include "sampldoc.h" #include "samplvw.h" ///////////////////////////////////////////////////////////////////////////// // 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_LBUTTONDOWN_TEXT(IDC_TREE, OnStartEdit) ON_SFTTREEN_QUITEDIT(IDC_TREE, OnQuitEdit) ON_SFTTREEN_VALIDATEEDIT(IDC_TREE, OnValidateEdit) ON_SFTTREEN_KEYINTERCEPTED(IDC_TREE, OnKeyIntercepted) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CSampleView construction/destruction CSampleView::CSampleView() { m_pEdit = NULL; /* No cell editing */ m_pCombo = NULL; } 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 */ 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_AUTOMATIC0);/* Dotted or invisible tree lines (incl. level 0) */ m_Tree.SetShowButtons(FALSE); /* Expand/collapse buttons (level 1..n) */ m_Tree.SetShowButton0(TRUE); /* Show expand/collapse buttons (level 0) */ m_Tree.SetButtons(SFTTREE_BUTTON_AUTOMATIC3);/* Automatic button style 3 */ 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 | SFTTREE_SELECTION_OUTLINE);/* Select first cell only using outline */ m_Tree.SetSelectionArea(SFTTREE_SELECTIONAREA_ALLCELLS);/* Selection changes by clicking on an item's cells */ m_Tree.SetFlyby(TRUE); /* Flyby highlighting */ m_Tree.SetUpdateCaretExpandCollapse(FALSE);/* don't update caret location when expand/collapse button clicked */ m_Tree.SetScrollTips(TRUE); /* Show Scrolltips */ m_Tree.SetInheritBgColor(TRUE); /* Inherit background color of first cell */ 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[3] = { { 0, 0, /* Reserved */ 221, /* 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) */ 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) */ 0, /* Column flag */ 0, /* Minimum column width */ }, { 0, 0, /* Reserved */ 100, /* 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 */ 0, /* Minimum column width */ } }; m_Tree.SetColumns(3, 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 */ m_RowColBitmap.LoadBitmap(IDB_SMILE);/* Cell picture */ 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_ALLCHARSWRAP2, -1);/* Consider all characters typed, find next item, wrap around, don't expand */ /* 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 */ } /*------------------------------------------------------------------------------*/ /* Add a few items. */ /*------------------------------------------------------------------------------*/ { int index; index = m_Tree.AddString(TEXT("Click on a cell to edit"));/* Add an item */ m_Tree.SetText(index, 1, TEXT("Use Tab/Return keys"));/* Set text in next column */ m_Tree.SetText(index, 2, TEXT("Use arrow keys"));/* Set text in next column */ index = m_Tree.AddString(TEXT("This sample supports cell navigation"));/* Add an item */ m_Tree.SetText(index, 1, TEXT("Ctrl+Home and Ctrl+End"));/* Set text in next column */ } for (int i = 0 ; i < 50 ; ++i) { int index; index = m_Tree.AddString(_T("An item"));/* Add an item */ m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */ m_Tree.SetText(index, 2, _T("3rd Column"));/* Set text in next column */ index = m_Tree.AddString(_T("Another item"));/* Add another item */ m_Tree.SetText(index, 1, _T("2nd Column"));/* Set text in next column */ m_Tree.SetText(index, 2, _T("3rd Column"));/* Set text in next column */ m_Tree.SetItemLevel(index, 1);/* change level */ index = m_Tree.AddString(_T("This item can't be edited"));/* Add another item */ m_Tree.SetItemEditIgnore(index, TRUE); m_Tree.SetItemLevel(index, 2);/* change level */ m_Tree.SetText(index, 1, _T("2nd Column (can't edit this item)"));/* Set text in next column */ m_Tree.SetText(index, 2, _T("3rd Column (can't edit this item)"));/* Set text in next column */ index = m_Tree.AddString(_T("A fourth item"));/* Add another item */ m_Tree.SetItemLevel(index, 1);/* change level */ m_Tree.SetText(index, 1, _T("This cell can't be edited"));/* Set text in next column */ SFTTREE_CELLINFOPARM CellInfo; CellInfo.version = 7; CellInfo.index = index; CellInfo.iCol = 1; m_Tree.GetCellInfo(&CellInfo); CellInfo.Cell.flag2 |= SFTTREECELL_EDITIGNORE; // can't edit this column m_Tree.SetCellInfo(&CellInfo); m_Tree.SetText(index, 2, _T("3rd Column"));/* Set text in next column */ /* Set a cell bitmap */ CellInfo.version = 7; CellInfo.index = index; CellInfo.iCol = 1; m_Tree.GetCellInfo(&CellInfo); Sft_SetPictureBitmap(&CellInfo.Cell.CellPicture1, m_CellBitmap); m_Tree.SetCellInfo(&CellInfo); } /*------------------------------------------------------------------------------*/ /* 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 */ m_Tree.SetCurSel(0); // select the first item m_Tree.SetCaretIndex(0); // and make it current 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 */ } } /* These routines handle item data editing. In this */ /* example, an edit control is used. Any Windows control */ /* can be used, even custom controls. */ void CSampleView::OnLButtonDownText() { int index, col; index = m_Tree.GetCaretIndex();/* Get item index */ col = m_Tree.GetCaretColumn();/* Get column number */ StartEdit(index, col); } /* Start editing in response to a */ /* SFTTREEN_LBUTTONDOWN_TEXT notification. */ void CSampleView::StartEdit(int index, int col) { CRect rect; /* Make the cell completely visible */ m_Tree.MakeCellVisible(index, col); /* get the item location */ if (!m_Tree.GetDisplayCellRect(index, col, TRUE, &rect, NULL)) return; /* No column active */ if (m_Tree.GetItemEditIgnore(index)) return; // this item can't be edited SFTTREE_CELLINFOPARM CellInfo; CellInfo.version = 7; CellInfo.index = index; CellInfo.iCol = col; m_Tree.GetCellInfo(&CellInfo); if (CellInfo.Cell.flag2 & SFTTREECELL_EDITIGNORE) return; // this item can't be edited m_editIndex = index; /* save position */ m_editCol = col; m_Tree.SetCurSel(index); // <<<< added: selection follows item being edited m_Tree.SetCaretIndex(index); // <<<< added: selection follows item being edited /* Change selection style to not shown anything */ m_Tree.SetNoFocusStyle(SFTTREE_NOFOCUS_NOTHING); /* Copy the text found in the tree control */ CString str; m_Tree.GetText(m_editIndex, m_editCol, str); m_Tree.AdjustCellEditRect(m_editIndex, m_editCol, &rect); CWnd* pEditParent = m_Tree.GetCellEditWindow(m_editIndex, m_editCol); // based on font height, get best height for the control used for cell editing CFont* pFont = m_Tree.GetFont(); int diff; TEXTMETRIC tm; CDC* pDC = GetDC(); CFont* pFontOld = (CFont*) pDC->SelectObject(pFont); pDC->GetTextMetrics(&tm); // Get Font Information pDC->SelectObject(pFontOld); ReleaseDC(pDC); diff = (tm.tmHeight + 5) - (rect.bottom-rect.top); rect.InflateRect(0, (diff+1)/2); int height; height = rect.bottom-rect.top; if (col != 1) { /* Create the edit control.*/ /* Based on the tree control attributes and your preference, you may */ /* have to adjust the rectangle used for the edit control. */ m_pEdit = new CEdit; m_pEdit->Create( WS_CHILD|WS_BORDER|ES_LEFT|ES_AUTOHSCROLL, /* Styles */ rect, /* Coordinates */ pEditParent, /* Parent window */ IDC_EDIT); /* <-- provide unique ID */ /* Set some edit control attributes */ m_pEdit->SetWindowText(str); /* Set the font defined for cell editing */ m_pEdit->SetFont(pFont, FALSE); /* Select all text in the edit control and display it */ m_pEdit->LimitText(80); m_pEdit->SetSel(0, -1, TRUE); m_pEdit->ShowWindow(SW_SHOW); m_pEdit->SetFocus(); /* Set input focus to the control */ } else { /* Create the combo box */ RECT comboRect; comboRect = rect; comboRect.bottom = comboRect.top + (comboRect.bottom-comboRect.top)*8; m_pCombo = new CComboBox; m_pCombo->Create(WS_CHILD|WS_BORDER|WS_VSCROLL|CBS_DROPDOWN|CBS_AUTOHSCROLL, /* Styles */ comboRect, pEditParent, /* Tree control */ IDC_COMBO); /* <-- provide unique ID */ /* Set the font defined for cell editing */ m_pCombo->SetFont(pFont, FALSE); // Add possible selections m_pCombo->AddString(_T("Selection 1")); m_pCombo->AddString(_T("Selection 2")); m_pCombo->AddString(_T("Selection 3")); m_pCombo->SetWindowText(str); m_pCombo->LimitText(80); m_pCombo->SetItemHeight(-1, rect.bottom-rect.top-5); m_pCombo->ShowWindow(SW_SHOW); m_pCombo->SetFocus(); /* Set input focus to the control */ m_pCombo->ShowDropDown(); } // The following has been added to support key handling while cell editing // It is used to define keys to be intercepted { BYTE KeyTable[256]; m_Tree.GetKeyHandling(KeyTable, NULL, NULL); KeyTable[VK_TAB] = (SFTTREE_HANDLEPURE|SFTTREE_HANDLESHIFT|SFTTREE_HANDLECTRL);// handle Tab key KeyTable[VK_RETURN] = (SFTTREE_HANDLEPURE|SFTTREE_HANDLESHIFT|SFTTREE_HANDLECTRL);// handle Return key KeyTable[VK_HOME] = (SFTTREE_HANDLECTRL);// handle Control+Home key KeyTable[VK_END] = (SFTTREE_HANDLECTRL);// handle Control+End key if (m_pCombo) { KeyTable[VK_UP] = 0; // don't handle Up arrow key KeyTable[VK_DOWN] = 0; // don't handle Down arrow key } else { KeyTable[VK_UP] = (SFTTREE_HANDLEPURE);// handle Up arrow key KeyTable[VK_DOWN] = (SFTTREE_HANDLEPURE);// handle Down arrow key } m_Tree.SetKeyHandling(KeyTable); } m_Tree.UpdateWindow(); } void CSampleView::OnStartEdit() { /* Get cell to edit (honors cell merging) */ int index, col; index = m_Tree.GetCaretIndex(); /* Get item index */ col = m_Tree.GetCaretColumn(); /* Get column number */ StartEdit(index, col); } void CSampleView::CellNavigation(TCHAR vKey, BYTE vMask) { // Here we handle special keys to implement cell editing with // cell navigation. Cell navigation is not automatic, but using this // sample code, a sophisticated editing scheme can be easily implemented, // even with skipped columns, hidden columns, collapsed items, etc. // Keep in mind that col is a REAL column number, but we have // to deal in DISPLAY columns as the user may have reordered the // columns. When using cell navigation, we want to move through the // displayed columns // Please note that cell merging is not supported. int index = m_editIndex, col = m_editCol; int dispCol, firstDispCol, lastDispCol; LPSFTTREE_COLUMN_EX lpCol; int nCols; int lastShown = m_Tree.GetPrevShown(-1); // get general information about tree control and columns nCols = m_Tree.GetColumns(&lpCol);/* Get column attributes */ dispCol = m_Tree.GetDisplayColumn(col); firstDispCol = m_Tree.GetFirstDisplayColumn(); lastDispCol = m_Tree.GetLastDisplayColumn(); if (vKey == VK_HOME && (vMask & SFTTREE_HANDLECTRL)) { // Control+Home index = 0; dispCol = firstDispCol; vKey = VK_RIGHT; // if index/dispCol can't be edited, search a cell in this direction: } else if (vKey == VK_END && (vMask & SFTTREE_HANDLECTRL)) { // Control+End index = m_Tree.GetPrevShown(-1); dispCol = lastDispCol; vKey = VK_LEFT; // if index/dispCol can't be edited, search a cell in this direction: } else if ((vKey == VK_LEFT && (vMask & SFTTREE_HANDLEPURE)) || (vKey == VK_TAB && (vMask & SFTTREE_HANDLESHIFT))) { // Left Arrow or Shift+Tab dispCol--; vKey = VK_LEFT; // if index/dispCol can't be edited, search a cell in this direction: } else if ((vKey == VK_RIGHT || vKey == VK_TAB) && (vMask & SFTTREE_HANDLEPURE)) { // Right Arrow or Tab dispCol++; vKey = VK_RIGHT; // if index/dispCol can't be edited, search a cell in this direction: } else if (vKey == VK_RETURN && (vMask & SFTTREE_HANDLEPURE)) { // Return dispCol++; vKey = VK_RIGHT; // if index/dispCol can't be edited, search a cell in this direction: } else if (vKey == VK_UP && (vMask & SFTTREE_HANDLEPURE)) { // Up arrow index--; } else if (vKey == VK_DOWN && (vMask & SFTTREE_HANDLEPURE)) { // Down arrow index++; } else return; // this key is not handled // index, dispCol has possible cell coordinates. If this cell can't be // edited, proceed in vKey direction (VK_UP,VK_LEFT,VK_DOWN,VK_RIGHT only) // until a suitable cell is found or until we hit m_editIndex, m_editCol. for ( ; ; ) { // position to a valid cell if (dispCol < firstDispCol) { index = m_Tree.GetPrevShown(index);// try previous item dispCol = lastDispCol; } if (dispCol > lastDispCol) { index = m_Tree.GetNextShown(index);// try next item if (index < 0) index = 0; dispCol = firstDispCol; } if (index < 0) index = lastShown; if (index > lastShown) index = 0; col = m_Tree.GetRealColumn(dispCol); // make sure the item is shown if (m_Tree.GetItemShown(index)) { // make sure the column is really displayed if (lpCol[col].width > 0) { // back at m_editIndex, m_editCol? if (m_editIndex == index && m_editCol == col) { StartEdit(index, col); return; } // check if item ignored if (!m_Tree.GetItemEditIgnore(index)) { // item not ignored // check if cell ignored SFTTREE_CELLINFOPARM CellInfo; CellInfo.version = 7; CellInfo.index = index; CellInfo.iCol = col; m_Tree.GetCellInfo(&CellInfo); if ((CellInfo.Cell.flag2 & SFTTREECELL_EDITIGNORE) == 0) { // cell not ignored StartEdit(index, col); return; } } } } // next cell if (vKey == VK_LEFT) { --dispCol; } else if (vKey == VK_RIGHT) { ++dispCol; } else if (vKey == VK_UP) { --index; } else if (vKey == VK_DOWN) { ++index; } } } /* Quit editing in response to a SFTTREEN_QUITEDIT */ /* notification. */ void CSampleView::OnQuitEdit() { /* If the control has the focus, set the focus back to the */ /* tree control after destroying the control */ BOOL fHadFocus = (GetFocus() == m_pEdit || GetFocus() == m_pCombo); if (m_pEdit) { m_pEdit->DestroyWindow(); delete m_pEdit; m_pEdit = NULL; } else if (m_pCombo) { m_pCombo->DestroyWindow(); delete m_pCombo; m_pCombo = NULL; } /* Restore nofocus display method */ m_Tree.SetNoFocusStyle(SFTTREE_NOFOCUS_KEEPSEL); if (fHadFocus) m_Tree.SetFocus(); } /* Validate edit data in response to a */ /* SFTTREEN_VALIDATEEDIT notification. */ void CSampleView::OnValidateEdit() { CString str; if (m_pEdit) { /* Get the text from the edit control */ m_pEdit->GetWindowText(str); /* Validate the data */ if (str == _T("")) { AfxMessageBox(_T("Just to demonstrate data input validation, this example rejects empty cells. Please enter some data.")); m_pEdit->SetFocus(); return; } else { m_pEdit->DestroyWindow(); delete m_pEdit; m_pEdit = NULL; } } else { /* Get the text from the combo control */ m_pCombo->GetWindowText(str); m_pCombo->GetWindowText(str); /* Validate the data */ if (str == _T("")) { AfxMessageBox(_T("Just to demonstrate data input validation, this example rejects empty cells. Please enter some data.")); m_pEdit->SetFocus(); return; } else { m_pCombo->DestroyWindow(); delete m_pCombo; m_pCombo = NULL; } } /* Save the data in the tree control */ m_Tree.SetText(m_editIndex, m_editCol, str); /* Restore nofocus display method */ m_Tree.SetNoFocusStyle(SFTTREE_NOFOCUS_KEEPSEL); } // The following has been added to support key handling while cell editing void CSampleView::OnKeyIntercepted() { TCHAR vKey; BYTE vMask; m_Tree.GetKeyHandling(NULL, &vKey, &vMask); switch (vKey) { case VK_TAB: // Tab key case VK_RETURN: // Return key case VK_UP: // Up arrow key case VK_DOWN: // Down arrow key case VK_HOME: // Home key case VK_END: // End key OnValidateEdit(); // validate the contents if (CellEditing()) // we're still editing (validation failed) break; CellNavigation(vKey, vMask); break; } }