📄 customtabctrl.cpp
字号:
{
DrawBk(dcMem, rPrev, m_hBmpBkLeftSpin, m_fIsLeftImageHorLayout, m_mrgnLeft,m_nPrevState-1);
}
else
*/
{
if(m_nPrevState == BNST_PRESSED)
{
dcMem.DrawFrameControl(rPrev, DFC_BUTTON, DFCS_BUTTONPUSH|DFCS_PUSHED);
}
else
{
dcMem.DrawFrameControl(rPrev, DFC_BUTTON, DFCS_BUTTONPUSH);
}
}
DrawGlyph(dcMem, ptPrev, 1, m_nPrevState-1);
CPoint ptNext(rNext.left + (rNext.Width()-8)/2, rNext.top + (rNext.Height()-7)/2);
/*
if(m_hBmpBkRightSpin)
{
DrawBk(dcMem, rNext, m_hBmpBkRightSpin, m_fIsRightImageHorLayout, m_mrgnRight, m_nNextState-1);
}
else
*/
{
rNext.left -= 1;
if(m_nNextState == BNST_PRESSED)
{
dcMem.DrawFrameControl(rNext, DFC_BUTTON, DFCS_BUTTONPUSH|DFCS_PUSHED);
}
else
{
dcMem.DrawFrameControl(rNext, DFC_BUTTON, DFCS_BUTTONPUSH);
}
}
DrawGlyph(dcMem, ptNext, 2, m_nNextState-1);
}
// draw lines around tabs
int nOffsetX = rAll.Width();
if(! ((BOOL) (GetStyle()&CTCS_NOLINES)) )
{
CPoint pts[4];
if(fAfter)
{
//buttons are after tabs.
if(GetStyle()&CTCS_TOP)
{
//nothing selected?
if(m_nItemSelected==-1)
{
pts[0] = CPoint(0, rCl.bottom-1);
pts[1] = CPoint(0, rCl.bottom-1);
pts[2] = CPoint(0, rCl.bottom-1);
pts[3] = CPoint(rCl.right-nOffsetX, rCl.bottom-1);
}
else
{
//something selected.
//is selected tab visible?
if(m_aItems[m_nItemSelected]->m_bShape)
{
pts[0] = CPoint(0, rCl.bottom-1);
pts[1] = CPoint(m_aItems[m_nItemSelected]->m_rect.left, rCl.bottom-1);
pts[2] = CPoint(m_aItems[m_nItemSelected]->m_rect.right, rCl.bottom-1);
pts[3] = CPoint(rCl.right-nOffsetX, rCl.bottom-1);
}
else
{
//no it is not.
pts[0] = CPoint(0, rCl.bottom-1);
pts[1] = CPoint(0, rCl.bottom-1);
pts[2] = CPoint(0, rCl.bottom-1);
pts[3] = CPoint(rCl.right-nOffsetX, rCl.bottom-1);
}
}
}//if top
else
{
//buttons after tabs, and BOTTOM style.
//nothing selected?
if(m_nItemSelected==-1)
{
pts[0] = CPoint(rCl.left, rCl.top);
pts[1] = CPoint(rCl.left, rCl.top);
pts[2] = CPoint(rCl.left, rCl.top);
pts[3] = CPoint(rCl.right-nOffsetX, rCl.top);
}
else
{
if(m_aItems[m_nItemSelected]->m_bShape)
{
pts[0] = CPoint(rCl.left, rCl.top);
pts[1] = CPoint(m_aItems[m_nItemSelected]->m_rect.left, rCl.top);
pts[2] = CPoint(m_aItems[m_nItemSelected]->m_rect.right, rCl.top);
pts[3] = CPoint(rCl.right-nOffsetX, rCl.top);
}
else
{
pts[0] = CPoint(rCl.left, rCl.top);
pts[1] = CPoint(rCl.left, rCl.top);
pts[2] = CPoint(rCl.left, rCl.top);
pts[3] = CPoint(rCl.right-nOffsetX, rCl.top);
}
}
}//if bottom
}//if after
else
{
//buttons before tabs.
if(GetStyle()&CTCS_TOP)
{
if(m_nItemSelected==-1)
{
pts[0] = CPoint(nOffsetX, rCl.bottom-1);
pts[1] = CPoint(nOffsetX, rCl.bottom-1);
pts[2] = CPoint(nOffsetX, rCl.bottom-1);
pts[3] = CPoint(rCl.right, rCl.bottom-1);
}
else
{
if(m_aItems[m_nItemSelected]->m_bShape)
{
pts[0] = CPoint(nOffsetX, rCl.bottom-1);
pts[1] = CPoint(m_aItems[m_nItemSelected]->m_rect.left, rCl.bottom-1);
pts[2] = CPoint(m_aItems[m_nItemSelected]->m_rect.right, rCl.bottom-1);
pts[3] = CPoint(rCl.right, rCl.bottom-1);
}
else
{
pts[0] = CPoint(nOffsetX, rCl.bottom-1);
pts[1] = CPoint(nOffsetX, rCl.bottom-1);
pts[2] = CPoint(nOffsetX, rCl.bottom-1);
pts[3] = CPoint(rCl.right, rCl.bottom-1);
}
}
}//if top
else
{
if(m_nItemSelected==-1)
{
pts[0] = CPoint(nOffsetX, rCl.top);
pts[1] = CPoint(nOffsetX, rCl.top);
pts[2] = CPoint(nOffsetX, rCl.top);
pts[3] = CPoint(rCl.right, rCl.top);
}
else
{
if(m_aItems[m_nItemSelected]->m_bShape)
{
pts[0] = CPoint(nOffsetX, rCl.top);
pts[1] = CPoint(m_aItems[m_nItemSelected]->m_rect.left, rCl.top);
pts[2] = CPoint(m_aItems[m_nItemSelected]->m_rect.right, rCl.top);
pts[3] = CPoint(rCl.right, rCl.top);
}
else
{
pts[0] = CPoint(nOffsetX, rCl.top);
pts[1] = CPoint(nOffsetX, rCl.top);
pts[2] = CPoint(nOffsetX, rCl.top);
pts[3] = CPoint(rCl.right, rCl.top);
}
}
}//if bottom
}
CPen* pOldPen = dcMem.SelectObject(&blackPen);
//draw lines
dcMem.MoveTo(pts[0]);
dcMem.LineTo(pts[1]);
dcMem.MoveTo(pts[2]);
dcMem.LineTo(pts[3]);
dcMem.SelectObject(pOldPen);
}//if ! NOLINES
//ok all drawing done, now display control
if(IsVertical())
{
//need to rotate
#ifndef _WIN32_WCE
//on nt/2000/xp, very simple
POINT pts[3];
pts[0].x = 0;
pts[0].y = rCl.Width();
pts[1].x = 0;
pts[1].y = 0;
pts[2].x = rCl.Height();
pts[2].y = rCl.Width();
::PlgBlt(dc.m_hDC, pts, dcMem.m_hDC, 0, 0, rCl.Width(), rCl.Height(), NULL, 0, 0);
#else
//on PocketPC/Wince, a bit more complicated...
{
register int x, y, w, h;
register COLORREF cr;
w=rCl.Width();
h=rCl.Height();
for(x=0; x<w; x++)
{
for(y=0; y<h; y++)
{
cr=dcMem.GetPixel(x, y);
dc.SetPixel(y, w-x, cr);
}
}
}
#endif
}
else
{
//just display
dc.BitBlt(rCl.left, rCl.top, rCl.Width(), rCl.Height(), &dcMem, rCl.left, rCl.top, SRCCOPY);
// dc.BitBlt(rWnd.left, rWnd.top, rWnd.Width(), rWnd.Height(), &dcMem, rWnd.left, rWnd.top, SRCCOPY);
}
dcMem.SelectObject(pOldBmp);
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
if(cx && cy)
{
RecalcLayout(RECALC_RESIZED, m_nItemSelected);
}
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
int nHitTest;
nHitTest = HitTest(point);
NotifyParent(CTCN_CLICK, nHitTest, point);
ProcessLButtonDown(nHitTest, nFlags, point);
//avoid gesture recognition
#ifndef _WIN32_WCE
CWnd::OnLButtonDown(nFlags,point);
#else
Default();
#endif
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
{
int nHTRet;
nHTRet = ProcessLButtonDown(HitTest(point), nFlags, point);
if(nHTRet>=0)
{
m_nButtonIDDown = CTCID_NOBUTTON;
if(nHTRet==HitTest(point))
{
EditLabel(nHTRet, TRUE);
}
}
NotifyParent(CTCN_DBLCLK, HitTest(point), point);
CWnd::OnLButtonDblClk(nFlags, point);
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::ProcessLButtonDown(int nHitTest, UINT nFlags, CPoint point)
{
int i;
SetCapture();
switch(nHitTest)
{
case CTCHT_NOWHERE:
{
m_nButtonIDDown = CTCID_NOBUTTON;
break;
}
case CTCHT_ONFIRSTBUTTON:
{
m_nButtonIDDown = CTCID_FIRSTBUTTON;
m_nFirstState = BNST_PRESSED;
RecalcLayout(RECALC_FIRST_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
SetTimer(CTC_TIMER_ID, CTC_TIMER_TIMEOUT, NULL);
break;
}
case CTCHT_ONPREVBUTTON:
{
m_nButtonIDDown = CTCID_PREVBUTTON;
m_nPrevState = BNST_PRESSED;
RecalcLayout(RECALC_PREV_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
SetTimer(CTC_TIMER_ID, CTC_TIMER_TIMEOUT, NULL);
break;
}
case CTCHT_ONNEXTBUTTON:
{
m_nButtonIDDown = CTCID_NEXTBUTTON;
m_nNextState = BNST_PRESSED;
RecalcLayout(RECALC_NEXT_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
SetTimer(CTC_TIMER_ID, CTC_TIMER_TIMEOUT, NULL);
break;
}
case CTCHT_ONLASTBUTTON:
{
m_nButtonIDDown = CTCID_LASTBUTTON;
m_nLastState = BNST_PRESSED;
RecalcLayout(RECALC_LAST_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
SetTimer(CTC_TIMER_ID, CTC_TIMER_TIMEOUT, NULL);
break;
}
case CTCHT_ONCLOSEBUTTON:
{
m_nButtonIDDown = CTCID_CLOSEBUTTON;
m_nCloseState = BNST_PRESSED;
RecalcLayout(RECALC_CLOSE_PRESSED, m_nItemSelected);
Invalidate(FALSE);
break;
}
default:
{
DWORD dwStyle = GetStyle();
m_nButtonIDDown = CTCID_NOBUTTON;
if((GetStyle()&CTCS_MULTIHIGHLIGHT) && (nFlags&MK_CONTROL))
{
HighlightItem(nHitTest, TRUE, nFlags&MK_CONTROL);
}
else
{
BOOL bNotify = nHitTest!=m_nItemSelected;
SetCurSel(nHitTest, TRUE, nFlags&MK_CONTROL);
if(bNotify)
{
NotifyParent(CTCN_SELCHANGE, m_nItemSelected, point);
}
}
for(i=0; i<m_aItems.GetSize(); i++)
{
if(m_aItems[i]->m_fHighlightChanged)
{
NotifyParent(CTCN_HIGHLIGHTCHANGE, i, point);
}
}
}
break;
}
return nHitTest;
}
//////////////////////////////////////////////////////////////////////////
BOOL CCustomTabCtrl::NotifyParent(UINT code, int nItem, CPoint pt)
{
CTC_NMHDR nmh;
memset(&nmh, 0, sizeof(CTC_NMHDR));
nmh.hdr.hwndFrom = GetSafeHwnd();
nmh.hdr.idFrom = GetDlgCtrlID();
nmh.hdr.code = code;
nmh.nItem = nItem;
nmh.ptHitTest = pt;
if(nItem>=0)
{
_tcscpy(nmh.pszText, m_aItems[nItem]->m_sText);
nmh.lParam = m_aItems[nItem]->m_lParam;
nmh.rItem = m_aItems[nItem]->m_rectText;
nmh.fSelected = m_aItems[nItem]->m_fSelected;
nmh.fHighlighted = m_aItems[nItem]->m_fHighlighted;
}
return (BOOL)GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmh);
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::OnLButtonUp(UINT /*nFlags*/, CPoint /*point*/)
{
if(m_nPrevState || m_nNextState || m_nFirstState || m_nLastState || m_nCloseState)
{
if(m_nCloseState)
{
m_nCloseState = BNST_NORMAL;
}
if(m_nPrevState)
{
m_nPrevState = BNST_NORMAL;
m_nNextState = BNST_NORMAL;
}
if(m_nFirstState)
{
m_nFirstState = BNST_NORMAL;
m_nLastState = BNST_NORMAL;
}
Invalidate(FALSE);
KillTimer(1);
}
m_nButtonIDDown = CTCID_NOBUTTON;
m_nItemDragDest = CTCID_NOBUTTON;
ReleaseCapture();
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::OnUpdateEdit()
{
if(m_ctrlEdit.m_hWnd)
{
m_ctrlEdit.GetWindowText(m_aItems[m_nItemSelected]->m_sText);
RecalcLayout(RECALC_EDIT_RESIZED, m_nItemSelected);
Invalidate(FALSE);
}
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::OnTimer(UINT nIDEvent)
{
CWnd::OnTimer(nIDEvent);
if(nIDEvent == CTC_TIMER_ID)
{
if(m_nFirstState==BNST_PRESSED && ::GetTickCount()-m_dwLastRepeatTime >= REPEAT_TIMEOUT)
{
m_nFirstState = BNST_PRESSED;
RecalcLayout(RECALC_FIRST_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
return;
}
if(m_nPrevState==BNST_PRESSED && ::GetTickCount()-m_dwLastRepeatTime >= REPEAT_TIMEOUT)
{
m_nPrevState = BNST_PRESSED;
RecalcLayout(RECALC_PREV_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
return;
}
if(m_nNextState==BNST_PRESSED && ::GetTickCount()-m_dwLastRepeatTime >= REPEAT_TIMEOUT)
{
m_nNextState = BNST_PRESSED;
RecalcLayout(RECALC_NEXT_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
return;
}
if(m_nLastState==BNST_PRESSED && ::GetTickCount()-m_dwLastRepeatTime >= REPEAT_TIMEOUT)
{
m_nLastState = BNST_PRESSED;
RecalcLayout(RECALC_LAST_PRESSED, m_nItemSelected);
Invalidate(FALSE);
m_dwLastRepeatTime = ::GetTickCount();
return;
}
}
}
//////////////////////////////////////////////////////////////////////////
void CCustomTabCtrl::SetControlFont(const LOGFONT& lf, BOOL fRedraw)
{
LOGFONT lfSel;
if(m_Font.m_hObject)
{
DeleteObject(m_Font);
m_Font.m_hObject = NULL;
}
if(m_FontSelected.m_hObject)
{
DeleteObject(m_FontSelected);
m_FontSelected.m_hObject = NULL;
}
if(!m_Font.CreateFontIndirect(&lf))
{
m_Font.CreateFontIndirect(&lf_default);
}
m_Font.GetLogFont(&lfSel);
lfSel.lfWeight = FW_BOLD;
m_FontSelected.CreateFontIndirect(&lfSel);
if(fRedraw)
{
RecalcLayout(RECALC_RESIZED, m_nItemSelected);
Invalidate();
}
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::InsertItem(int nItem, CString sText, LPARAM lParam)
{
if(nItem<0 || nItem > m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
if(sText.GetLength() > MAX_LABEL_LENGTH-1)
{
return CTCERR_TEXTTOOLONG;
}
CCustomTabItem* pItem = new CCustomTabItem(sText, lParam);
if(pItem==NULL)
{
return CTCERR_OUTOFMEMORY;
}
m_aItems.InsertAt(nItem, pItem);
if(m_nItemSelected >= nItem)
{
m_nItemSelected++;
}
RecalcLayout(RECALC_RESIZED, m_nItemSelected);
Invalidate(FALSE);
return nItem;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::MoveItem(int nItemSrc, int nItemDst)
{
return MoveItem(nItemSrc, nItemDst, FALSE);
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::MoveItem(int nItemSrc, int nItemDst, BOOL fMouseSel)
{
if(nItemSrc<0||nItemSrc>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
if(nItemDst<0||nItemDst>m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
if(nItemSrc==nItemDst || nItemSrc==nItemDst-1)
{
return nItemSrc;
}
CCustomTabItem *pItem = m_aItems[nItemSrc];
// remove item from old place
m_aItems.RemoveAt(nItemSrc);
// insert item in new place
if(nItemDst>nItemSrc)
{
nItemDst--;
}
m_aItems.InsertAt(nItemDst, pItem);
m_nItemSelected = nItemDst;
RecalcLayout(RECALC_ITEM_SELECTED, m_nItemSelected);
Invalidate(FALSE);
if(fMouseSel)
{
NotifyParent(CTCN_ITEMMOVE, m_nItemSelected, CPoint(0, 0));
}
return nItemDst;
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::CopyItem(int nItemSrc, int nItemDst)
{
return CopyItem(nItemSrc, nItemDst, FALSE);
}
//////////////////////////////////////////////////////////////////////////
int CCustomTabCtrl::CopyItem(int nItemSrc, int nItemDst, BOOL fMouseSel)
{
int i;
CString sDst;
if(nItemSrc<0||nItemSrc>=m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
if(nItemDst<0||nItemDst>m_aItems.GetSize())
{
return CTCERR_INDEXOUTOFRANGE;
}
BOOL bAppendFlag=TRUE;
int n = m_aItems[nItemSrc]->m_sText.GetLength();
if(n>=4)
{
if(m_aItems[nItemSrc]->m_sText[n-1]==_T(')') &&
m_aItems[nItemSrc]->m_sText[n-2]>_T('1') &&
m_aItems[nItemSrc]->m_sText[n-2]<=_T('9') &&
m_aItems[nItemSrc]->m_sText[n-3]==_T('('))
{
n = m_aItems[nItemSrc]->m_sText.GetLength()-3;
bAppendFlag = FALSE;
}
else if(m_aItems[nItemSrc]->m_sText[n-1]==_T(')') &&
m_aItems[nItemSrc]->m_sText[n-2]>=_T('0') &&
m_aItems[nItemSrc]->m_sText[n-2]<=_T('9') &&
m_aItems[nItemSrc]->m_sText[n-3]>=_T('1') &&
m_aItems[nItemSrc]->m_sText[n-3]<=_T('9') &&
m_aItems[nItemSrc]->m_sText[n-4]==_T('('))
{
n = m_aItems[nItemSrc]->m_sText.GetLength()-4;
bAppendFlag = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -