You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1615 lines
32 KiB
C++
1615 lines
32 KiB
C++
// XTPExcelTabCtrl.cpp : implementation of the CXTPExcelTabCtrl class.
|
|
//
|
|
// This file is a part of the XTREME CONTROLS MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "../Resource.h"
|
|
|
|
#include "Common/XTPResourceManager.h"
|
|
#include "Common/XTPColorManager.h"
|
|
#include "Common/XTPDrawHelpers.h"
|
|
|
|
#include "../Defines.h"
|
|
#include "../Util/XTPGlobal.h"
|
|
#include "../Util/XTPControlTheme.h"
|
|
#include "XTPExcelTabCtrl.h"
|
|
#include "XTPExcelTabCtrlTheme.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
static const int GRIPPER_WIDTH = 6;
|
|
|
|
static const int BUTTON_COUNT = 4;
|
|
|
|
#define XTP_IDC_BTN_LEFT 100
|
|
#define XTP_IDC_BTN_RIGHT 101
|
|
#define XTP_IDC_BTN_HOME 102
|
|
#define XTP_IDC_BTN_END 103
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPExcelTabCtrlButtonState
|
|
|
|
CXTPExcelTabCtrlButtonState::CXTPExcelTabCtrlButtonState()
|
|
: m_rect(0, 0, 0, 0)
|
|
, m_bPressed(false)
|
|
, m_bEnabled(true)
|
|
, m_bHilight(false)
|
|
{
|
|
m_iCommand = 0;
|
|
}
|
|
|
|
void CXTPExcelTabCtrlButtonState::SetInfo(CRect rect, int iCommand, XTPArrowIcon iconType)
|
|
{
|
|
m_rect = rect;
|
|
m_iCommand = iCommand;
|
|
m_IconType = iconType;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CXTPExcelTabCtrl
|
|
|
|
CXTPExcelTabCtrl::CXTPExcelTabCtrl()
|
|
: m_iBtnLeft(-1)
|
|
, m_iBtnRight(-1)
|
|
, m_iBtnHome(-1)
|
|
, m_iBtnEnd(-1)
|
|
, m_bPainted(false)
|
|
, m_iBtnHilight(-1)
|
|
, m_pTheme(NULL)
|
|
, m_bSubclassed(TRUE)
|
|
{
|
|
m_dwStyle = NULL;
|
|
m_nCurSel = -1;
|
|
m_nOffset = 0;
|
|
m_nClientWidth = 0;
|
|
m_nClientHeight = 0;
|
|
m_pNormFont = &XTPAuxData().font;
|
|
m_pBoldFont = &XTPAuxData().fontBold;
|
|
m_bManagingViews = false;
|
|
m_rectGripper = CRect(0, 0, 0, 0);
|
|
m_bTracking = false;
|
|
m_bUserColors = false;
|
|
m_pWndLastFocus = NULL;
|
|
m_iGripperPosPerCent = 0;
|
|
m_xGripperPos = -1;
|
|
|
|
// Initialize the width and height for the left, right, home
|
|
// and end buttons.
|
|
m_cy = ::GetSystemMetrics(SM_CYHSCROLL);
|
|
m_cx = ::GetSystemMetrics(SM_CXHSCROLL)-1;
|
|
|
|
UpdateDefaultColors();
|
|
|
|
// Create the icons used by the left, right, home and end buttons.
|
|
CreateButtonIcons();
|
|
|
|
VERIFY(SetTheme(xtpControlThemeDefault));
|
|
}
|
|
|
|
CXTPExcelTabCtrl::~CXTPExcelTabCtrl()
|
|
{
|
|
CMDTARGET_RELEASE(m_pTheme);
|
|
|
|
// Cleanup
|
|
ClearAllItems();
|
|
FreeButtonIcons();
|
|
}
|
|
|
|
IMPLEMENT_DYNAMIC(CXTPExcelTabCtrl, CWnd)
|
|
|
|
BEGIN_MESSAGE_MAP(CXTPExcelTabCtrl, CWnd)
|
|
//{{AFX_MSG_MAP(CXTPExcelTabCtrl)
|
|
ON_WM_CREATE()
|
|
ON_WM_PAINT()
|
|
ON_MESSAGE(WM_PRINTCLIENT, OnPrintClient)
|
|
ON_WM_ERASEBKGND()
|
|
ON_BN_CLICKED(XTP_IDC_BTN_LEFT, OnLeftArrow)
|
|
ON_BN_CLICKED(XTP_IDC_BTN_RIGHT, OnRightArrow)
|
|
ON_BN_CLICKED(XTP_IDC_BTN_HOME, OnHomeArrow)
|
|
ON_BN_CLICKED(XTP_IDC_BTN_END, OnEndArrow)
|
|
ON_WM_SIZE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_SETCURSOR()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_LBUTTONDBLCLK()
|
|
ON_WM_HSCROLL()
|
|
ON_WM_TIMER()
|
|
//}}AFX_MSG_MAP
|
|
ON_MESSAGE(WM_XTP_SETCONTROLTHEME, OnSetTheme)
|
|
END_MESSAGE_MAP()
|
|
|
|
void CXTPExcelTabCtrl::RefreshMetrics()
|
|
{
|
|
if (m_pTheme)
|
|
m_pTheme->RefreshMetrics(this);
|
|
|
|
if (::IsWindow(m_hWnd))
|
|
RedrawWindow();
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::SetTheme(XTPControlTheme eTheme)
|
|
{
|
|
CMDTARGET_RELEASE(m_pTheme);
|
|
|
|
switch (eTheme)
|
|
{
|
|
case xtpControlThemeOfficeXP:
|
|
m_pTheme = new CXTPExcelTabCtrlThemeOfficeXP;
|
|
break;
|
|
|
|
case xtpControlThemeOffice2003:
|
|
m_pTheme = new CXTPExcelTabCtrlThemeOffice2003;
|
|
break;
|
|
|
|
default:
|
|
m_pTheme = new CXTPExcelTabCtrlTheme;
|
|
break;
|
|
}
|
|
|
|
RefreshMetrics();
|
|
|
|
return (m_pTheme != NULL);
|
|
}
|
|
|
|
LRESULT CXTPExcelTabCtrl::OnSetTheme(WPARAM wParam, LPARAM /*lParam*/)
|
|
{
|
|
XTPControlTheme eTheme = (XTPControlTheme)wParam;
|
|
|
|
SetTheme(eTheme);
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::Init()
|
|
{
|
|
if (SetTheme(xtpControlThemeDefault))
|
|
{
|
|
if (m_bSubclassed)
|
|
{
|
|
m_dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
|
|
|
|
CXTPClientRect rect(this);
|
|
m_nClientWidth = rect.Width();
|
|
m_nClientHeight = rect.Height();
|
|
}
|
|
|
|
SetTabStyle(m_dwStyle);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
if (message == WM_SETTINGCHANGE || message == WM_SYSCOLORCHANGE)
|
|
{
|
|
RefreshMetrics();
|
|
}
|
|
|
|
return CWnd::OnWndMsg(message, wParam, lParam, pResult);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::PreSubclassWindow()
|
|
{
|
|
CWnd::PreSubclassWindow();
|
|
|
|
if (m_bSubclassed)
|
|
{
|
|
// Initialize the control.
|
|
Init();
|
|
}
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::PreCreateWindow(CREATESTRUCT& cs)
|
|
{
|
|
if (!CWnd::PreCreateWindow(cs))
|
|
return FALSE;
|
|
|
|
// When creating controls dynamically Init() must
|
|
// be called from OnCreate() and not from
|
|
// PreSubclassWindow().
|
|
|
|
m_bSubclassed = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL CXTPExcelTabCtrl::Create(DWORD dwStyle, const CRect& rect, CWnd* pParentWnd, UINT nID)
|
|
{
|
|
ASSERT(pParentWnd != NULL); // must be valid.
|
|
|
|
// Call the base class for creation.
|
|
if (!CWnd::Create(NULL, NULL, dwStyle, rect, pParentWnd, nID))
|
|
{
|
|
TRACE0("Failed to create flat tab control.\n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CWnd::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
// Save the window style.
|
|
m_dwStyle = lpCreateStruct->style;
|
|
m_nClientWidth = lpCreateStruct->cx;
|
|
m_nClientHeight = lpCreateStruct->cy;
|
|
|
|
// Initialize the control.
|
|
Init();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetGripperPosition(int x, bool bPercent)
|
|
{
|
|
// only valid for tabs with horizontal scroll bars
|
|
if (!(m_dwStyle & FTS_XTP_HSCROLL)) return;
|
|
|
|
int x_percent;
|
|
if (bPercent)
|
|
{
|
|
x_percent = x;
|
|
x = m_nClientWidth * x / 100;
|
|
}
|
|
else
|
|
{
|
|
x_percent = x * 100 / m_nClientWidth;
|
|
}
|
|
|
|
// too far to the left ?
|
|
const int arrowWidth = 0; //GetTotalArrowWidth();
|
|
if (x < arrowWidth) x = arrowWidth;
|
|
|
|
// too far to the right ?
|
|
const int sbExtreme = (m_nClientWidth - 4 * m_cx - m_cy);
|
|
if (x > sbExtreme) x = sbExtreme;
|
|
|
|
m_xGripperPos = x;
|
|
m_iGripperPosPerCent = x_percent;
|
|
|
|
m_rectGripper = m_rectTabs;
|
|
m_rectGripper.left += x;
|
|
m_rectGripper.right = m_rectGripper.left + GRIPPER_WIDTH;
|
|
|
|
const int isbottom = ((m_dwStyle & FTS_XTP_BOTTOM) == FTS_XTP_BOTTOM);
|
|
m_rectSB_H = CRect(
|
|
m_rectGripper.right,
|
|
m_rectTabs.top - !isbottom,
|
|
m_rectTabs.right - m_cy,
|
|
m_rectTabs.bottom + isbottom);
|
|
m_wndHScrollBar.MoveWindow(m_rectSB_H);
|
|
|
|
EnableButtons();
|
|
InvalidateRect(m_rectTabs);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabStyle(DWORD dwStyle)
|
|
{
|
|
m_dwStyle = dwStyle;
|
|
|
|
if (!GetSafeHwnd())
|
|
return;
|
|
|
|
if (m_dwStyle & FTS_XTP_HASHOMEEND) m_dwStyle |= FTS_XTP_HASARROWS;
|
|
|
|
// If we use tooltips, create the control.
|
|
if (m_dwStyle & FTS_XTP_TOOLTIPS)
|
|
{
|
|
if (m_ToolTip.GetSafeHwnd() == 0)
|
|
{
|
|
CString strTipText;
|
|
XTPResourceManager()->LoadString(&strTipText, XTP_IDS_TIPTEXT);
|
|
|
|
m_ToolTip.Create(this);
|
|
m_ToolTip.Activate(TRUE);
|
|
m_ToolTip.AddTool(this, strTipText);
|
|
m_ToolTip.SendMessage(TTM_SETMAXTIPWIDTH, 0, SHRT_MAX); // Allow multi line tooltips
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_ToolTip.DestroyWindow();
|
|
}
|
|
|
|
CRect rectDummy(0, 0, 0, 0);
|
|
|
|
// If we use arrow buttons, create the buttons.
|
|
if (m_dwStyle & FTS_XTP_HASARROWS)
|
|
{
|
|
int nIndex = 0;
|
|
|
|
// Create the home button.
|
|
if (m_dwStyle & FTS_XTP_HASHOMEEND)
|
|
{
|
|
m_buttons[nIndex].SetInfo(rectDummy, XTP_IDC_BTN_HOME,
|
|
xtpArrowIconLeftHome);
|
|
m_iBtnHome = nIndex;
|
|
++nIndex;
|
|
}
|
|
else
|
|
{
|
|
m_iBtnHome = 3;
|
|
}
|
|
|
|
// Create the left button.
|
|
m_buttons[nIndex].SetInfo(rectDummy, XTP_IDC_BTN_LEFT, xtpArrowIconLeft);
|
|
m_iBtnLeft = nIndex;
|
|
++nIndex;
|
|
|
|
// Create the right button.
|
|
m_buttons[nIndex].SetInfo(rectDummy, XTP_IDC_BTN_RIGHT, xtpArrowIconRight);
|
|
m_iBtnRight = nIndex;
|
|
++nIndex;
|
|
|
|
// Create the end button.
|
|
if (m_dwStyle & FTS_XTP_HASHOMEEND)
|
|
{
|
|
m_buttons[nIndex].SetInfo(rectDummy, XTP_IDC_BTN_END,
|
|
xtpArrowIconRightHome);
|
|
m_iBtnEnd = nIndex;
|
|
++nIndex;
|
|
}
|
|
else
|
|
{
|
|
m_iBtnEnd = 3;
|
|
}
|
|
|
|
}
|
|
|
|
if (m_dwStyle & FTS_XTP_HSCROLL)
|
|
{
|
|
if (m_wndHScrollBar.GetSafeHwnd() == 0)
|
|
{
|
|
CRect rc(0, 0, 0, 0);
|
|
VERIFY(m_wndHScrollBar.Create(WS_VISIBLE | WS_CHILD | SBS_HORZ,
|
|
rc, this, AFX_IDW_HSCROLL_FIRST));
|
|
SetGripperPosition(60, true);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_wndHScrollBar.DestroyWindow();
|
|
m_rectSB_H = CRect(0, 0, 0, 0);
|
|
}
|
|
|
|
RecalcLayout();
|
|
SetGripperPosition(m_iGripperPosPerCent, true);
|
|
|
|
RedrawWindow();
|
|
|
|
}
|
|
|
|
|
|
int CXTPExcelTabCtrl::GetGripperPosition() const
|
|
{
|
|
return m_xGripperPos;
|
|
}
|
|
|
|
|
|
BOOL CXTPExcelTabCtrl::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
if (GetItemCount() == 0)
|
|
{
|
|
pDC->FillSolidRect(m_rectViews, GetXtremeColor(COLOR_3DFACE));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::CreateButtonIcons()
|
|
{
|
|
// obsolete
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::FreeButtonIcons()
|
|
{
|
|
// obsolete
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::GetTabWidth(int nItem) const
|
|
{
|
|
CDC *pDC = CDC::FromHandle(::GetDC(m_hWnd));
|
|
|
|
CFont* pOldFont = pDC->SelectObject((m_nCurSel == nItem) ?
|
|
m_pBoldFont : m_pNormFont);
|
|
|
|
CSize size = pDC->GetTextExtent(m_tcbItems[nItem]->szTabLabel);
|
|
pDC->SelectObject(pOldFont);
|
|
|
|
::ReleaseDC(m_hWnd, pDC->m_hDC);
|
|
|
|
return size.cx + m_cy + (m_cy / 2);
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::GetTotalTabWidth() const
|
|
{
|
|
int iWidth = 0;
|
|
const int cItems = GetItemCount();
|
|
const int iOverlap = GetOverlap();
|
|
int i;
|
|
for (i = 0; i < cItems; i++)
|
|
{
|
|
iWidth += GetTabWidth(i);
|
|
if (i != 0)
|
|
{
|
|
iWidth -= iOverlap;
|
|
}
|
|
}
|
|
return iWidth;
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::GetTotalArrowWidth() const
|
|
{
|
|
int iWidth = 0;
|
|
|
|
if (m_dwStyle & FTS_XTP_HASARROWS)
|
|
iWidth += (m_cx * 2);
|
|
|
|
if (m_dwStyle & FTS_XTP_HASHOMEEND)
|
|
iWidth += (m_cx * 2);
|
|
|
|
return iWidth;
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::GetTotalTabAreaWidth() const
|
|
{
|
|
int iWidth;
|
|
if (m_dwStyle & FTS_XTP_HSCROLL)
|
|
{
|
|
iWidth = m_xGripperPos;
|
|
}
|
|
else
|
|
{
|
|
iWidth = m_nClientWidth;
|
|
}
|
|
iWidth -= GetTotalArrowWidth();
|
|
return iWidth;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::InvalidateTabs()
|
|
{
|
|
if (GetSafeHwnd())
|
|
{
|
|
// invalidate the visible tab area
|
|
// to minimize flicker - don't erase the background
|
|
CRect rcTabs;
|
|
|
|
rcTabs.left = GetTotalArrowWidth();
|
|
rcTabs.top = m_rectTabs.top;
|
|
rcTabs.right = rcTabs.left + (GetTotalTabWidth() - m_nOffset);
|
|
rcTabs.bottom = m_rectTabs.bottom;
|
|
InvalidateRect(&rcTabs, FALSE);
|
|
|
|
// invalidate the blank area to the right of the tabs
|
|
if (rcTabs.right < m_nClientWidth)
|
|
{
|
|
rcTabs.left = rcTabs.right;
|
|
rcTabs.right = m_nClientWidth;
|
|
InvalidateRect(&rcTabs, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::EnableButtons()
|
|
{
|
|
if (m_dwStyle & FTS_XTP_HASARROWS)
|
|
{
|
|
m_buttons[m_iBtnLeft].m_bEnabled = (m_nOffset > 0);
|
|
m_buttons[m_iBtnRight].m_bEnabled =
|
|
(GetTotalTabWidth() - m_nOffset > GetTotalTabAreaWidth() - 1);
|
|
|
|
if (m_dwStyle & FTS_XTP_HASHOMEEND)
|
|
{
|
|
m_buttons[m_iBtnHome].m_bEnabled = m_buttons[m_iBtnLeft].m_bEnabled;
|
|
m_buttons[m_iBtnEnd].m_bEnabled = m_buttons[m_iBtnRight].m_bEnabled;
|
|
}
|
|
|
|
CRect rc = m_buttons[m_iBtnLeft].m_rect;
|
|
rc.left = 0;
|
|
rc.right = GetTotalArrowWidth();
|
|
InvalidateRect(rc);
|
|
}
|
|
else
|
|
{
|
|
InvalidateRect(CRect(0, 0, GetTotalArrowWidth(), m_nClientHeight));
|
|
}
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::GetItemRect(int nItem, LPRECT lpRect)
|
|
{
|
|
const int cItems = GetItemCount();
|
|
if (nItem < 0 || nItem >= cItems)
|
|
return FALSE;
|
|
|
|
const int iOverlap = GetOverlap();
|
|
int x = GetTotalArrowWidth();
|
|
int i;
|
|
for (i = 0; i < nItem; i++)
|
|
{
|
|
x += GetTabWidth(i) - iOverlap;
|
|
}
|
|
lpRect->left = x - m_nOffset;
|
|
lpRect->top = m_rectTabs.top;
|
|
lpRect->right = lpRect->left + GetTabWidth(nItem);
|
|
lpRect->bottom = m_rectTabs.bottom;
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::ResetMouseOver()
|
|
{
|
|
for (int i = 0; i < BUTTON_COUNT; ++i)
|
|
{
|
|
m_buttons[i].m_bHilight = false;
|
|
}
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::ButtonHitTest(CPoint& pt)
|
|
{
|
|
ResetMouseOver();
|
|
|
|
int i;
|
|
for (i = 0; i < BUTTON_COUNT; ++i)
|
|
{
|
|
if (m_buttons[i].m_rect.PtInRect(pt))
|
|
{
|
|
m_buttons[i].m_bHilight = true;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::HitTest(TCHITTESTINFO* pHitTestInfo) const
|
|
{
|
|
// ignore hits on the buttons
|
|
int iHitX = pHitTestInfo->pt.x;
|
|
if (iHitX < GetTotalArrowWidth())
|
|
return -1;
|
|
|
|
// on or to the right of the the scroll bar/gripper ?
|
|
if ((m_dwStyle & FTS_XTP_HSCROLL) && iHitX > m_rectGripper.left)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
const int iOverlap = GetOverlap();
|
|
|
|
// check if any tabs were hit
|
|
int x = GetTotalArrowWidth() - m_nOffset;
|
|
const int cItems = GetItemCount();
|
|
int i;
|
|
for (i = 0; i < cItems; i++)
|
|
{
|
|
int iTabWidth = GetTabWidth(i);
|
|
if (i != cItems - 1)
|
|
{
|
|
iTabWidth -= iOverlap;
|
|
}
|
|
if ((x <= iHitX) && (iHitX <= x + iTabWidth))
|
|
{
|
|
return i;
|
|
}
|
|
x += iTabWidth;
|
|
}
|
|
|
|
// hit point is right of rightmost tab
|
|
return -1;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnLeftArrow()
|
|
{
|
|
// Move the tabs right, ensuring that we move right by one
|
|
// whole tab each time ala Microsoft Access
|
|
|
|
CPoint Point(GetTotalArrowWidth() + 1 + GetOverlap(), 1);
|
|
|
|
TCHITTESTINFO htInfo;
|
|
htInfo.pt = Point;
|
|
int iTab = HitTest(&htInfo);
|
|
|
|
if (iTab != -1)
|
|
{
|
|
m_nOffset = 0;
|
|
RECT rect;
|
|
if (GetItemRect(iTab - 1, &rect))
|
|
{
|
|
m_nOffset += rect.left;
|
|
m_nOffset -= GetTotalArrowWidth();
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnRightArrow()
|
|
{
|
|
// Move the tabs left, ensuring that we move left by one
|
|
// whole tab each time ala Microsoft Access
|
|
|
|
CPoint Point(GetTotalArrowWidth()+ 1 + GetOverlap(), 1);
|
|
|
|
TCHITTESTINFO htInfo;
|
|
htInfo.pt = Point;
|
|
int iTab = HitTest(&htInfo);
|
|
|
|
if (iTab != -1)
|
|
{
|
|
RECT rect;
|
|
if (GetItemRect(iTab + 1, &rect))
|
|
{
|
|
m_nOffset += rect.left - GetTotalArrowWidth();
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnHomeArrow()
|
|
{
|
|
m_nOffset = 0;
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnEndArrow()
|
|
{
|
|
m_nOffset = GetTotalTabWidth() - GetTotalTabAreaWidth() + 1;
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CWnd::OnSize(nType, cx, cy);
|
|
|
|
m_nClientWidth = cx;
|
|
m_nClientHeight = cy;
|
|
|
|
RecalcLayout();
|
|
SetGripperPosition(m_iGripperPosPerCent, true);
|
|
SyncScrollBar();
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::InsertItem(int nItem, LPCTSTR lpszItem, CWnd* pWndControl)
|
|
{
|
|
const int cItems = GetItemCount();
|
|
if (nItem < 0 || nItem > cItems)
|
|
return -1;
|
|
|
|
if (pWndControl)
|
|
{
|
|
ASSERT(::IsWindow(pWndControl->m_hWnd));
|
|
|
|
// managed view should be a hidden child
|
|
ASSERT((::GetWindowLong(pWndControl->m_hWnd, GWL_STYLE) & (WS_VISIBLE | WS_CHILD)) == WS_CHILD);
|
|
|
|
// can't have both managed and non-managed tabs
|
|
ASSERT(m_bManagingViews || cItems == 0);
|
|
|
|
m_bManagingViews = true;
|
|
|
|
pWndControl->SetParent(this);
|
|
pWndControl->SetWindowPos(NULL, m_rectViews.left, m_rectViews.top,
|
|
m_rectViews.Width(), m_rectViews.Height(),
|
|
SWP_NOZORDER | SWP_NOREDRAW);
|
|
}
|
|
|
|
// Allocate a new CXTPTcbItem object.
|
|
CXTPTcbItem* pMember = new CXTPTcbItem;
|
|
if (pMember == NULL)
|
|
return -1;
|
|
|
|
pMember->pWnd = pWndControl;
|
|
pMember->szTabLabel = lpszItem;
|
|
pMember->szToolTipLabel = lpszItem;
|
|
pMember->uiToolTipId = GetItemCount();
|
|
|
|
if (nItem <= m_nCurSel) ++m_nCurSel;
|
|
|
|
// Add the new CXTPTcbItem to the tab item list.
|
|
m_tcbItems.InsertAt(nItem, pMember);
|
|
|
|
if (m_nCurSel < 0) m_nCurSel = 0;
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
SetCurSel(nItem);
|
|
|
|
return nItem;
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::_DeleteItem(int nItem)
|
|
{
|
|
const int cItems = (int)m_tcbItems.GetSize();
|
|
if (nItem < 0 || nItem >= cItems)
|
|
return FALSE;
|
|
|
|
// Remove the item from the string arrays.
|
|
CWnd *pWndControl = m_tcbItems[nItem]->pWnd;
|
|
if (::IsWindow(pWndControl->GetSafeHwnd()))
|
|
{
|
|
pWndControl->ShowWindow(SW_HIDE);
|
|
pWndControl->SetParent(NULL);
|
|
}
|
|
SAFE_DELETE(m_tcbItems[nItem]);
|
|
m_tcbItems.RemoveAt(nItem);
|
|
if (m_tcbItems.GetSize() == 0)
|
|
{
|
|
m_bManagingViews = false;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::DeleteItem(int nItem)
|
|
{
|
|
if (!_DeleteItem(nItem))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
const int cItems = GetItemCount();
|
|
ASSERT(cItems >= 0);
|
|
|
|
if (cItems == 0)
|
|
{
|
|
m_nCurSel = -1;
|
|
}
|
|
else
|
|
{
|
|
if (nItem == m_nCurSel)
|
|
{
|
|
m_nCurSel = 0;
|
|
SetCurSel(0);
|
|
}
|
|
else if (m_nCurSel > nItem)
|
|
{
|
|
--m_nCurSel;
|
|
}
|
|
}
|
|
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::ClearAllItems()
|
|
{
|
|
while (_DeleteItem(0))
|
|
{
|
|
};
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::DeleteAllItems()
|
|
{
|
|
ClearAllItems();
|
|
|
|
// Reset the currently selected tab to -1 as we have no tabs in our list now.
|
|
m_nCurSel = -1;
|
|
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::SetCurSel(int nItem)
|
|
{
|
|
const int cItems = GetItemCount();
|
|
if (nItem < 0 || nItem >= cItems)
|
|
return -1;
|
|
|
|
int iPrevSel = m_nCurSel;
|
|
m_nCurSel = nItem;
|
|
|
|
// test if we need to center on the selected tab
|
|
CRect rcItem;
|
|
if (GetItemRect(nItem, &rcItem))
|
|
{
|
|
// test if the tab is off on the left
|
|
int iTotalArrowWidth = GetTotalArrowWidth();
|
|
rcItem.left -= iTotalArrowWidth;
|
|
if (rcItem.left <= 0)
|
|
m_nOffset += rcItem.left;
|
|
else
|
|
{
|
|
// test if the tab is off on the right
|
|
rcItem.right -= iTotalArrowWidth;
|
|
int iTabAreaWidth = GetTotalTabAreaWidth();
|
|
if (rcItem.right > iTabAreaWidth)
|
|
m_nOffset += (rcItem.right - iTabAreaWidth);
|
|
}
|
|
}
|
|
|
|
// hide/show managed controls
|
|
ASSERT(iPrevSel >= 0);
|
|
if (iPrevSel < cItems && m_tcbItems[iPrevSel]->pWnd->GetSafeHwnd())
|
|
{
|
|
m_tcbItems[iPrevSel]->pWnd->ShowWindow(SW_HIDE);
|
|
}
|
|
if (m_tcbItems[m_nCurSel]->pWnd->GetSafeHwnd())
|
|
{
|
|
m_tcbItems[m_nCurSel]->pWnd->ShowWindow(SW_SHOW);
|
|
}
|
|
|
|
// reset scroll bar position
|
|
SyncScrollBar();
|
|
|
|
EnableButtons();
|
|
InvalidateTabs();
|
|
|
|
return iPrevSel;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
TCHITTESTINFO tchtinfo;
|
|
tchtinfo.pt = point;
|
|
|
|
// sizing grip ?
|
|
if (m_rectGripper.PtInRect(point))
|
|
{
|
|
ASSERT(m_bTracking == false);
|
|
SetTracking(true);
|
|
return;
|
|
}
|
|
|
|
// on a button ?
|
|
int iButton = ButtonHitTest(point);
|
|
if (iButton >= 0)
|
|
{
|
|
CXTPExcelTabCtrlButtonState& b = m_buttons[iButton];
|
|
if (b.m_bEnabled)
|
|
{
|
|
b.m_bPressed = true;
|
|
RedrawWindow(b.m_rect);
|
|
SetCapture();
|
|
}
|
|
return;
|
|
}
|
|
|
|
int iTab = HitTest(&tchtinfo);
|
|
if ((iTab != -1) && (iTab != m_nCurSel))
|
|
{
|
|
// warn parent that the selection is about to change
|
|
int id = GetDlgCtrlID();
|
|
NMHDR hdr;
|
|
hdr.hwndFrom = m_hWnd;
|
|
hdr.idFrom = id;
|
|
hdr.code = TCN_SELCHANGING;
|
|
if (GetOwner()->SendMessage(WM_NOTIFY, id, (LPARAM)&hdr) == 0)
|
|
{
|
|
// parent has given permission for the selection to change
|
|
SetCurSel(iTab);
|
|
InvalidateTabs();
|
|
|
|
// notify parent that the selection has changed
|
|
hdr.hwndFrom = m_hWnd;
|
|
hdr.idFrom = id;
|
|
hdr.code = TCN_SELCHANGE;
|
|
GetOwner()->SendMessage(WM_NOTIFY, id, (LPARAM)&hdr);
|
|
}
|
|
}
|
|
|
|
CWnd::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bTracking)
|
|
{
|
|
SetTracking(false);
|
|
}
|
|
|
|
// on a button ?
|
|
int i;
|
|
for (i = 0; i < BUTTON_COUNT; ++i)
|
|
{
|
|
CXTPExcelTabCtrlButtonState& b = m_buttons[i];
|
|
if (b.m_bEnabled & b.m_bPressed)
|
|
{
|
|
PostMessage(WM_COMMAND, b.m_iCommand, NULL);
|
|
b.m_bPressed = false;
|
|
RedrawWindow(b.m_rect);
|
|
ReleaseCapture();
|
|
return;
|
|
}
|
|
}
|
|
|
|
CWnd::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnPaint()
|
|
{
|
|
CPaintDC dc(this);
|
|
|
|
if (m_dwStyle & FTS_XTP_HSCROLL)
|
|
{
|
|
dc.ExcludeClipRect(&m_rectSB_H);
|
|
}
|
|
|
|
CXTPBufferDC memDC(dc, m_rectTabs);
|
|
OnDraw(&memDC);
|
|
}
|
|
|
|
LRESULT CXTPExcelTabCtrl::OnPrintClient(WPARAM wParam, LPARAM /*lParam*/)
|
|
{
|
|
CDC* pDC = CDC::FromHandle((HDC)wParam);
|
|
if (pDC)
|
|
{
|
|
OnDraw(pDC);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnDraw(CDC* pDC)
|
|
{
|
|
CRect rectPaint(m_rectTabs); // this the only part we care about
|
|
|
|
pDC->FillSolidRect(rectPaint, GetXtremeColor(COLOR_3DFACE));
|
|
|
|
// Exclude the arrow buttons from being repainted.
|
|
const int iTotalArrowWidth = GetTotalArrowWidth();
|
|
CRect rcArrows(rectPaint);
|
|
rcArrows.top += 1;
|
|
rcArrows.right = rcArrows.left + iTotalArrowWidth-1;
|
|
|
|
pDC->FillSolidRect(0, (m_dwStyle & FTS_XTP_BOTTOM) ? rectPaint.top : rectPaint.bottom - 1,
|
|
rectPaint.Width(), 1, m_pTheme->m_clr3DShadow);
|
|
|
|
int i;
|
|
for (i = 0; i < BUTTON_COUNT; ++i)
|
|
{
|
|
if (CRect().IntersectRect(rectPaint, m_buttons[i].m_rect))
|
|
{
|
|
m_pTheme->DrawButton(pDC, this, m_buttons[i]);
|
|
}
|
|
}
|
|
|
|
if (rectPaint.right >= rcArrows.right)
|
|
{
|
|
const int nTotalTabWidth = GetTotalTabWidth();
|
|
|
|
// Draw the tabs to an offscreen device context, this is done
|
|
// so that we can "scroll" the entire tab group left or right whenever
|
|
// any of the arrow buttons are pressed.
|
|
CDC tabDC;
|
|
tabDC.CreateCompatibleDC(pDC);
|
|
CBitmap bitmap;
|
|
bitmap.CreateCompatibleBitmap(pDC, nTotalTabWidth, m_cy);
|
|
CBitmap* pOldBitmap = tabDC.SelectObject(&bitmap);
|
|
|
|
// Fill the background color.
|
|
CRect rcTabs(0, 0, nTotalTabWidth, m_cy);
|
|
tabDC.FillSolidRect(rcTabs, GetXtremeColor(COLOR_3DFACE));
|
|
|
|
// Define xy coordinates to draw each tab.
|
|
const int iOverlap = GetOverlap();
|
|
int x = 0;
|
|
int iSelX = 0;
|
|
int y = 0;
|
|
|
|
// Draw all of the non-selected tabs first...
|
|
const int cItems = GetItemCount();
|
|
for (i = 0; i < cItems; i++)
|
|
{
|
|
if (i != m_nCurSel)
|
|
{
|
|
const int cx = m_pTheme->DrawTab(&tabDC, this,
|
|
CPoint(x, y), false, m_tcbItems[i]);
|
|
x += cx;
|
|
}
|
|
else
|
|
{
|
|
iSelX = x;
|
|
x += GetTabWidth(i);
|
|
}
|
|
x -= iOverlap;
|
|
}
|
|
|
|
// then draw the selected tab. Make sure that m_TabList is not empty.
|
|
if (m_nCurSel >= 0 && cItems > 0)
|
|
{
|
|
m_pTheme->DrawTab(&tabDC, this,
|
|
CPoint(iSelX, y), true, m_tcbItems[m_nCurSel]);
|
|
}
|
|
|
|
// blit the bitmap onto the pDC->
|
|
pDC->BitBlt(iTotalArrowWidth, rectPaint.top, GetTotalTabAreaWidth(),
|
|
m_cy, &tabDC, m_nOffset, 0, SRCCOPY);
|
|
// cleanup.
|
|
tabDC.SelectObject(pOldBitmap);
|
|
}
|
|
|
|
if (m_dwStyle & FTS_XTP_HSCROLL)
|
|
{
|
|
DrawGripper(pDC, m_rectGripper);
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::DrawGripper(CDC* pDC, CRect rect) const
|
|
{
|
|
pDC->Draw3dRect(rect, GetXtremeColor(COLOR_3DHILIGHT), GetXtremeColor(COLOR_3DSHADOW));
|
|
rect.InflateRect(-CX_BORDER, -CY_BORDER);
|
|
|
|
// fill the middle
|
|
pDC->FillSolidRect(rect, GetXtremeColor(COLOR_3DFACE));
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
ASSERT_VALID(this);
|
|
if (pMsg->message == WM_KEYDOWN)
|
|
{
|
|
if (pMsg->wParam == VK_ESCAPE)
|
|
{
|
|
if (m_bTracking)
|
|
{
|
|
SetTracking(false);
|
|
}
|
|
|
|
return TRUE; // eat ESC keyboard press...
|
|
}
|
|
}
|
|
|
|
if (::IsWindow(m_ToolTip.m_hWnd))
|
|
{
|
|
if (pMsg->message == WM_MOUSEMOVE && pMsg->hwnd == m_hWnd)
|
|
{
|
|
CPoint Point(LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
|
|
|
|
TCHITTESTINFO htInfo;
|
|
htInfo.pt = Point;
|
|
int iTab = HitTest(&htInfo);
|
|
|
|
if (iTab >= 0)
|
|
{
|
|
CString strOldTipText;
|
|
CString strNewTipText = m_tcbItems[iTab]->szToolTipLabel;
|
|
|
|
m_ToolTip.GetText(strOldTipText, this);
|
|
|
|
// If the tip text differs, update the tooltip control.
|
|
if (strNewTipText != strOldTipText)
|
|
{
|
|
m_ToolTip.DelTool(this);
|
|
m_ToolTip.AddTool(this, strNewTipText);
|
|
}
|
|
|
|
// Pass on to tooltip.
|
|
m_ToolTip.RelayEvent(pMsg);
|
|
}
|
|
else
|
|
{
|
|
m_ToolTip.SendMessage(TTM_POP, 0, 0L);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_ToolTip.SendMessage(TTM_POP, 0, 0L);
|
|
}
|
|
}
|
|
|
|
return CWnd::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTipText(int nItem, LPCTSTR lpszTabTip)
|
|
{
|
|
const int cItems = GetItemCount();
|
|
if (nItem < 0 || nItem >= cItems)
|
|
{
|
|
ASSERT(0);
|
|
return;
|
|
}
|
|
m_tcbItems[nItem]->szToolTipLabel = lpszTabTip;
|
|
}
|
|
|
|
CString CXTPExcelTabCtrl::GetTipText(int nItem)
|
|
{
|
|
const int cItems = GetItemCount();
|
|
if (nItem < 0 || nItem >= cItems)
|
|
{
|
|
ASSERT(0);
|
|
return _T("");
|
|
}
|
|
return m_tcbItems[nItem]->szToolTipLabel;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::Home()
|
|
{
|
|
OnHomeArrow();
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bTracking)
|
|
{
|
|
// resize
|
|
SetGripperPosition(point.x + m_xTrackingDelta, false);
|
|
}
|
|
else
|
|
{
|
|
if (ButtonHitTest(point) != m_iBtnHilight)
|
|
{
|
|
SetTimer(1, 10, NULL);
|
|
OnTimer(1);
|
|
}
|
|
}
|
|
|
|
CWnd::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
if (m_bTracking && GetCapture() != this)
|
|
{
|
|
m_bTracking = FALSE;
|
|
}
|
|
|
|
POINT pt;
|
|
GetCursorPos(&pt);
|
|
ScreenToClient(&pt);
|
|
if (m_bTracking || m_rectGripper.PtInRect(pt))
|
|
{
|
|
::SetCursor(XTPAuxData().hcurHSplitBar);
|
|
return TRUE;
|
|
}
|
|
|
|
return CWnd::OnSetCursor(pWnd, nHitTest, message);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTracking(bool bTracking)
|
|
{
|
|
if (m_bTracking == bTracking)
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_bTracking = bTracking;
|
|
if (bTracking)
|
|
{
|
|
SetCapture();
|
|
POINT pt;
|
|
GetCursorPos(&pt);
|
|
ScreenToClient(&pt);
|
|
m_xTrackingDelta = GetGripperPosition() - pt.x;
|
|
m_pWndLastFocus = SetFocus();
|
|
}
|
|
else
|
|
{
|
|
ReleaseCapture();
|
|
if (::IsWindow(m_pWndLastFocus->GetSafeHwnd()))
|
|
{
|
|
m_pWndLastFocus->SetFocus();
|
|
}
|
|
else
|
|
{
|
|
m_pWndLastFocus = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
{
|
|
// on a button ?
|
|
int iButton = ButtonHitTest(point);
|
|
if (iButton >= 0)
|
|
{
|
|
CXTPExcelTabCtrlButtonState& b = m_buttons[iButton];
|
|
if (b.m_bEnabled)
|
|
{
|
|
SetCapture();
|
|
b.m_bPressed = true;
|
|
RedrawWindow(b.m_rect);
|
|
}
|
|
return;
|
|
}
|
|
|
|
CWnd::OnLButtonDblClk(nFlags, point);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* /*pScrollBar*/)
|
|
{
|
|
CWnd *pWndControl = GetItemWindow(m_nCurSel);
|
|
if (!pWndControl)
|
|
return;
|
|
|
|
if (pWndControl->GetSafeHwnd())
|
|
{
|
|
if (nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK)
|
|
{
|
|
int dx = nPos - pWndControl->GetScrollPos(SB_HORZ);
|
|
if (dx)
|
|
{
|
|
pWndControl->SendMessage(LVM_SCROLL, dx, 0);
|
|
}
|
|
}
|
|
|
|
// pass message to control's scroll bar
|
|
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
|
|
pWndControl->SendMessage(
|
|
pThreadState->m_lastSentMsg.message,
|
|
pThreadState->m_lastSentMsg.wParam,
|
|
(LPARAM)pWndControl->GetScrollBarCtrl(SB_HORZ)->GetSafeHwnd());
|
|
|
|
// reflect changes in our scroll bar
|
|
SyncScrollBar();
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SyncScrollBar()
|
|
{
|
|
if (!m_wndHScrollBar.m_hWnd)
|
|
{
|
|
return;
|
|
}
|
|
|
|
CWnd *pWndControl = NULL;
|
|
if (m_nCurSel >= 0)
|
|
{
|
|
pWndControl = m_tcbItems[m_nCurSel]->pWnd;
|
|
}
|
|
if (pWndControl && pWndControl->GetSafeHwnd())
|
|
{
|
|
pWndControl->ShowScrollBar(SB_HORZ, FALSE);
|
|
pWndControl->ModifyStyle(WS_HSCROLL, 0, SWP_DRAWFRAME);
|
|
|
|
SCROLLINFO si;
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_ALL;
|
|
|
|
if (!pWndControl->GetScrollInfo (SB_HORZ, &si) ||
|
|
si.nPage == 0 ||
|
|
si.nMin + (int) si.nPage >= si.nMax)
|
|
{
|
|
m_wndHScrollBar.EnableWindow(FALSE);
|
|
}
|
|
else
|
|
{
|
|
m_wndHScrollBar.EnableWindow(TRUE);
|
|
m_wndHScrollBar.SetScrollInfo(&si);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_wndHScrollBar.EnableWindow(FALSE);
|
|
}
|
|
}
|
|
|
|
BOOL CXTPExcelTabCtrl::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
|
{
|
|
NMHDR* pNMHDR = (NMHDR*)lParam;
|
|
ASSERT (pNMHDR != NULL);
|
|
|
|
BOOL bRetVal = CWnd::OnNotify(wParam, lParam, pResult);
|
|
|
|
if (pNMHDR && pNMHDR->code == HDN_ITEMCHANGED)
|
|
{
|
|
SyncScrollBar();
|
|
}
|
|
|
|
return bRetVal;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::RecalcLayout()
|
|
{
|
|
m_rectViews.left = m_rectTabs.left = 0;
|
|
m_rectViews.right = m_rectTabs.right = m_nClientWidth;
|
|
if (m_dwStyle & FTS_XTP_BOTTOM)
|
|
{
|
|
m_rectTabs.top = m_nClientHeight - m_cy;
|
|
m_rectViews.top = 0;
|
|
}
|
|
else
|
|
{
|
|
m_rectTabs.top = 0;
|
|
m_rectViews.top = m_cy;
|
|
}
|
|
m_rectTabs.bottom = m_rectTabs.top + m_cy;
|
|
m_rectViews.bottom = m_rectViews.top + m_nClientHeight - m_cy;
|
|
|
|
int nIndex;
|
|
|
|
// update managed view positions
|
|
if (m_bManagingViews)
|
|
{
|
|
const int cItems = GetItemCount();
|
|
for (nIndex = 0; nIndex < cItems; ++nIndex)
|
|
{
|
|
ASSERT(m_tcbItems[nIndex]->pWnd->GetSafeHwnd());
|
|
m_tcbItems[nIndex]->pWnd->SetWindowPos(NULL,
|
|
m_rectViews.left, m_rectViews.top,
|
|
m_rectViews.Width(), m_rectViews.Height(),
|
|
SWP_NOZORDER | SWP_NOREDRAW);
|
|
}
|
|
}
|
|
|
|
// update arrow buttons if we have them
|
|
if (m_dwStyle & FTS_XTP_HASARROWS)
|
|
{
|
|
CRect btnRects[] =
|
|
{
|
|
CRect(0, m_rectTabs.top + 1, m_cx, m_rectTabs.bottom),
|
|
CRect(m_cx, m_rectTabs.top + 1, m_cx * 2, m_rectTabs.bottom),
|
|
CRect(m_cx * 2, m_rectTabs.top + 1, m_cx * 3, m_rectTabs.bottom),
|
|
CRect(m_cx * 3, m_rectTabs.top + 1, m_cx * 4, m_rectTabs.bottom)
|
|
};
|
|
|
|
const int cButtons = (m_dwStyle & FTS_XTP_HASHOMEEND) ? 4 : 2;
|
|
for (nIndex = 0; nIndex < cButtons; ++nIndex)
|
|
{
|
|
m_buttons[nIndex].m_rect = btnRects[nIndex];
|
|
}
|
|
}
|
|
|
|
EnableButtons();
|
|
}
|
|
|
|
LPCTSTR CXTPExcelTabCtrl::GetItemText(int nIndex) const
|
|
{
|
|
if (nIndex < 0 || nIndex >= GetItemCount())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return m_tcbItems[nIndex]->szTabLabel;
|
|
}
|
|
|
|
bool CXTPExcelTabCtrl::SetItemText(int nIndex, LPCTSTR pszText)
|
|
{
|
|
if (nIndex < 0 || nIndex >= GetItemCount())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
m_tcbItems[nIndex]->szTabLabel = pszText;
|
|
RecalcLayout();
|
|
InvalidateTabs();
|
|
return true;
|
|
}
|
|
|
|
CWnd *CXTPExcelTabCtrl::GetItemWindow(int nIndex) const
|
|
{
|
|
if (nIndex < 0 || nIndex >= GetItemCount())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return m_tcbItems[nIndex]->pWnd;
|
|
}
|
|
|
|
int CXTPExcelTabCtrl::GetOverlap() const
|
|
{
|
|
return ((m_cy / 2) + 2);
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::UpdateDefaultColors()
|
|
{
|
|
RefreshMetrics();
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabShadowColor(COLORREF crShadow)
|
|
{
|
|
m_pTheme->m_clr3DShadow.SetCustomValue(crShadow);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetTabShadowColor() const
|
|
{
|
|
return m_pTheme->m_clr3DShadow;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabHilightColor(COLORREF crHilight)
|
|
{
|
|
m_pTheme->m_clr3DHilight.SetCustomValue(crHilight);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetTabHilightColor() const
|
|
{
|
|
return m_pTheme->m_clr3DHilight;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabBackColor(COLORREF crBack)
|
|
{
|
|
m_pTheme->m_clr3DFace.SetCustomValue(crBack);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetTabBackColor() const
|
|
{
|
|
return m_pTheme->m_clr3DFace;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabTextColor(COLORREF crText)
|
|
{
|
|
m_pTheme->m_clrBtnText.SetCustomValue(crText);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetTabTextColor() const
|
|
{
|
|
return m_pTheme->m_clrBtnText;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetSelTabBackColor(COLORREF crBack)
|
|
{
|
|
m_pTheme->m_clrWindow.SetCustomValue(crBack);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetSelTabBackColor() const
|
|
{
|
|
return m_pTheme->m_clrWindow;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetSelTabTextColor(COLORREF crText)
|
|
{
|
|
m_pTheme->m_clrWindowText.SetCustomValue(crText);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetSelTabTextColor() const
|
|
{
|
|
return m_pTheme->m_clrWindowText;
|
|
}
|
|
|
|
CScrollBar* CXTPExcelTabCtrl::GetScrollBarCtrl(int nBar) const
|
|
{
|
|
if (nBar == SB_HORZ && ::IsWindow(m_wndHScrollBar.m_hWnd))
|
|
{
|
|
return (CScrollBar*)&m_wndHScrollBar;
|
|
}
|
|
return CWnd::GetScrollBarCtrl(nBar);
|
|
}
|
|
|
|
CRect CXTPExcelTabCtrl::GetTotalButtonRect() const
|
|
{
|
|
CRect rect;
|
|
|
|
rect.CopyRect(&m_buttons[0].m_rect);
|
|
|
|
int iWidth = 0;
|
|
for (int i = 0; i < BUTTON_COUNT; ++i)
|
|
{
|
|
iWidth += m_buttons[i].m_rect.Width();
|
|
}
|
|
|
|
rect.right = rect.left + iWidth;
|
|
|
|
return rect;
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::OnTimer(UINT_PTR nIDEvent)
|
|
{
|
|
if (nIDEvent == 1)
|
|
{
|
|
CRect rc;
|
|
GetWindowRect(rc);
|
|
|
|
CPoint point;
|
|
GetCursorPos(&point);
|
|
ScreenToClient(&point);
|
|
|
|
int iBtnHilight = ButtonHitTest(point);
|
|
if (iBtnHilight == -1)
|
|
{
|
|
KillTimer(1);
|
|
|
|
if (m_bPainted == TRUE)
|
|
{
|
|
CRect rect = GetTotalButtonRect();
|
|
InvalidateRect(&rect);
|
|
}
|
|
|
|
m_iBtnHilight = iBtnHilight;
|
|
m_bPainted = FALSE;
|
|
}
|
|
|
|
// On mouse over, show raised button.
|
|
else if (!m_bPainted || (iBtnHilight != m_iBtnHilight))
|
|
{
|
|
CRect rect = GetTotalButtonRect();
|
|
InvalidateRect(&rect);
|
|
|
|
m_iBtnHilight = iBtnHilight;
|
|
m_bPainted = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CWnd::OnTimer(nIDEvent);
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabBackColor(int nIndex, COLORREF crBack)
|
|
{
|
|
if (nIndex >= 0 && nIndex < GetItemCount())
|
|
{
|
|
m_tcbItems[nIndex]->crTabBack = crBack;
|
|
|
|
CRect rcItem;
|
|
GetItemRect(nIndex, &rcItem);
|
|
InvalidateRect(rcItem);
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetTabTextColor(int nIndex, COLORREF crText)
|
|
{
|
|
if (nIndex >= 0 && nIndex < GetItemCount())
|
|
{
|
|
m_tcbItems[nIndex]->crTabText = crText;
|
|
|
|
CRect rcItem;
|
|
GetItemRect(nIndex, &rcItem);
|
|
InvalidateRect(rcItem);
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetSelTabBackColor(int nIndex, COLORREF crSelBack)
|
|
{
|
|
if (nIndex >= 0 && nIndex < GetItemCount())
|
|
{
|
|
m_tcbItems[nIndex]->crTabSelBack = crSelBack;
|
|
|
|
CRect rcItem;
|
|
GetItemRect(nIndex, &rcItem);
|
|
InvalidateRect(rcItem);
|
|
}
|
|
}
|
|
|
|
void CXTPExcelTabCtrl::SetSelTabTextColor(int nIndex, COLORREF crSelText)
|
|
{
|
|
if (nIndex >= 0 && nIndex < GetItemCount())
|
|
{
|
|
m_tcbItems[nIndex]->crTabSelText = crSelText;
|
|
|
|
CRect rcItem;
|
|
GetItemRect(nIndex, &rcItem);
|
|
InvalidateRect(rcItem);
|
|
}
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetTabBackColor(int nIndex) const
|
|
{
|
|
return m_pTheme->GetTabBackColor(m_tcbItems[nIndex]);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetTabTextColor(int nIndex) const
|
|
{
|
|
return m_pTheme->GetTabTextColor(m_tcbItems[nIndex]);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetSelTabBackColor(int nIndex) const
|
|
{
|
|
return m_pTheme->GetSelTabBackColor(m_tcbItems[nIndex]);
|
|
}
|
|
|
|
COLORREF CXTPExcelTabCtrl::GetSelTabTextColor(int nIndex) const
|
|
{
|
|
return m_pTheme->GetSelTabTextColor(m_tcbItems[nIndex]);
|
|
}
|