📄 customtabctrl.cpp
字号:
}
}
int ndx = 1;
while(1)
{
ndx++;
if(bAppendFlag)
{
sDst.Format(_T("%s (%d)"), (LPCTSTR)m_aItems[nItemSrc]->m_sText, ndx);
}
else
{
sDst.Format(_T("%s(%d)"), (LPCTSTR)m_aItems[nItemSrc]->m_sText.Left(n), ndx);
}
for(i=0; i<m_aItems.GetSize(); i++)
{
if(m_aItems[i]->m_sText==sDst)
{
break;
}
}
if(i == m_aItems.GetSize())
{
break;
}
}
int nRetItem = InsertItem(nItemDst,sDst,m_aItems[nItemSrc]->m_lParam);
if(nRetItem>=0)
{
SetCurSel(nRetItem);
if(fMouseSel)
{
NotifyParent(CTCN_ITEMCOPY, nRetItem, CPoint(0, 0));
}
}
else if(fMouseSel && nRetItem==CTCERR_OUTOFMEMORY)
{
NotifyParent(CTCN_OUTOFMEMORY, nRetItem, CPoint(0, 0));
}
return nRetItem;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::DeleteItem(int nItem)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
if(m_aItems.GetSize()==1)
{
m_nItemSelected = -1;
}
else if(m_nItemSelected==nItem)
{
if(m_nItemSelected==m_aItems.GetSize()-1) // last item
{
m_nItemSelected--;
m_aItems[m_nItemSelected]->m_fSelected = TRUE;
}
else
{
m_aItems[m_nItemSelected+1]->m_fSelected = TRUE;
}
}
else if(m_nItemSelected>nItem)
{
m_nItemSelected--;
}
delete m_aItems[nItem];
m_aItems.RemoveAt(nItem);
RecalcLayout(RECALC_RESIZED, m_nItemSelected);
Invalidate(FALSE);
return CTCERR_NOERROR;
}
void CCustomTabCtrl::DeleteAllItems()
{
{
for(int i=0; i< m_aItems.GetSize(); i++)
delete m_aItems[i];
}
m_aItems.RemoveAll();
m_nItemSelected = -1;
RecalcLayout(RECALC_RESIZED,m_nItemSelected);
Invalidate(FALSE);
}
int CCustomTabCtrl::SetCurSel(int nItem)
{
return SetCurSel(nItem,FALSE,FALSE);
}
int CCustomTabCtrl::HighlightItem(int nItem, BOOL fHighlight)
{
if(!(GetStyle()&CTCS_MULTIHIGHLIGHT))
return CTCERR_NOMULTIHIGHLIGHTSTYLE;
if(nItem<0 || nItem>=m_aItems.GetSize())
return CTCERR_INDEXOUTOFRANGE;
if(m_nItemSelected==-1 && !fHighlight)
return CTCERR_NOERROR;
if(m_nItemSelected==-1)
{
SetCurSel(nItem);
return CTCERR_NOERROR;
}
if(fHighlight==m_aItems[nItem]->m_fHighlighted || nItem==m_nItemSelected)
return CTCERR_NOERROR;
m_aItems[nItem]->m_fHighlighted = fHighlight;
return CTCERR_NOERROR;
}
int CCustomTabCtrl::GetItemText(int nItem, CString& sText)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
return CTCERR_INDEXOUTOFRANGE;
sText = m_aItems[nItem]->m_sText;
return CTCERR_NOERROR;
}
int CCustomTabCtrl::SetItemText(int nItem, CString sText)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
return CTCERR_INDEXOUTOFRANGE;
m_aItems[nItem]->m_sText = sText;
RecalcLayout(RECALC_RESIZED,m_nItemSelected);
Invalidate(FALSE);
return CTCERR_NOERROR;
}
int CCustomTabCtrl::GetItemData(int nItem, DWORD& dwData)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
dwData = (DWORD)m_aItems[nItem]->m_lParam;
return CTCERR_NOERROR;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::GetItemRect(int nItem, CRect& rect) const
{
if(nItem<0 || nItem>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
rect = m_aItems[nItem]->m_rectText;
return CTCERR_NOERROR;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::SetItemData(int nItem, DWORD dwData)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
m_aItems[nItem]->m_lParam = dwData;
return CTCERR_NOERROR;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::IsItemHighlighted(int nItem)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
return (m_aItems[nItem]->m_fHighlighted)?1:0;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::HitTest(CPoint pt)
{
CRect rCl;
int i, nBtns;
GetTabsRect(&rCl);
if(IsVertical())
{
rCl.SetRect(0, 0, rCl.Height(), rCl.Width());
pt = CPoint(rCl.Width()-pt.y, pt.x);
}
nBtns = 0;
if(m_nCloseState)
{
nBtns++;
}
if(m_nPrevState)
{
nBtns += 2;
}
if(m_nFirstState)
{
nBtns += 2;
}
int nA = rCl.Height()-2;
int nCloseOffset = 0;
if(m_nCloseState)
{
nCloseOffset = nA;
CRect rClose(0, rCl.top, nA+1, rCl.bottom);
if(GetStyle()&CTCS_BUTTONSAFTER)
{
rClose.SetRect(rCl.Width()-nA-1, rCl.top, rCl.Width(), rCl.bottom);
}
if(rClose.PtInRect(pt))
{
return CTCHT_ONCLOSEBUTTON;
}
}
CRect rFirst, rPrev, rNext, rLast;
if(GetStyle()&CTCS_BUTTONSAFTER)
{
if(nBtns==2 || nBtns==3)
{
rNext.SetRect(rCl.Width()-nCloseOffset-nA-1, rCl.top, rCl.Width()-nCloseOffset, rCl.bottom);
rPrev.SetRect(rCl.Width()-nCloseOffset-2*nA-3, rCl.top, rCl.Width()-nCloseOffset-nA-1, rCl.bottom);
}
else if(nBtns==4 || nBtns==5)
{
rLast.SetRect(rCl.Width()-nCloseOffset-nA-1, rCl.top, rCl.Width()-nCloseOffset, rCl.bottom);
rNext.SetRect(rCl.Width()-nCloseOffset-2*nA-1, rCl.top, rCl.Width()-nCloseOffset-nA-1, rCl.bottom);
rPrev.SetRect(rCl.Width()-nCloseOffset-3*nA-2, rCl.top, rCl.Width()-nCloseOffset-2*nA-1, rCl.bottom);
rFirst.SetRect(rCl.Width()-nCloseOffset-4*nA-3, rCl.top, rCl.Width()-nCloseOffset-3*nA-2, rCl.bottom);
}
}
else
{
if(nBtns==2 || nBtns==3)
{
rPrev.SetRect(nCloseOffset, rCl.top, nCloseOffset+nA+1, rCl.bottom);
rNext.SetRect(nCloseOffset+nA+1, rCl.top, nCloseOffset+2*nA+3, rCl.bottom);
}
else if(nBtns==4 || nBtns==5)
{
rFirst.SetRect(nCloseOffset, rCl.top, nCloseOffset+nA+1, rCl.bottom);
rPrev.SetRect(nCloseOffset+nA+1, rCl.top, nCloseOffset+2*nA+1, rCl.bottom);
rNext.SetRect(nCloseOffset+2*nA+1, rCl.top, nCloseOffset+3*nA+2, rCl.bottom);
rLast.SetRect(nCloseOffset+3*nA+2, rCl.top, nCloseOffset+4*nA+3, rCl.bottom);
}
}
if(nBtns>=4 && m_nFirstState && rFirst.PtInRect(pt))
{
return CTCHT_ONFIRSTBUTTON;
}
if(m_nPrevState && rPrev.PtInRect(pt))
{
return CTCHT_ONPREVBUTTON;
}
if(m_nNextState && rNext.PtInRect(pt))
{
return CTCHT_ONNEXTBUTTON;
}
if(nBtns>=4 && m_nLastState && rLast.PtInRect(pt))
{
return CTCHT_ONLASTBUTTON;
}
for(i=0; i<m_aItems.GetSize(); i++)
{
if(m_aItems[i]->HitTest(pt))
{
return i;
}
}
return CTCHT_NOWHERE;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::HighlightItem(int nItem, BOOL fMouseSel, BOOL fCtrlPressed)
{
int i;
if(!(GetStyle()&CTCS_MULTIHIGHLIGHT))
{
return CTCERR_NOMULTIHIGHLIGHTSTYLE;
}
for(i=0; i<m_aItems.GetSize();i++)
{
m_aItems[i]->m_fHighlightChanged = FALSE;
}
if(fCtrlPressed)
{
if(nItem!=m_nItemSelected)
{
m_aItems[nItem]->m_fHighlighted = !m_aItems[nItem]->m_fHighlighted;
if(fMouseSel)
{
m_aItems[nItem]->m_fHighlightChanged = TRUE;
}
}
}
else
if(!m_aItems[nItem]->m_fHighlighted)
{
m_aItems[nItem]->m_fHighlighted = TRUE;
m_aItems[nItem]->m_fHighlightChanged = TRUE;
for(i=0; i<m_aItems.GetSize(); i++)
{
if(i!=m_nItemSelected)
{
if(m_aItems[i]->m_fHighlighted)
{
m_aItems[i]->m_fHighlighted = FALSE;
if(fMouseSel)
{
m_aItems[i]->m_fHighlightChanged = TRUE;
}
}
}
}//for items
}
if(fMouseSel)
{
RecalcLayout(RECALC_ITEM_SELECTED,nItem);
}
Invalidate(FALSE);
return CTCERR_NOERROR;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::SetCurSel(int nItem, BOOL fMouseSel, BOOL fCtrlPressed)
{
if(nItem<0 || nItem>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
if(m_nItemSelected!=-1)
{
m_aItems[m_nItemSelected]->m_fSelected = FALSE;
}
m_nItemSelected = nItem;
if(m_nItemSelected!=-1)
{
m_aItems[m_nItemSelected]->m_fSelected = TRUE;
}
if(fMouseSel)
{
RecalcLayout(RECALC_ITEM_SELECTED, m_nItemSelected);
}
else
{
m_nFirstVisibleItem = nItem;
RecalcLayout(RECALC_RESIZED, m_nItemSelected);
}
Invalidate(FALSE);
HighlightItem(nItem, fMouseSel, fCtrlPressed);
return CTCERR_NOERROR;
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::RecalcLayout(int nRecalcType, int nItem)
{
CRect rCl;
int nCloseOffset, nA, nBnWidth, nBtns;
GetTabsRect(&rCl);
if(IsVertical())
{
rCl.SetRect(0, 0, rCl.Height(), rCl.Width());
}
nCloseOffset = 0;
nA = rCl.Height()-3;
nBnWidth = 0;
nBtns = 0;
if(GetStyle()&CTCS_CLOSEBUTTON)
{
nBtns++;
nCloseOffset = nA;
nBnWidth = nA+3;
//show close button
if(m_nCloseState == BNST_INVISIBLE)
{
m_nCloseState = BNST_NORMAL;
}
}
else
{
m_nCloseState = BNST_INVISIBLE;
}
int nWidth = RecalcRectangles();
if((GetStyle()&CTCS_AUTOHIDEBUTTONS) && (m_aItems.GetSize()<2 || nWidth <= rCl.Width()-nBnWidth))
{
//hide buttons
m_nFirstState = BNST_INVISIBLE;
m_nPrevState = BNST_INVISIBLE;
m_nNextState = BNST_INVISIBLE;
m_nLastState = BNST_INVISIBLE;
m_nFirstVisibleItem = 0;
RecalcOffset(nBnWidth);
if(nRecalcType == RECALC_EDIT_RESIZED)
{
RecalcEditResized(0, nItem);
}
return;
}
if(m_nPrevState==BNST_INVISIBLE)
{
m_nPrevState = BNST_NORMAL;
m_nNextState = BNST_NORMAL;
}
if(GetStyle()&CTCS_FOURBUTTONS)
{
nBtns += 4;
if(m_nFirstState==BNST_INVISIBLE)
{
m_nFirstState = BNST_NORMAL;
m_nLastState = BNST_NORMAL;
}
}
else
{
nBtns += 2;
m_nFirstState = BNST_INVISIBLE;
m_nLastState = BNST_INVISIBLE;
}
if(m_aItems.GetSize()==0)
{
return;
}
nBnWidth = nBtns*nA+3;
if(GetStyle()&CTCS_BUTTONSAFTER)
{
rCl.right -= nBnWidth;
}
switch(nRecalcType)
{
case RECALC_CLOSE_PRESSED:
{
RecalcRectangles();
RecalcOffset(nBnWidth);
break;
}
case RECALC_FIRST_PRESSED:
{
m_nFirstVisibleItem=0;
RecalcRectangles();
RecalcOffset(nBnWidth);
break;
}
case RECALC_PREV_PRESSED:
{
RecalcOffset(nBnWidth);
if(m_nFirstVisibleItem > 0)
{
m_nFirstVisibleItem--;
RecalcRectangles();
RecalcOffset(nBnWidth);
}
break;
}
case RECALC_NEXT_PRESSED:
{
RecalcOffset(nBnWidth);
if(m_aItems[m_aItems.GetSize()-1]->m_rect.right > rCl.Width() && m_nFirstVisibleItem != m_aItems.GetSize()-1)
{
m_nFirstVisibleItem++;
RecalcRectangles();
RecalcOffset(nBnWidth);
}
break;
}
case RECALC_ITEM_SELECTED:
{
RecalcOffset(nBnWidth);
if(m_aItems[nItem]->m_bShape==TAB_BEFORE_FIRST_VISIBLE)
{
m_nFirstVisibleItem--;
RecalcRectangles();
RecalcOffset(nBnWidth);
}
else
{
while(m_nFirstVisibleItem < nItem &&
m_aItems[nItem]->m_bShape==TAB_VISIBLE &&
m_aItems[nItem]->m_rect.right > rCl.Width() &&
m_aItems[nItem]->m_rect.left > ((GetStyle()&CTCS_BUTTONSAFTER)? 0:nBnWidth))
{
m_nFirstVisibleItem++;
RecalcRectangles();
RecalcOffset(nBnWidth);
}
}
break;
}
case RECALC_EDIT_RESIZED:
{
RecalcOffset(nBnWidth);
RecalcEditResized(nBnWidth,nItem);
break;
}
case RECALC_LAST_PRESSED:
{
m_nFirstVisibleItem=(int)m_aItems.GetSize()-1;
//no break here?
}
default: // window resized
{
BOOL bNdxOffsetChanged = FALSE;
RecalcOffset(nBnWidth);
while(m_nFirstVisibleItem>=0 && m_aItems[m_aItems.GetSize()-1]->m_rect.right < rCl.Width())
{
m_nFirstVisibleItem--;
if(m_nFirstVisibleItem>=0)
{
RecalcRectangles();
RecalcOffset(nBnWidth);
}
bNdxOffsetChanged = TRUE;
}
if(bNdxOffsetChanged)
{
m_nFirstVisibleItem++;
RecalcRectangles();
RecalcOffset(nBnWidth);
}
break;
}//default
}//switch recalc type
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::RecalcEditResized(int nOffset, int nItem)
{
CRect rCl;
GetTabsRect(rCl);
if(GetStyle() & CTCS_BUTTONSAFTER)
{
rCl.right -= nOffset;
}
do
{
CRect r;
CDC* pDC = GetDC();
CFont* pOldFont = pDC->SelectObject(&m_FontSelected);
int h = pDC->DrawText(m_aItems[nItem]->m_sText+_T("X"), r, DT_CALCRECT);
pDC->SelectObject(pOldFont);
ReleaseDC(pDC);
r = m_aItems[nItem]->m_rectText;
if(r.Height()>h)
{
r.top += (r.Height()-h)/2;
r.bottom -= (r.Height()-h)/2;
}
r.left += 2;
if(r.right>rCl.right && m_nItemSelected>m_nFirstVisibleItem)
{
m_nFirstVisibleItem++;
RecalcRectangles();
RecalcOffset(nOffset);
}
else
{
if(r.right>rCl.right)
{
r.right = rCl.right;
}
m_ctrlEdit.MoveWindow(r);
int n = m_aItems[nItem]->m_sText.GetLength();
int nStart, nEnd;
m_ctrlEdit.GetSel(nStart, nEnd);
if(nStart == nEnd && nStart == n)
{
m_ctrlEdit.SetSel(0, 0);
m_ctrlEdit.SetSel(n, n);
}
return;
}
}
while(1);
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::RecalcOffset(int nOffset)
{
CRect rCl;
int i;
GetTabsRect(&rCl);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -