📄 supergridctrl.cpp
字号:
}
else
if(nIndex > nListItem && nCurIndent < iIndent)
{
//draw |
pDC->MoveTo(xLine, yDown);
pDC->LineTo(xLine, rcBounds.bottom);
break;
}
}
pSelItem = pParent;//next
}
//draw plus/minus sign
if(bChild)
{
CRectangle rect(this, pDC, iIndent, rcBounds);
rect.DrawRectangle(this);
CPen* pPenPlusMinus = pDC->SelectObject(&m_psPlusMinus);
if(bCollapsed)
rect.DrawPlus();
else {
rect.DrawMinus();
//draw line up to parent folder
CPen* pLine = pDC->SelectObject(&m_psTreeLine);
int nOffset = (rcBounds.Height() - m_cyImage)/2;
pDC->MoveTo(rect.GetLeft()+ m_cxImage, rcBounds.top + m_cyImage+nOffset);
pDC->LineTo(rect.GetLeft() + m_cxImage, rcBounds.bottom);
pDC->SelectObject(pLine);
}
pDC->SelectObject(pPenPlusMinus);
}
pDC->SelectObject(pPenTreeLine);
}
//walk all over the place setting the hide/show flag of the nodes.
//it also deletes items from the listviewctrl.
void CSuperGridCtrl::HideChildren(CTreeItem *pItem, BOOL bHide,int nItem)
{
if(!IsCollapsed(pItem))
if(ItemHasChildren(pItem))
{
Hide(pItem, bHide);
POSITION pos = pItem->m_listChild.GetHeadPosition();
while (pos != NULL)
{
HideChildren((CTreeItem *)pItem->m_listChild.GetNext(pos),bHide,nItem+1);
DeleteItem(nItem);
}
}
}
void CSuperGridCtrl::Collapse(CTreeItem *pItem)
{
if(pItem != NULL && ItemHasChildren(pItem))
{
SetRedraw(0);
int nIndex = NodeToIndex(pItem);
HideChildren(pItem, TRUE, nIndex+1);
InternaleUpdateTree();
SetRedraw(1);
}
}
void CSuperGridCtrl::ExpandAll(CTreeItem *pItem, int& nScroll)
{
const int nChildren = pItem->m_listChild.GetCount();
if (nChildren > 0)
{
int nIndex = NodeToIndex(pItem);
nScroll = Expand(pItem, nIndex);
}
POSITION pos = pItem->m_listChild.GetHeadPosition();
while (pos)
{
CTreeItem *pChild = (CTreeItem*)pItem->m_listChild.GetNext(pos);
ExpandAll(pChild, nScroll);
}
}
int CSuperGridCtrl::Expand(CTreeItem* pSelItem, int nIndex)
{
if(ItemHasChildren(pSelItem) && IsCollapsed(pSelItem))
{
LV_ITEM lvItem;
lvItem.mask = LVIF_INDENT ;
lvItem.iItem = nIndex;
lvItem.iSubItem = 0;
lvItem.lParam=(LPARAM)pSelItem;
lvItem.iIndent = GetIndent(pSelItem);
// lvItem.iImage = pSelItem->m_lpNodeInfo->m_iImage;
SetItem(&lvItem);
Hide(pSelItem, FALSE);
//expand children
POSITION pos = pSelItem->m_listChild.GetHeadPosition();
while(pos != NULL)
{
CTreeItem* pNextNode = (CTreeItem*)pSelItem->m_listChild.GetNext(pos);
CString str = GetData(pNextNode)->GetItemText();
LV_ITEM lvItem;
lvItem.mask = LVIF_TEXT | LVIF_INDENT | LVIF_PARAM | LVIF_IMAGE;
lvItem.pszText =str.GetBuffer(1);
lvItem.iItem = nIndex + 1;
lvItem.iSubItem = 0;
lvItem.lParam=(LPARAM)pNextNode;
lvItem.iIndent = GetIndent(pSelItem)+1;
lvItem.iImage = pNextNode->m_lpNodeInfo->GetImage();
CListCtrl::InsertItem(&lvItem);
if(GetData(pNextNode)->GetCheck())
SetCheck(nIndex + 1);
//get subitems
int nSize = GetData(pNextNode)->GetItemCount();
for(int i=0; i< nSize;i++)
{
CString str=GetData(pNextNode)->GetSubItem(i);
lvItem.mask = LVIF_TEXT;
lvItem.iSubItem = i+1;
lvItem.pszText=str.GetBuffer(1);
SetItem(&lvItem);
}
nIndex++;
}
}
InternaleUpdateTree();
return nIndex;
}
int CSuperGridCtrl::SelectNode(CTreeItem *pLocateNode)
{
if(IsRoot(pLocateNode))
{
UINT uflag = LVIS_SELECTED | LVIS_FOCUSED;
SetItemState(0, uflag, uflag);
return 0;
}
int nSelectedItem=-1;
CTreeItem* pNode = pLocateNode;
CTreeItem* pTopLevelParent=NULL;
//Get top parent
while(1)
{
CTreeItem *pParent = GetParentItem(pLocateNode);
if(IsRoot(pParent))
break;
pLocateNode = pParent;
}
pTopLevelParent = pLocateNode;//on top of all
//Expand the folder
if(pTopLevelParent != NULL)
{
SetRedraw(0);
CWaitCursor wait;
CTreeItem *pRoot = GetParentItem(pTopLevelParent);
if(IsCollapsed(pRoot))
//old Expand(pRoot,0);
Expand(pRoot, NodeToIndex(pRoot)); // Yep! Now it's right!
ExpandUntil(pTopLevelParent, pNode);
UINT uflag = LVIS_SELECTED | LVIS_FOCUSED;
nSelectedItem = NodeToIndex(pNode);
SetItemState(nSelectedItem, uflag, uflag);
SetRedraw(1);
EnsureVisible(nSelectedItem, TRUE);
}
return nSelectedItem;
}
void CSuperGridCtrl::ExpandUntil(CTreeItem *pItem, CTreeItem* pStopAt)
{
const int nChildren = pItem->m_listChild.GetCount();
if (nChildren > 0)
{
POSITION pos = pItem->m_listChild.GetHeadPosition();
while (pos)
{
CTreeItem *pChild = (CTreeItem*)pItem->m_listChild.GetNext(pos);
if(pChild == pStopAt)
{
int nSize = GetIndent(pChild);
CTreeItem** ppParentArray = new CTreeItem*[nSize];
int i=0;
while(1)
{
CTreeItem *pParent = GetParentItem(pChild);
if(IsRoot(pParent))
break;
pChild = pParent;
ppParentArray[i] = pChild;
i++;
}
for(int x=i; x > 0; x--)
{
CTreeItem *pParent = ppParentArray[x-1];
Expand(pParent, NodeToIndex(pParent));
}
delete [] ppParentArray;
return;
}
}
}
POSITION pos = pItem->m_listChild.GetHeadPosition();
while (pos)
{
CTreeItem *pChild = (CTreeItem*)pItem->m_listChild.GetNext(pos);
ExpandUntil(pChild, pStopAt);
}
}
void CSuperGridCtrl::DeleteItemEx(CTreeItem *pSelItem, int nItem)
{
SetRedraw(0);
DeleteItem(nItem);//delete cur item in listview
//delete/hide all children in pSelItem
HideChildren(pSelItem, TRUE, nItem);
//delete all internal nodes
// If root, must delete from m_rootData
if(GetParentItem(pSelItem) == NULL )
{
DeleteRootItem(pSelItem);
}
else
Delete(pSelItem);
InternaleUpdateTree();
if(nItem-1<0)//no more items in list
{
SetRedraw(1);
InvalidateRect(NULL);
UpdateWindow();
return;
}
UINT uflag = LVIS_SELECTED | LVIS_FOCUSED;
CRect rcTestIfItemIsValidToSelectOtherWiseSubtrackOneFromItem;//just to get the documention right :)
GetItemRect(nItem, rcTestIfItemIsValidToSelectOtherWiseSubtrackOneFromItem ,LVIR_LABEL) ? SetItemState(nItem, uflag, uflag) : SetItemState(nItem-1, uflag, uflag);
SetRedraw(1);
InvalidateRect(NULL);
UpdateWindow();
}
void CSuperGridCtrl::CleanMe(CTreeItem *pItem)
{
// delete child nodes
POSITION pos = pItem->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CTreeItem* pItemData = (CTreeItem*)pItem->m_listChild.GetNext(pos);
if(pItemData!=NULL)
{
if(pItemData->m_lpNodeInfo!=NULL)
delete pItemData->m_lpNodeInfo;
pItemData->m_listChild.RemoveAll();
delete pItemData;
}
}
pItem->m_listChild.RemoveAll();
}
CSuperGridCtrl::CTreeItem* CSuperGridCtrl::GetNext(CTreeItem* pStartAt, CTreeItem* pNode, BOOL bInit, BOOL bDontIncludeHidden)
{
static BOOL bFound;
if (bInit)
bFound = FALSE;
if (pNode == pStartAt)
bFound = TRUE;
if(bDontIncludeHidden)
{
if (!IsCollapsed(pStartAt))
{
POSITION pos = pStartAt->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CTreeItem* pChild = (CTreeItem*)pStartAt->m_listChild.GetNext(pos);
if (bFound)
return pChild;
pChild = GetNext(pChild, pNode, FALSE, TRUE);
if (pChild != NULL)
return pChild;
}
}
}
else {
POSITION pos = pStartAt->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CTreeItem* pChild = (CTreeItem*)pStartAt->m_listChild.GetNext(pos);
if (bFound)
return pChild;
pChild = GetNext(pChild, pNode, FALSE,FALSE);
if (pChild != NULL)
return pChild;
}
}
// if reached top and last level return original
if (bInit)
return pNode;
else
return NULL;
}
CSuperGridCtrl::CTreeItem* CSuperGridCtrl::GetPrev(CTreeItem* pStartAt, CTreeItem* pNode, BOOL bInit, BOOL bDontIncludeHidden)
{
static CTreeItem* pPrev;
if (bInit)
pPrev = pStartAt;
if (pNode == pStartAt)
return pPrev;
pPrev = pStartAt;
if(bDontIncludeHidden)
{
if (!IsCollapsed(pStartAt))
{
POSITION pos = pStartAt->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CTreeItem* pCur = (CTreeItem*)pStartAt->m_listChild.GetNext(pos);
CTreeItem* pChild = GetPrev(pCur,pNode, FALSE,TRUE);
if (pChild != NULL)
return pChild;
}
}
}
else {
POSITION pos = pStartAt->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CTreeItem* pCur = (CTreeItem*)pStartAt->m_listChild.GetNext(pos);
CTreeItem* pChild = GetPrev(pCur,pNode, FALSE,FALSE);
if (pChild != NULL)
return pChild;
}
}
if (bInit)
return pPrev;
else
return NULL;
}
int CSuperGridCtrl::_NodeToIndex(CTreeItem *pStartpos, CTreeItem* pNode, int& nIndex, BOOL binit)
{
static BOOL bFound;
// Account for other root nodes
if(GetParentItem(pStartpos) == NULL && GetRootIndex(pStartpos) !=0)
nIndex++;
if(binit)
bFound=FALSE;
if(pStartpos==pNode)
bFound=TRUE;
if(!IsCollapsed(pStartpos))
{
POSITION pos = GetHeadPosition(pStartpos);
while (pos)
{
CTreeItem *pChild = GetNextChild(pStartpos, pos);
if(bFound)
return nIndex;
// Craig Schmidt: Cannot set nIndex as return value. Worked find with single root but
// the calling function get confused since the return value may indicate
// that the next root needs to be searched. Didn'd spend much time on
// this so there is probably a better way of doing this.
// nIndex = _NodeToIndex(pChild, pNode, nIndex, binit);
_NodeToIndex(pChild, pNode, nIndex, binit);
nIndex++;
}
}
if(binit && bFound)
return nIndex;
else
return -1;
}
BOOL CSuperGridCtrl::Delete(CTreeItem* pNode, BOOL bClean)
{
POSITION pos = m_RootItems.GetHeadPosition();
while(pos!=NULL)
{
CTreeItem * pRoot = (CTreeItem*)m_RootItems.GetNext(pos);
if(_Delete(pRoot, pNode, bClean))
return TRUE;
}
return FALSE;
}
BOOL CSuperGridCtrl::_Delete(CTreeItem* pStartAt, CTreeItem* pNode, BOOL bClean)
{
POSITION pos = pStartAt->m_listChild.GetHeadPosition();
while (pos != NULL)
{
POSITION posPrev = pos;
CTreeItem *pChild = (CTreeItem*)pStartAt->m_listChild.GetNext(pos);
if (pChild == pNode)
{
pStartAt->m_listChild.RemoveAt(posPrev);
if(bClean)
{
if(GetData(pNode)!=NULL)
delete GetData(pNode);
delete pNode;
}
return TRUE;
}
if (_Delete(pChild, pNode) == TRUE)
return TRUE;
}
return FALSE;
}
BOOL CSuperGridCtrl::IsChildOf(const CTreeItem* pParent, const CTreeItem* pChild) const
{
if (pChild == pParent)
return TRUE;
POSITION pos = pParent->m_listChild.GetHeadPosition();
while (pos != NULL)
{
CTreeItem* pNode = (CTreeItem*)pParent->m_listChild.GetNext(pos);
if (IsChildOf(pNode, pChild))
return TRUE;
}
return FALSE;
}
void CSuperGridCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
if( GetFocus() != this)
SetFocus();
LVHITTESTINFO ht;
ht.pt = point;
SubItemHitTest(&ht);
if(OnItemLButtonDown(ht))
{
BOOL bSelect=1;
bSelect = HitTestOnSign(point, ht);
if(bSelect && ht.iItem!=-1)
{
m_CurSubItem = IndexToOrder(ht.iSubItem);
CHeaderCtrl* pHeader = GetHeaderCtrl();
// Make the column fully visible.
MakeColumnVisible(Header_OrderToIndex(pHeader->m_hWnd, m_CurSubItem));
CListCtrl::OnLButtonDown(nFlags, point);
OnControlLButtonDown(nFlags, point, ht);
//update row anyway for selection bar
CRect rc;
GetItemRect(ht.iItem, rc, LVIR_BOUNDS);
InvalidateRect(rc);
UpdateWindow();
}
}
}
void CSuperGridCtrl::OnUpdateListViewItem(CTreeItem* lpItem, LV_ITEM *plvItem)
{
//default implementation you would go for this 9 out of 10 times
CItemInfo *lp = GetData(lpItem);
CString str = (CString)plvItem->pszText;
if(lp!=NULL)
{
if(plvItem->iSubItem==0)
lp->SetItemText(str);
else //subitem data
lp->SetSubItemText(plvItem->iSubItem-1, str);
UpdateData(lpItem, lp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -