// XTabCtrl.cpp : implementation file
|
//
|
|
#include "stdafx.h"
|
#include "XTabCtrl.h"
|
|
#ifdef _DEBUG
|
#define new DEBUG_NEW
|
#undef THIS_FILE
|
static char THIS_FILE[] = __FILE__;
|
#endif
|
|
/////////////////////////////////////////////////////////////////////////////
|
// CXTabCtrl
|
|
CXTabCtrl::CXTabCtrl()
|
{
|
m_iSelectedTab = 0;
|
m_ptTabs.x = 0;
|
m_ptTabs.y = 20;
|
|
m_crSelected = 0;
|
m_crDisabled = 0;
|
m_crNormal = 0;
|
m_crMouseOver = 0;
|
m_crBKColor = RGB(255,255,255);
|
|
m_bColorSelected = false;
|
m_bColorDisabled = false;
|
m_bColorNormal = false;
|
m_bColorMouseOver = false;
|
|
|
m_iIndexMouseOver = -1;
|
|
m_bMouseOver = false;
|
}
|
|
CXTabCtrl::~CXTabCtrl()
|
{
|
m_arrayStatusTab.RemoveAll();
|
}
|
|
BEGIN_MESSAGE_MAP(CXTabCtrl, CTabCtrl)
|
//{{AFX_MSG_MAP(CXTabCtrl)
|
ON_NOTIFY_REFLECT(TCN_SELCHANGE, OnSelchange)
|
ON_NOTIFY_REFLECT(TCN_SELCHANGING, OnSelchanging)
|
ON_WM_MOUSEMOVE()
|
ON_WM_TIMER()
|
//}}AFX_MSG_MAP
|
ON_WM_PAINT()
|
END_MESSAGE_MAP()
|
|
/////////////////////////////////////////////////////////////////////////////
|
// CXTabCtrl message handlers
|
|
void CXTabCtrl::SetTopLeftCorner(CPoint pt)
|
{
|
m_ptTabs.x = pt.x;
|
m_ptTabs.y = pt.y;
|
}
|
|
void CXTabCtrl::SetMouseOverColor(COLORREF cr)
|
{
|
m_bColorMouseOver = true;
|
m_crMouseOver = cr;
|
}
|
|
void CXTabCtrl::SetDisabledColor(COLORREF cr)
|
{
|
m_bColorDisabled = true;
|
m_crDisabled = cr;
|
}
|
|
void CXTabCtrl::SetSelectedColor(COLORREF cr)
|
{
|
m_bColorSelected = true;
|
m_crSelected = cr;
|
}
|
|
void CXTabCtrl::SetNormalColor(COLORREF cr)
|
{
|
m_bColorNormal = true;
|
m_crNormal = cr;
|
}
|
|
void CXTabCtrl::AddTab(CWnd* pWnd, LPTSTR lpszCaption, int iImage)
|
{
|
ASSERT_VALID(pWnd);
|
|
TCITEM item;
|
item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE;
|
item.lParam = (LPARAM) pWnd;
|
item.pszText = lpszCaption;
|
item.iImage = iImage;
|
|
int iIndex = static_cast<int>(m_arrayStatusTab.GetSize());
|
InsertItem(iIndex, &item);
|
|
pWnd->SetWindowPos(NULL, m_ptTabs.x, m_ptTabs.y, 505, 415,
|
SWP_FRAMECHANGED | SWP_NOZORDER);
|
|
pWnd->ShowWindow(iIndex ? SW_HIDE : SW_SHOW);
|
|
//** the initial status is enabled
|
m_arrayStatusTab.Add(TRUE);
|
}
|
|
void CXTabCtrl::AddTab(CWnd* pWnd, LPTSTR lpszCaption, int Width, int Height, int iImage)
|
{
|
ASSERT_VALID(pWnd);
|
|
TCITEM item;
|
item.mask = TCIF_TEXT|TCIF_PARAM|TCIF_IMAGE;
|
item.lParam = (LPARAM) pWnd;
|
item.pszText = lpszCaption;
|
item.iImage = iImage;
|
|
int iIndex = static_cast<int>(m_arrayStatusTab.GetSize());
|
InsertItem(iIndex, &item);
|
|
//if(Width==0 && Height==0)
|
//{
|
// int nX, nY, nXc, nYc;
|
// CRect tabRect, itemRect;
|
// GetClientRect(&tabRect);
|
// GetItemRect(0, &itemRect);
|
|
// nX=itemRect.left;
|
// nY=itemRect.bottom+1;
|
// nXc=tabRect.right-itemRect.left-1;
|
// nYc=tabRect.bottom-nY-1;
|
|
// pWnd->SetWindowPos(NULL, nX, nY, nXc, nYc, SWP_FRAMECHANGED | SWP_NOZORDER);
|
//}
|
//else
|
//{
|
// pWnd->SetWindowPos(NULL, m_ptTabs.x, m_ptTabs.y, Width, Height,
|
// SWP_FRAMECHANGED | SWP_NOZORDER);
|
//}
|
|
pWnd->SetWindowPos(NULL, m_ptTabs.x, m_ptTabs.y, Width, Height,
|
SWP_FRAMECHANGED | SWP_NOZORDER);
|
|
pWnd->ShowWindow(iIndex ? SW_HIDE : SW_SHOW);
|
|
//** the initial status is enabled
|
m_arrayStatusTab.Add(TRUE);
|
}
|
|
void CXTabCtrl::EnableTab(int iIndex, BOOL bEnable)
|
{
|
ASSERT(iIndex < m_arrayStatusTab.GetSize());
|
|
//** if it should change the status ----
|
if (m_arrayStatusTab[iIndex] != bEnable)
|
{
|
m_arrayStatusTab[iIndex] = bEnable;
|
|
//** redraw the item -------
|
CRect rect;
|
|
GetItemRect(iIndex, &rect);
|
InvalidateRect(rect);
|
}
|
}
|
|
void CXTabCtrl::DeleteAllTabs()
|
{
|
m_arrayStatusTab.RemoveAll();
|
|
DeleteAllItems();
|
}
|
|
void CXTabCtrl::DeleteTab(int iIndex)
|
{
|
ASSERT(iIndex < m_arrayStatusTab.GetSize());
|
|
m_arrayStatusTab.RemoveAt(iIndex);
|
|
DeleteItem(iIndex);
|
}
|
|
BOOL CXTabCtrl::IsTabEnabled(int iIndex)
|
{
|
ASSERT(iIndex < m_arrayStatusTab.GetSize());
|
|
return m_arrayStatusTab[iIndex];
|
}
|
|
BOOL CXTabCtrl::SelectTab(int iIndex)
|
{
|
ASSERT(iIndex < m_arrayStatusTab.GetSize());
|
|
if (GetCurSel() == iIndex)
|
return TRUE;
|
|
//** check if the tab is enabled --------
|
if (m_arrayStatusTab[iIndex])
|
{
|
TCITEM item;
|
CWnd* pWnd;
|
item.mask = TCIF_PARAM;
|
|
GetItem(GetCurSel(), &item);
|
pWnd = reinterpret_cast<CWnd*> (item.lParam);
|
ASSERT_VALID(pWnd);
|
pWnd->ShowWindow(SW_HIDE);
|
|
SetCurSel(iIndex);
|
GetItem(iIndex, &item);
|
pWnd = reinterpret_cast<CWnd*> (item.lParam);
|
ASSERT_VALID(pWnd);
|
pWnd->ShowWindow(SW_SHOW);
|
|
return TRUE;
|
}
|
|
return FALSE;
|
}
|
|
void CXTabCtrl::OnSelchange(NMHDR* pNMHDR, LRESULT* pResult)
|
{
|
// TODO: Add your control notification handler code here
|
int iNewTab = GetCurSel();
|
|
if (!IsTabEnabled(iNewTab))
|
{
|
SetCurSel(m_iSelectedTab);
|
}
|
else
|
{
|
TCITEM item;
|
CWnd* pWnd;
|
|
item.mask = TCIF_PARAM;
|
|
//** hide the current tab ---------
|
GetItem(m_iSelectedTab, &item);
|
pWnd = reinterpret_cast<CWnd*> (item.lParam);
|
ASSERT_VALID(pWnd);
|
pWnd->ShowWindow(SW_HIDE);
|
|
//** show the selected tab --------
|
GetItem(iNewTab, &item);
|
pWnd = reinterpret_cast<CWnd*> (item.lParam);
|
ASSERT_VALID(pWnd);
|
pWnd->ShowWindow(SW_SHOW);
|
}
|
|
*pResult = 0;
|
}
|
|
void CXTabCtrl::OnSelchanging(NMHDR* pNMHDR, LRESULT* pResult)
|
{
|
// TODO: Add your control notification handler code here
|
m_iSelectedTab = GetCurSel();
|
|
*pResult = 0;
|
}
|
|
void CXTabCtrl::PreSubclassWindow()
|
{
|
// TODO: Add your specialized code here and/or call the base class
|
CTabCtrl::PreSubclassWindow();
|
ModifyStyle(0, TCS_OWNERDRAWFIXED);
|
}
|
|
void CXTabCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
|
{
|
CRect rect = lpDrawItemStruct->rcItem;
|
rect.top += ::GetSystemMetrics(SM_CYEDGE);
|
|
int nTabIndex = lpDrawItemStruct->itemID;
|
|
if (nTabIndex < 0) return;
|
|
BOOL bSelected = (nTabIndex == GetCurSel());
|
|
COLORREF crSelected = m_bColorSelected ? m_crSelected : GetSysColor(COLOR_BTNTEXT);
|
COLORREF crNormal = m_bColorNormal ? m_crNormal : GetSysColor(COLOR_BTNTEXT);
|
COLORREF crDisabled = m_bColorDisabled ? m_crDisabled : GetSysColor(COLOR_GRAYTEXT);
|
|
|
TCHAR label[64];
|
TC_ITEM item;
|
item.mask = TCIF_TEXT|TCIF_IMAGE;
|
item.pszText = label;
|
item.cchTextMax = 63;
|
if (!GetItem(nTabIndex, &item))
|
return;
|
|
CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
|
if (!pDC)
|
return;
|
|
int nSavedDC = pDC->SaveDC();
|
|
CRect rectItem;
|
POINT pt;
|
|
GetItemRect(nTabIndex, &rectItem);
|
GetCursorPos(&pt);
|
ScreenToClient(&pt);
|
|
if (rectItem.PtInRect(pt))
|
m_iIndexMouseOver = nTabIndex;
|
|
pDC->SetBkMode(TRANSPARENT);
|
pDC->FillSolidRect(rect, m_crBKColor);
|
//pDC->FillSolidRect(rect, ::GetSysColor(COLOR_BTNFACE));
|
|
//** Draw the image
|
CImageList* pImageList = GetImageList();
|
if (pImageList && item.iImage >= 0)
|
{
|
|
rect.left += pDC->GetTextExtent(_T(" ")).cx;
|
|
IMAGEINFO info;
|
pImageList->GetImageInfo(item.iImage, &info);
|
CRect ImageRect(info.rcImage);
|
int nYpos = rect.top;
|
|
pImageList->Draw(pDC, item.iImage, CPoint(rect.left, nYpos), ILD_TRANSPARENT);
|
rect.left += ImageRect.Width();
|
}
|
|
if (!IsTabEnabled(nTabIndex))
|
{
|
pDC->SetTextColor(crDisabled);
|
rect.top -= ::GetSystemMetrics(SM_CYEDGE);
|
pDC->DrawText(label, rect, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
|
}
|
else
|
{
|
//** selected item -----
|
if (bSelected)
|
pDC->SetTextColor(crSelected);
|
else //** other item ---
|
{
|
if (m_bColorMouseOver && nTabIndex == m_iIndexMouseOver)
|
{
|
pDC->SetTextColor(m_crMouseOver);
|
}
|
else
|
{
|
pDC->SetTextColor(crNormal);
|
}
|
}
|
|
rect.top -= ::GetSystemMetrics(SM_CYEDGE);
|
pDC->DrawText(label, rect, DT_SINGLELINE|DT_VCENTER|DT_CENTER);
|
|
}
|
|
pDC->RestoreDC(nSavedDC);
|
}
|
|
void CXTabCtrl::OnMouseMove(UINT nFlags, CPoint point)
|
{
|
// TODO: Add your message handler code here and/or call default
|
|
//** if we should change the color of the tab ctrl ---
|
if (m_bColorMouseOver)
|
{
|
SetTimer(1,10,NULL);
|
|
if (m_iIndexMouseOver != -1)
|
{
|
CRect rectItem;
|
GetItemRect(m_iIndexMouseOver, rectItem);
|
if (!rectItem.PtInRect(point))
|
{
|
CRect rectOldItem;
|
GetItemRect(m_iIndexMouseOver, rectOldItem);
|
m_iIndexMouseOver = -1;
|
InvalidateRect(rectOldItem);
|
return;
|
}
|
}
|
|
|
if (!m_bMouseOver)
|
{
|
TCHITTESTINFO hitTest;
|
|
m_bMouseOver = true;
|
hitTest.pt = point;
|
|
int iItem = HitTest(&hitTest);
|
if (iItem != -1 && m_arrayStatusTab[iItem])
|
{
|
RECT rectItem;
|
GetItemRect(iItem, &rectItem);
|
|
InvalidateRect(&rectItem);
|
}
|
}
|
}
|
|
CTabCtrl::OnMouseMove(nFlags, point);
|
}
|
|
void CXTabCtrl::OnTimer(UINT_PTR nIDEvent)
|
{
|
// TODO: Add your message handler code here and/or call default
|
POINT pt;
|
GetCursorPos(&pt);
|
CRect rectItem, rectScreen;
|
|
GetItemRect(m_iIndexMouseOver, rectItem);
|
rectScreen = rectItem;
|
ClientToScreen(rectScreen);
|
|
// If mouse leaves, show normal
|
if (!rectScreen.PtInRect(pt))
|
{
|
KillTimer (1);
|
m_bMouseOver = false;
|
m_iIndexMouseOver = -1;
|
InvalidateRect(rectItem);
|
}
|
|
|
CTabCtrl::OnTimer(nIDEvent);
|
}
|
|
BOOL CXTabCtrl::OnEraseBkgnd(CDC* pDC)
|
{
|
// TODO: Add your message handler code here and/or call default
|
BOOL bRet=CTabCtrl::OnEraseBkgnd(pDC);
|
|
CRect crtClient;
|
CRect crtItem;
|
GetItemRect(0,crtItem);
|
GetClientRect(crtClient);
|
crtClient.top+=crtItem.Height();
|
pDC->FillSolidRect(crtClient, m_crBKColor);
|
|
return bRet;
|
}
|