📄 bcgtabwnd.cpp
字号:
{
m_ToolTip.SetToolRect (this, i + 1, CRect (0, 0, 0, 0));
}
x += pTab->m_rect.Width () + 1;
m_nTabsTotalWidth += pTab->m_rect.Width () + 1;
if (m_bFlat)
{
//--------------------------------------------
// In the flat mode tab is overlapped by next:
//--------------------------------------------
pTab->m_rect.right += m_nTabsHeight / 2;
}
pTab->m_strDisplayedText = pTab->m_strText;
}
if (m_bFlat || x < m_rectTabsArea.right)
{
m_nTabsTotalWidth += m_nTabsHeight / 2;
dc.SelectObject(pOldFont);
return;
}
//-----------------------------------------
// Not enouth space to show the whole text.
//-----------------------------------------
int nTabWidth = m_rectTabsArea.Width () / m_iTabsNum;
//------------------------------------
// May be it's too wide for some tabs?
//------------------------------------
int nRest = 0;
int nCuttedTabsNum = m_iTabsNum;
for (i = 0; i < m_iTabsNum; i ++)
{
CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
ASSERT_VALID (pTab);
if (pTab->m_nFullWidth < nTabWidth)
{
nRest += nTabWidth - pTab->m_nFullWidth;
nCuttedTabsNum --;
}
}
if (nCuttedTabsNum <= 0)
{
ASSERT (FALSE); // Somethin wrong
dc.SelectObject(pOldFont);
return;
}
nTabWidth += nRest / nCuttedTabsNum;
//----------------------------------
// Last pass: set actual rectangles:
//----------------------------------
x = m_rectTabsArea.left;
for (i = 0; i < m_iTabsNum; i ++)
{
CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
ASSERT_VALID (pTab);
BOOL bIsTrucncated = pTab->m_nFullWidth > nTabWidth;
int nCurrTabWidth = (bIsTrucncated) ? nTabWidth : pTab->m_nFullWidth;
if (bIsTrucncated)
{
TruncateText (&dc, pTab->m_strDisplayedText,
nCurrTabWidth - TEXT_MARGIN - IMAGE_MARGIN - m_sizeImage.cx);
}
if (nTabWidth < m_sizeImage.cx + IMAGE_MARGIN)
{
// Too narrow!
nCurrTabWidth = (m_rectTabsArea.Width () + TAB_BORDER_SIZE * 2) / m_iTabsNum;
pTab->m_strDisplayedText.Empty ();
}
else
{
if (pTab->m_strDisplayedText.IsEmpty ())
{
nCurrTabWidth = m_sizeImage.cx + 2 * TEXT_MARGIN;
}
}
pTab->m_rect = CRect (CPoint (x, m_rectTabsArea.top),
CSize (nCurrTabWidth, m_rectTabsArea.Height ()));
if (!m_bFlat)
{
pTab->m_rect.bottom -= 2;
m_ToolTip.SetToolRect (this, i + 1,
bIsTrucncated ? pTab->m_rect : CRect (0, 0, 0, 0));
}
x += nCurrTabWidth + 1;
}
dc.SelectObject(pOldFont);
}
//***************************************************************************************
void CBCGTabWnd::Draw3DTab (CDC* pDC, CBCGTabInfo* pTab, BOOL bActive)
{
ASSERT_VALID (pTab);
ASSERT_VALID (pDC);
const int iVertOffset = 2;
const int iHorzOffset = 2;
CRect rectTab = pTab->m_rect;
if (!bActive)
{
rectTab.bottom -= iVertOffset;
}
CPen penLight (PS_SOLID, 1, ::GetSysColor (COLOR_3DHILIGHT));
CPen* pOldPen = (CPen*) pDC->SelectObject (&penLight);
ASSERT(pOldPen != NULL);
pDC->MoveTo(rectTab.left, rectTab.top);
pDC->LineTo(rectTab.left, rectTab.bottom - iVertOffset);
pDC->SelectStockObject(BLACK_PEN);
pDC->LineTo(rectTab.left + iHorzOffset, rectTab.bottom);
pDC->LineTo(rectTab.right - iHorzOffset, rectTab.bottom);
pDC->LineTo(rectTab.right, rectTab.bottom - iVertOffset);
pDC->LineTo(rectTab.right, rectTab.top - 1);
CPen penDkGray (PS_SOLID, 1, ::GetSysColor (COLOR_3DSHADOW));
pDC->SelectObject(&penDkGray);
pDC->MoveTo(rectTab.left + iHorzOffset + 1, rectTab.bottom - 1);
pDC->LineTo(rectTab.right - iHorzOffset, rectTab.bottom - 1);
pDC->LineTo(rectTab.right - 1, rectTab.bottom - iVertOffset);
pDC->LineTo(rectTab.right - 1, rectTab.top - 1);
if (bActive)
{
pDC->FillRect (CRect (CPoint (rectTab.left, rectTab.top - 3),
CSize (rectTab.Width (), 3)), &globalData.brBtnFace);
}
if (m_sizeImage.cx + IMAGE_MARGIN <= rectTab.Width ())
{
if (m_Images.GetSafeHandle () != NULL)
{
// Draw the tab's image:
CRect rectImage = rectTab;
rectImage.top += (rectTab.Height () - m_sizeImage.cy) / 2;
rectImage.bottom = rectImage.top + m_sizeImage.cy;
rectImage.left += IMAGE_MARGIN;
rectImage.right = rectImage.left + m_sizeImage.cx;
m_Images.Draw (pDC, pTab->m_uiIcon, rectImage.TopLeft (), ILD_TRANSPARENT);
}
// Finally, draw the tab's text
CRect rcText = rectTab;
rcText.left += m_sizeImage.cx + 2 * TEXT_MARGIN;
pDC->DrawText (pTab->m_strDisplayedText,
rcText, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
}
pDC->SelectObject (pOldPen);
}
//***************************************************************************************
void CBCGTabWnd::DrawFlatTab (CDC* pDC, CBCGTabInfo* pTab, BOOL /*bActive*/)
{
ASSERT_VALID (pTab);
ASSERT_VALID (pDC);
CRect rectTab = pTab->m_rect;
rectTab.bottom --;
//----------------
// Draw tab edges:
//----------------
#define POINTS_NUM 4
POINT pts [POINTS_NUM];
pts [0].x = rectTab.left;
pts [0].y = rectTab.top;
pts [1].x = rectTab.left + m_nTabsHeight / 2;
pts [1].y = rectTab.bottom;
pts [2].x = rectTab.right - m_nTabsHeight / 2;
pts [2].y = rectTab.bottom;
pts [3].x = rectTab.right;
pts [3].y = rectTab.top;
pDC->Polygon (pts, POINTS_NUM);
//---------------
// Draw tab text:
//---------------
pDC->DrawText (pTab->m_strDisplayedText,
rectTab, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
}
//***************************************************************************************
void CBCGTabWnd::OnLButtonDown(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDown(nFlags, point);
if (m_rectTabSplitter.PtInRect (point))
{
m_bTrackSplitter = TRUE;
SetCapture ();
return;
}
CWnd* pWndParent = GetParent ();
ASSERT_VALID (pWndParent);
for (int i = 0; i < m_iTabsNum; i ++)
{
CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [i];
ASSERT_VALID (pTab);
if (pTab->m_rect.PtInRect (point))
{
if (i != m_iActiveTab && m_rectTabsArea.PtInRect (point))
{
SetActiveTab (i);
pWndParent->SendMessage (BCGM_CHANGE_ACTIVE_TAB, i);
}
return;
}
}
CWnd* pWndTarget = FindTargetWnd (point);
if (pWndTarget == NULL)
{
return;
}
ASSERT_VALID (pWndTarget);
MapWindowPoints (pWndTarget, &point, 1);
pWndTarget->SendMessage (WM_LBUTTONDOWN, nFlags,
MAKELPARAM (point.x, point.y));
}
//***************************************************************************************
void CBCGTabWnd::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CWnd::OnLButtonDblClk(nFlags, point);
CWnd* pWndTarget = FindTargetWnd (point);
if (pWndTarget == NULL)
{
return;
}
ASSERT_VALID (pWndTarget);
MapWindowPoints (pWndTarget, &point, 1);
pWndTarget->SendMessage (WM_LBUTTONDBLCLK, nFlags,
MAKELPARAM (point.x, point.y));
}
//****************************************************************************************
int CBCGTabWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
if (m_bFlat)
{
//-------------------
// Create scrollbars:
//-------------------
CRect rectDummy (0, 0, 0, 0);
m_wndScrollTabs.Create (WS_CHILD | WS_VISIBLE | SBS_HORZ, rectDummy,
this, (UINT) -1);
if (m_bSharedScroll)
{
m_wndScrollWnd.Create (WS_CHILD | WS_VISIBLE | SBS_HORZ, rectDummy,
this, (UINT) -1);
}
//---------------------
// Create active brush:
//---------------------
m_brActiveTab.CreateSolidBrush (GetActiveTabColor ());
}
else
{
//---------------------------------------
// Text may be truncated. Create tooltip.
//---------------------------------------
m_ToolTip.Create (this, TTS_ALWAYSTIP);
m_ToolTip.Activate (TRUE);
m_ToolTip.BringWindowToTop ();
}
SetTabsHeight ();
return 0;
}
//***************************************************************************************
BOOL CBCGTabWnd::SetImageList (UINT uiID, int cx, COLORREF clrTransp)
{
if (m_bFlat)
{
ASSERT (FALSE);
return FALSE;
}
if (!m_Images.Create (uiID, cx, 0, clrTransp))
{
return FALSE;
}
IMAGEINFO info;
m_Images.GetImageInfo (0, &info);
CRect rectImage = info.rcImage;
m_sizeImage = rectImage.Size ();
SetTabsHeight ();
return TRUE;
}
//***************************************************************************************
BOOL CBCGTabWnd::OnEraseBkgnd(CDC* pDC)
{
if (m_iTabsNum == 0)
{
CRect rectClient;
GetClientRect (rectClient);
pDC->FillRect (rectClient, &globalData.brBtnFace);
}
return TRUE;
}
//****************************************************************************************
BOOL CBCGTabWnd::PreTranslateMessage(MSG* pMsg)
{
switch (pMsg->message)
{
case WM_KEYDOWN:
if (m_iActiveTab != -1 &&
::GetAsyncKeyState (VK_CONTROL) & 0x8000) // Ctrl is pressed
{
switch (pMsg->wParam)
{
case VK_NEXT:
SetActiveTab (m_iActiveTab == m_iTabsNum - 1 ? 0 : m_iActiveTab + 1);
GetActiveWnd ()->SetFocus ();
GetParent ()->SendMessage (BCGM_CHANGE_ACTIVE_TAB, m_iActiveTab);
break;
case VK_PRIOR:
SetActiveTab (m_iActiveTab == 0 ? m_iTabsNum - 1 : m_iActiveTab - 1);
GetActiveWnd ()->SetFocus ();
GetParent ()->SendMessage (BCGM_CHANGE_ACTIVE_TAB, m_iActiveTab);
break;
}
}
// Continue....
case WM_SYSKEYDOWN:
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
case WM_NCLBUTTONDOWN:
case WM_NCRBUTTONDOWN:
case WM_NCMBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCRBUTTONUP:
case WM_NCMBUTTONUP:
case WM_MOUSEMOVE:
if (!m_bFlat)
{
m_ToolTip.RelayEvent(pMsg);
}
break;
}
return CWnd::PreTranslateMessage(pMsg);
}
//****************************************************************************************
CWnd* CBCGTabWnd::GetTabWnd (int iTab) const
{
if (iTab >= 0 && iTab < m_iTabsNum)
{
CBCGTabInfo* pTab = (CBCGTabInfo*) m_arTabs [iTab];
ASSERT_VALID (pTab);
return pTab->m_pWnd;
}
else
{
return NULL;
}
}
//******************************************************************************************
CWnd* CBCGTabWnd::GetActiveWnd () const
{
return m_iActiveTab == -1 ?
NULL :
((CBCGTabInfo*) m_arTabs [m_iActiveTab])->m_pWnd;
}
//******************************************************************************************
void CBCGTabWnd::TruncateText (CDC* pDC, CString& strText, int nMaxWidth)
//--------------
// By Alan Fritz
//--------------
{
ASSERT_VALID (pDC);
if (strText.IsEmpty ())
{
return;
}
CString strFirstChar = strText.Left (1);
if (pDC->GetTextExtent (strFirstChar).cx > nMaxWidth)
{
// Even first char can't be displayed!
strText.Empty ();
return;
}
const CString strEllipses (_T("..."));
CString strNewText (strText);
while (strText.GetLength () > 1 &&
pDC->GetTextExtent (strNewText).cx > nMaxWidth)
{
strText = strText.Left (strText.GetLength () - 1);
strNewText = strText + strEllipses;
}
if (strText.GetLength () == 1)
{
// Start remove dots from ellipses...
while (!strNewText.IsEmpty () &&
pDC->GetTextExtent (strNewText).cx > nMaxWidth)
{
strNewText = strNewText.Left (strNewText.GetLength () - 1);
}
}
strText = strNewText;
}
//******************************************************************************************
void CBCGTabWnd::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
if (!m_bFlat)
{
CWnd::OnHScroll (nSBCode, nPos, pScrollBar);
return;
}
if (pScrollBar->GetSafeHwnd () == m_wndScrollWnd.GetSafeHwnd ())
{
static BOOL bInsideScroll = FALSE;
if (m_iActiveTab != -1 && !bInsideScroll)
{
CWnd* pWndActive = GetActiveWnd ();
ASSERT_VALID (pWndActive);
WPARAM wParam = MAKEWPARAM (nSBCode, nPos);
//----------------------------------
// Pass scroll to the active window:
//----------------------------------
bInsideScroll = TRUE;
pWndActive->SendMessage (WM_HSCROLL, wParam, 0);
bInsideScroll = FALSE;
m_wndScrollWnd.SetScrollPos (pWndActive->GetScrollPos (SB_HORZ));
HideActiveWindowHorzScrollBar ();
GetParent ()->SendMessage (BCGM_ON_HSCROLL, wParam);
}
return;
}
if (pScrollBar->GetSafeHwnd () != m_wndScrollTabs.GetSafeHwnd ())
{
CWnd::OnHScroll (nSBCode, nPos, pScrollBar);
return;
}
int nPrevOffset = m_nTabsHorzOffset;
const int nScrollOffset = 20;
switch (nSBCode)
{
case SB_LINELEFT:
m_nTabsHorzOffset -= nScrollOffset;
break;
case SB_LINERIGHT:
m_nTabsHorzOffset += nScrollOffset;
break;
default:
AdjustTabsScroll ();
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -