HTREEITEM CTreeCtrlEx::GetPrevSelectedItem( HTREEITEM hItem ) { for ( hItem = GetPrevVisibleItem( hItem ); hItem!=NULL; hItem = GetPrevVisibleItem( hItem ) ) if ( GetItemState( hItem, TVIS_SELECTED ) & TVIS_SELECTED ) return hItem; return NULL; }
void CLibraryFolderCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { if ( ( nChar == VK_UP || nChar == VK_DOWN ) && ( GetKeyState( VK_SHIFT ) & 0x8000 ) && m_bMultiSelect ) { if ( ! m_hFirstSelected ) { m_hFirstSelected = GetFirstSelectedItem(); ClearSelection( m_hFirstSelected ); } HTREEITEM hItemPrevSel = GetSelectedItem(); HTREEITEM hItemNext; if ( nChar == VK_UP ) hItemNext = GetPrevVisibleItem( hItemPrevSel ); else hItemNext = GetNextVisibleItem( hItemPrevSel ); if ( hItemNext ) { BOOL bReselect = ! ( GetItemState( hItemNext, TVIS_SELECTED ) & TVIS_SELECTED ); SelectItem( hItemNext ); if ( bReselect ) SetItemState( hItemPrevSel, TVIS_SELECTED, TVIS_SELECTED ); } NotifySelectionChanged(); return; } else if ( nChar >= VK_SPACE ) { m_hFirstSelected = NULL; ClearSelection(); } else if ( nChar == 'A' && ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) && m_bMultiSelect ) { BOOL bChanged = FALSE; for ( HTREEITEM hItem = GetRootItem() ; hItem != NULL ; hItem = GetNextItem( hItem, TVGN_NEXTVISIBLE ) ) { if ( ( GetItemState( hItem, TVIS_SELECTED ) & TVIS_SELECTED ) == 0 ) { SetItemState( hItem, TVIS_SELECTED, TVIS_SELECTED ); bChanged = TRUE; } } if ( bChanged ) NotifySelectionChanged(); return; } CTreeCtrl::OnKeyDown( nChar, nRepCnt, nFlags ); }
void CTreeCtrlFolder::SelectNextItem(BOOL selectNext) { HTREEITEM item = GetSelectedItem(); if (selectNext) item = GetNextVisibleItem(item); else item = GetPrevVisibleItem(item); if (item != NULL) { SelectItem(item); Inform(); } }
HTREEITEM CEditTreeCtrl::GetDropTarget(EDropHint & hint) { ASSERT(m_pDragData != 0); CPoint pt; GetCursorPos(&pt); ScreenToClient(&pt); UINT flags; HTREEITEM hDrop = HitTest(pt, &flags); hint = GetDropHint(flags); m_pDragData->SetDropTarget(hDrop); if(hDrop) { m_pDragData->DragLeave(); // allow updates SelectDropTarget(hDrop); if(m_pDragData->CheckExpand(hDrop)) Expand(hDrop, TVE_EXPAND); // Make sure the surrounding items are visible, too // This will scroll the tree if necessary. HTREEITEM hPrev = GetPrevVisibleItem(hDrop); if(hPrev) EnsureVisible(hPrev); HTREEITEM hNext = GetNextVisibleItem(hDrop); if(hNext) EnsureVisible(hNext); // if the drop target is a descendent of the dragged item, then // disallow dropping the item here... if(IsAncestor(m_pDragData->GetDragItem(), hDrop) || !CanDropItem(m_pDragData->GetDragItem(), hDrop, hint)) hint = DROP_NODROP; m_pDragData->DragEnter(pt); } else if(hint != DROP_NODROP && !CanDropItem(m_pDragData->GetDragItem(), hDrop, hint)) hint = DROP_NODROP; return hDrop; }
BOOL CMultiSelTreeCtrl::ScrollTree( int linesToScroll ) { BOOL moved= FALSE; HTREEITEM firstItem; HTREEITEM currentItem; if( linesToScroll < 0 ) { // Scrolling down firstItem=GetFirstVisibleItem(); long visible=GetVisibleCount(); int count=0; for(int i=0; i < visible - linesToScroll; i++) { currentItem= firstItem; firstItem= GetNextVisibleItem(currentItem); if( firstItem == NULL ) { firstItem= currentItem; break; } else count++; } if( count >= visible ) moved= TRUE; } else if( linesToScroll > 0 ) { // Scrolling up firstItem=GetFirstVisibleItem(); for(int i=0; i < linesToScroll; i++) { currentItem= firstItem; firstItem= GetPrevVisibleItem(currentItem); if( firstItem == NULL ) { firstItem= currentItem; break; } else moved= TRUE; } } else { ASSERT(0); return moved; } // Turn on redraws if(moved) { EnsureVisible(firstItem); // Redraw w/out erase to avoid slow video update RedrawWindow( NULL, NULL, RDW_UPDATENOW ); } return moved; }
void CTreeCtrlEx::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags ) { CWnd* pWnd = GetParent(); if ( nChar==VK_NEXT || nChar==VK_PRIOR ) { if ( !( GetKeyState( VK_SHIFT )&0x8000 ) ) { // User pressed Pg key without holding 'Shift': // Clear multiple selection (if multiple) and let base class do // normal selection work! if ( GetSelectedCount()>1 ) ClearSelection( TRUE ); CTreeCtrl::OnKeyDown( nChar, nRepCnt, nFlags ); m_hFirstSelectedItem = GetSelectedItem(); return; } // Flag signaling that selection process is NOT complete. // (Will prohibit TVN_SELCHANGED from being sent to parent) m_bSelectionComplete = FALSE; // Let base class select the item CTreeCtrl::OnKeyDown( nChar, nRepCnt, nFlags ); HTREEITEM hSelectedItem = GetSelectedItem(); // Then select items in between SelectItems( m_hFirstSelectedItem, hSelectedItem ); // Selection process is now complete. Since we have 'eaten' the TVN_SELCHANGED // notification provided by Windows' treectrl, we must now produce one ourselves, // so that our parent gets to know about the change of selection. m_bSelectionComplete = TRUE; if (pWnd) { NM_TREEVIEW tv; memset(&tv.itemOld, 0, sizeof(tv.itemOld)); tv.hdr.hwndFrom = GetSafeHwnd(); tv.hdr.idFrom = GetWindowLong(GetSafeHwnd(), GWL_ID); tv.hdr.code = TVN_SELCHANGED; tv.itemNew.hItem = hSelectedItem; tv.itemNew.state = GetItemState(hSelectedItem, 0xffffffff); tv.itemNew.lParam = GetItemData(hSelectedItem); tv.itemNew.mask = TVIF_HANDLE|TVIF_STATE|TVIF_PARAM; tv.action = TVC_UNKNOWN; pWnd->SendMessage(WM_NOTIFY, tv.hdr.idFrom, (LPARAM)&tv); } } else if ( nChar==VK_UP || nChar==VK_DOWN ) { // Find which item is currently selected HTREEITEM hSelectedItem = GetSelectedItem(); HTREEITEM hNextItem; if ( nChar==VK_UP ) hNextItem = GetPrevVisibleItem( hSelectedItem ); else hNextItem = GetNextVisibleItem( hSelectedItem ); if ( !( GetKeyState( VK_SHIFT )&0x8000 ) ) { // User pressed arrow key without holding 'Shift': // Clear multiple selection (if multiple) and let base class do // normal selection work! if ( GetSelectedCount()>1 ) ClearSelection( TRUE ); if ( hNextItem ) CTreeCtrl::OnKeyDown( nChar, nRepCnt, nFlags ); m_hFirstSelectedItem = GetSelectedItem(); return; } if ( hNextItem ) { // Flag signaling that selection process is NOT complete. // (Will prohibit TVN_SELCHANGED from being sent to parent) m_bSelectionComplete = FALSE; // If the next item is already selected, we assume user is // "moving back" in the selection, and thus we should clear // selection on the previous one BOOL bSelect = !( GetItemState( hNextItem, TVIS_SELECTED ) & TVIS_SELECTED ); // Select the next item (this will also deselect the previous one!) SelectItem( hNextItem ); // Now, re-select the previously selected item if ( bSelect || ( !( GetItemState( hSelectedItem, TVIS_SELECTED ) & TVIS_SELECTED ) ) ) SelectItems( m_hFirstSelectedItem, hNextItem ); // Selection process is now complete. Since we have 'eaten' the TVN_SELCHANGED // notification provided by Windows' treectrl, we must now produce one ourselves, // so that our parent gets to know about the change of selection. m_bSelectionComplete = TRUE; if (pWnd) { NM_TREEVIEW tv; memset(&tv.itemOld, 0, sizeof(tv.itemOld)); tv.hdr.hwndFrom = GetSafeHwnd(); tv.hdr.idFrom = GetWindowLong(GetSafeHwnd(), GWL_ID); tv.hdr.code = TVN_SELCHANGED; tv.itemNew.hItem = hNextItem; tv.itemNew.state = GetItemState(hNextItem, 0xffffffff); tv.itemNew.lParam = GetItemData(hNextItem); tv.itemNew.mask = TVIF_HANDLE|TVIF_STATE|TVIF_PARAM; tv.action = TVC_UNKNOWN; pWnd->SendMessage(WM_NOTIFY, tv.hdr.idFrom, (LPARAM)&tv); } } // Since the base class' OnKeyDown() isn't called in this case, // we must provide our own TVN_KEYDOWN notification to the parent CWnd* pWnd = GetParent(); if ( pWnd ) { NMTVKEYDOWN tvk; tvk.hdr.hwndFrom = GetSafeHwnd(); tvk.hdr.idFrom = GetWindowLong( GetSafeHwnd(), GWL_ID ); tvk.hdr.code = TVN_KEYDOWN; tvk.wVKey = nChar; tvk.flags = 0; pWnd->SendMessage( WM_NOTIFY, tvk.hdr.idFrom, (LPARAM)&tvk ); } } else // Behave normally CTreeCtrl::OnKeyDown( nChar, nRepCnt, nFlags ); }