This commit is contained in:
romkazvo
2023-08-07 19:29:24 +08:00
commit 34d6c5d489
4832 changed files with 1389451 additions and 0 deletions

View File

@@ -0,0 +1,498 @@
////////////////////////////////////////////////////////////////////////////
//
// Crytek Engine Source File.
// Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
// File name: treectrlex.cpp
// Version: v1.00
// Created: 1/8/2002 by Timur.
// Compilers: Visual Studio.NET
// Description:
// -------------------------------------------------------------------------
// History:
//
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "TreeCtrlEx.h"
// CTreeCtrlEx
IMPLEMENT_DYNAMIC(CTreeCtrlEx, CTreeCtrl)
CTreeCtrlEx::CTreeCtrlEx()
{
// When this tree is initialized, no dragging of course
m_bLDragging = false;
m_pDragImage = NULL;
m_hitemDrag = NULL;
m_hitemDrop = NULL;
m_dropCursor = LoadCursor(NULL,IDC_ARROW);
m_noDropCursor = LoadCursor(NULL,IDC_NO);
}
CTreeCtrlEx::~CTreeCtrlEx()
{
}
BEGIN_MESSAGE_MAP(CTreeCtrlEx, CTreeCtrl)
ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginDrag)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// CTreeCtrlEx message handlers
//////////////////////////////////////////////////////////////////////////
// CopyItem - Copies an item to a new location
// Returns - Handle of the new item
// hItem - Item to be copied
// htiNewParent - Handle of the parent for new item
// htiAfter - Item after which the new item should be created
HTREEITEM CTreeCtrlEx::CopyItem( HTREEITEM hItem, HTREEITEM htiNewParent,
HTREEITEM htiAfter /*= TVI_LAST*/ )
{
TV_INSERTSTRUCT tvstruct;
HTREEITEM hNewItem;
CString sText;
// get information of the source item
tvstruct.item.hItem = hItem;
tvstruct.item.mask = TVIF_CHILDREN | TVIF_HANDLE |
TVIF_IMAGE | TVIF_SELECTEDIMAGE;
GetItem(&tvstruct.item);
sText = GetItemText( hItem );
tvstruct.item.cchTextMax = sText.GetLength();
tvstruct.item.pszText = sText.LockBuffer();
// Insert the item at proper location
tvstruct.hParent = htiNewParent;
tvstruct.hInsertAfter = htiAfter;
tvstruct.item.mask = TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT;
hNewItem = InsertItem(&tvstruct);
sText.ReleaseBuffer();
// Now copy item data and item state.
SetItemData( hNewItem, GetItemData( hItem ));
SetItemState( hNewItem, GetItemState( hItem, TVIS_STATEIMAGEMASK | TVIS_EXPANDED ),
TVIS_STATEIMAGEMASK | TVIS_EXPANDED );
// Call virtual function to allow further processing in derived class
OnItemCopied( hItem, hNewItem );
return hNewItem;
}
//////////////////////////////////////////////////////////////////////////
void CTreeCtrlEx::OnItemCopied(HTREEITEM /*hItem*/, HTREEITEM /*hNewItem*/ )
{
// Virtual function
}
//////////////////////////////////////////////////////////////////////////
// CopyBranch - Copies all items in a branch to a new location
// Returns - The new branch node
// htiBranch - The node that starts the branch
// htiNewParent - Handle of the parent for new branch
// htiAfter - Item after which the new branch should be created
HTREEITEM CTreeCtrlEx::CopyBranch( HTREEITEM htiBranch, HTREEITEM htiNewParent,
HTREEITEM htiAfter /*= TVI_LAST*/ )
{
HTREEITEM hChild;
HTREEITEM hNewItem = CopyItem( htiBranch, htiNewParent, htiAfter );
SetItemState(hNewItem, GetItemState(htiBranch, 0xffffffff), 0xffffffff);
hChild = GetChildItem(htiBranch);
while( hChild != NULL)
{
// recursively transfer all the items
CopyBranch(hChild, hNewItem);
hChild = GetNextSiblingItem( hChild );
}
return hNewItem;
}
//////////////////////////////////////////////////////////////////////////
void CTreeCtrlEx::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
*pResult = 0;
m_hitemDrag = pNMTreeView->itemNew.hItem;
m_hitemDrop = NULL;
if (!IsDropSource(m_hitemDrag))
return;
m_pDragImage = CreateDragImage(m_hitemDrag); // get the image list for dragging
// CreateDragImage() returns NULL if no image list
// associated with the tree view control
if( !m_pDragImage )
return;
m_bLDragging = true;
// Calculate the offset to the hotspot
CPoint offsetPt(8,8); // Initialize a default offset
CPoint dragPt = pNMTreeView->ptDrag; // Get the Drag point
UINT nHitFlags = 0;
HTREEITEM htiHit = HitTest(dragPt, &nHitFlags);
if (NULL != htiHit)
{
// The drag point has Hit an item in the tree
CRect itemRect;
// Get the text bounding rectangle
if (GetItemRect(htiHit, &itemRect, TRUE))
{
// Calculate the new offset
offsetPt.y = dragPt.y - itemRect.top;
offsetPt.x = dragPt.x - (itemRect.left - GetIndent());
}
/*
if (GetItemRect(htiHit, &itemRect, FALSE))
{
// Count indent levels
HTREEITEM htiParent = htiHit;
int nIndentCnt = 0;
while (htiParent != NULL)
{
htiParent = GetParentItem(htiParent);
nIndentCnt++;
}
if (!(GetStyle() & TVS_LINESATROOT))
nIndentCnt--;
// Calculate the new offset
offsetPt.y = dragPt.y - itemRect.top;
offsetPt.x = dragPt.x - (nIndentCnt * GetIndent()) + GetScrollPos(SB_HORZ);
CImageList* pImageListState = GetImageList(TVSIL_STATE);
UINT nState = GetItemState( htiHit, LVIS_STATEIMAGEMASK );
if (pImageListState && nState)
{
(nState>>=12)--;
IMAGEINFO ImageInfo;
//State Image list
pImageListState->GetImageInfo(nState,&ImageInfo);
offsetPt.x -= (ImageInfo.rcImage.right-ImageInfo.rcImage.left);
}
}
*/
}
/*
CImageList* pList = GetImageList(TVSIL_STATE);
if (pList)
{
IMAGEINFO info;
pList->GetImageInfo(1, &info);
offsetPt.x -= info.rcImage.right-info.rcImage.left;
}
*/
// Begin the Drag operation using the Drag image and the calculated hotspot offset
m_pDragImage->BeginDrag(0, offsetPt);
//m_pDragImage->BeginDrag(0, CPoint(-15,-15));
POINT pt = pNMTreeView->ptDrag;
ClientToScreen( &pt );
m_pDragImage->DragEnter(NULL, pt);
SetCapture();
}
//////////////////////////////////////////////////////////////////////////
void CTreeCtrlEx::OnMouseMove(UINT nFlags, CPoint point)
{
HTREEITEM hitem;
UINT flags;
if (m_bLDragging)
{
POINT pt = point;
ClientToScreen( &pt );
CImageList::DragMove(pt);
hitem = HitTest(point, &flags);
if (m_hitemDrop != hitem)
{
CImageList::DragShowNolock(FALSE);
SelectDropTarget(hitem);
m_hitemDrop = hitem;
CImageList::DragShowNolock(TRUE);
}
if(hitem)
hitem = GetDropTarget(hitem);
if (hitem)
SetCursor(m_dropCursor);
else
SetCursor(m_noDropCursor);
}
CTreeCtrl::OnMouseMove(nFlags, point);
}
//////////////////////////////////////////////////////////////////////////
void CTreeCtrlEx::OnLButtonUp(UINT nFlags, CPoint point)
{
CTreeCtrl::OnLButtonUp(nFlags, point);
if (m_bLDragging)
{
m_bLDragging = false;
CImageList::DragLeave(this);
CImageList::EndDrag();
ReleaseCapture();
delete m_pDragImage;
// Remove drop target highlighting
SelectDropTarget(NULL);
m_hitemDrop = GetDropTarget(m_hitemDrop);
if(m_hitemDrop == NULL)
return;
if( m_hitemDrag == m_hitemDrop )
return;
Expand( m_hitemDrop, TVE_EXPAND ) ;
HTREEITEM htiNew = CopyBranch( m_hitemDrag, m_hitemDrop, TVI_LAST );
DeleteItem(m_hitemDrag);
SelectItem( htiNew );
}
}
void CTreeCtrlEx::OnLButtonDown(UINT nFlags, CPoint point)
{
// Set focus on tree when clicked.
SetFocus();
CTreeCtrl::OnLButtonDown(nFlags, point);
}
BOOL CTreeCtrlEx::PreTranslateMessage(MSG* pMsg)
{
if( pMsg->message == WM_KEYDOWN )
{
bool bHandledHere = false;
// When an item is being edited make sure the edit control
// receives certain important key strokes
if (GetKeyState( VK_CONTROL))
{
bHandledHere = true;
}
CString m_Test;
switch(pMsg->wParam)
{
case VK_RETURN:
//GetEditControl()->GetWindowText(m_Test);
//if(SetItemText(m_CurItem.p_Item, m_Test) == NULL)
//TRACE("Unable to Change Item Text(Enter Message)!!!\n");
bHandledHere = true;
break;
case VK_DELETE:
//GetEditControl()->SetWindowText("");
bHandledHere = true;
break;
case VK_ESCAPE:
break;
bHandledHere = true;
}
if (bHandledHere)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
return TRUE; // DO NOT process further
}
}
if (pMsg->message == WM_KEYDOWN && m_bLDragging)
{
if (pMsg->wParam == VK_ESCAPE)
{
m_bLDragging = false;
CImageList::DragLeave(NULL);
CImageList::EndDrag();
ReleaseCapture();
SelectDropTarget(NULL);
delete m_pDragImage;
m_pDragImage = NULL;
}
return TRUE; // DO NOT process further
}
return CTreeCtrl::PreTranslateMessage(pMsg);
}
//////////////////////////////////////////////////////////////////////////
BOOL CTreeCtrlEx::IsDropSource(HTREEITEM hItem)
{
if (m_bOnlyLeafsDrag)
{
if (GetParentItem(hItem) == TVI_ROOT)
return FALSE;
}
return TRUE; // all other items are valid sources
}
//////////////////////////////////////////////////////////////////////////
HTREEITEM CTreeCtrlEx::GetDropTarget(HTREEITEM hItem)
{
if (hItem != m_hitemDrag && hItem != GetParentItem(m_hitemDrag))
{
if (m_bOnlyLeafsDrag)
{
if (GetParentItem(hItem) != TVI_ROOT)
return GetParentItem(hItem);
}
HTREEITEM htiParent = hItem;
while((htiParent = GetParentItem( htiParent )) != NULL )
{
if( htiParent == m_hitemDrag )
return NULL;
}
return hItem;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
HTREEITEM CTreeCtrlEx::GetNextItem( HTREEITEM hItem, UINT nCode )
{
return CTreeCtrl::GetNextItem( hItem, nCode );
}
//////////////////////////////////////////////////////////////////////////
HTREEITEM CTreeCtrlEx::GetNextItem(HTREEITEM hItem)
{
HTREEITEM hti = NULL;
if (ItemHasChildren(hItem))
hti = GetChildItem(hItem); // return first child
if (hti == NULL) {
// return next sibling item
// Go up the tree to find a parent's sibling if needed.
while ((hti = GetNextSiblingItem(hItem)) == NULL)
{
if ((hItem = GetParentItem(hItem)) == NULL)
return NULL;
}
}
return hti;
}
//////////////////////////////////////////////////////////////////////////
HTREEITEM CTreeCtrlEx::FindNextItem(TV_ITEM* pItem, HTREEITEM hItem)
{
ASSERT(::IsWindow(m_hWnd));
TV_ITEM hNextItem;
//Clear Item data
ZeroMemory(&hNextItem, sizeof(hNextItem));
//The mask is used to retrieve the data to compare
hNextItem.mask = pItem->mask;
hNextItem.hItem = (hItem) ? GetNextItem(hItem) : GetRootItem();
//Prepare to compare pszText
//Testing pItem->pszText protects the code from a client setting the
//TVIF_TEXT bit but passing in a NULL pointer.
if((pItem->mask & TVIF_TEXT) && pItem->pszText)
{
hNextItem.cchTextMax = strlen(pItem->pszText);
if(hNextItem.cchTextMax)
hNextItem.pszText = new char[++hNextItem.cchTextMax];
}
while(hNextItem.hItem)
{
if(CompareItems(pItem, hNextItem))
{
//Copy all the information into pItem and return
memcpy(pItem, &hNextItem, sizeof(TV_ITEM));
//Free resources
if(hNextItem.pszText)
delete hNextItem.pszText;
return pItem->hItem;
}
//The mask is used to retrieve the data to compare and must be
//reset before calling Compare
hNextItem.mask = pItem->mask;
hNextItem.hItem = GetNextItem(hNextItem.hItem);
}
//Set hItem in pItem
pItem->hItem = NULL;
//Free resources
if(hNextItem.pszText)
delete hNextItem.pszText;
return NULL;
}
//////////////////////////////////////////////////////////////////////////
BOOL CTreeCtrlEx::CompareItems(TV_ITEM* pItem, TV_ITEM& tvTempItem)
{
//This call uses the .mask setting to just retrieve the values
//that the client wants to compare.
//Get all the data passed in by pItem
GetItem(&tvTempItem);
//Reset the mask so I can keep track of the matching attributes
tvTempItem.mask = 0;
if((pItem->mask & TVIF_STATE) &&
(pItem->state == tvTempItem.state))
tvTempItem.mask |= TVIF_STATE;
if((pItem->mask & TVIF_IMAGE) &&
(pItem->iImage == tvTempItem.iImage))
tvTempItem.mask |= TVIF_IMAGE;
if((pItem->mask & TVIF_PARAM) &&
(pItem->lParam == tvTempItem.lParam))
tvTempItem.mask |= TVIF_PARAM;
if((pItem->mask & TVIF_TEXT) &&
pItem->pszText && tvTempItem.pszText && //Don't compare if either is NULL
!strcmp(pItem->pszText, tvTempItem.pszText))
tvTempItem.mask |= TVIF_TEXT;
if((pItem->mask & TVIF_CHILDREN) &&
(pItem->cChildren == tvTempItem.cChildren))
tvTempItem.mask |= TVIF_CHILDREN;
if((pItem->mask & TVIF_SELECTEDIMAGE) &&
(pItem->iSelectedImage == tvTempItem.iSelectedImage))
tvTempItem.mask |= TVIF_SELECTEDIMAGE;
//If by this point these two values are the same.
//tvTempItem.hItem is the desired item
return (pItem->mask == tvTempItem.mask);
}