#include "stdafx.h"
#include "CeTab.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CeTabCtrl
CeTabCtrl::~CeTabCtrl()
{
}
BOOL CeTabCtrl::Create(DWORD dwStyle, const RECT& rect, HWND hWndParent, UINT nID)
{
return CeWnd::Create(NULL, WC_TABCONTROL, hWndParent, rect, NULL,
dwStyle, 0, nID);
}
BOOL CeTabCtrl::InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem,
int nImage, LPARAM lParam, DWORD dwState,
DWORD dwStateMask)
{
TCITEM item;
item.mask = nMask;
item.dwState = dwState;
item.dwStateMask = dwStateMask;
item.pszText = (LPTSTR) lpszItem;
item.cchTextMax = lstrlen(lpszItem);
item.iImage = nImage;
item.lParam = lParam;
return InsertItem(nItem, &item);
}
BOOL CeTabCtrl::InsertItem(UINT nMask, int nItem, LPCTSTR lpszItem,
int nImage, LPARAM lParam)
{
return InsertItem(nMask, nItem, lpszItem, nImage, lParam, 0, 0);
}
/////////////////////////////////////////////////////////////////////////////
// CeTabSheet
CeTabSheet::CeTabSheet()
{
m_nActivePage = -1;
}
CeTabSheet::~CeTabSheet()
{
}
/////////////////////////////////////////////////////////////////////////////
// CeTabSheet message handlers
void CeTabSheet::AddPage(CeTabPage* pPage, int nBitmap /*=-1*/)
{
ASSERT(pPage != NULL);
// ASSERT(pPage->GetID() != 0); // did you forget to overload this
m_arPages.Add(&pPage);
// add the item to the end of the tab
int nItem; // page's item number
if ( ! (nItem = m_tabCtrl.InsertItem( m_tabCtrl.GetItemCount(), pPage->GetTabTitle(), nBitmap)) )
{
// first tab create
pPage->Create(pPage->GetID(), m_hWnd);
SetActivePage(nItem);
CeRect rectWnd;
GetPageRect(rectWnd);
// convert to client coords
ScreenToClient(rectWnd);
// tab goes before ALL pages
pPage->SetWindowPos(m_hWnd, rectWnd.left, rectWnd.top,
rectWnd.Width(), rectWnd.Height(), SWP_NOACTIVATE);
// if (GetStyle() & (KTCS_RIGHT|KTCS_BOTTOM))
// {
// // tab goes AFTER all pages, move it back
// SetWindowPos(GetPage(nItem), 0, 0, 0, 0,
// SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE);
// }
}
}
int CeTabSheet::FindPage(CeTabPage *pPage) const
{
for (int ii = 0; ii < m_arPages.GetSize(); ii++)
if (m_arPages[ii] == pPage)
return ii;
return -1;
}
BOOL CeTabSheet::SetActivePage(CeTabPage* pPage)
{
ASSERT(pPage != NULL);
int nPage = FindPage(pPage);
return (nPage < 0) ? FALSE: SetActivePage(nPage);
}
BOOL CeTabSheet::SetActivePage(int nPage)
{
if (nPage == m_nActivePage)
return TRUE;
ASSERT(GetStyle() & WS_CHILD);
HWND hParent = GetParent();
CeTabPage* pPage = GetPage(nPage);
CeRect rectWnd;
// calc the area available for children
GetPageRect(rectWnd);
// convert to client coords
ScreenToClient(rectWnd);
if (! ::IsWindow(pPage->m_hWnd))
{
// first display do create
pPage->Create(pPage->GetID(), m_hWnd);
CeBaseWnd* pBefore = GetPage(0);
// CeWnd* pWndBefore = (GetStyle() & (KTCS_RIGHT|KTCS_BOTTOM)) ?
// (CWnd*)GetPage(0): (CWnd*)this;
// set position before tab or after 'this'
// tab goes before ALL pages
pPage->SetWindowPos(pBefore->m_hWnd, rectWnd, SWP_NOACTIVATE);
}
// Hide the current window and then change the current window
if (m_nActivePage >= 0)
{
// for sanity
GetPage(m_nActivePage)->EnableWindow(FALSE);
GetPage(m_nActivePage)->ShowWindow(FALSE);
}
pPage->MoveWindow(rectWnd);
pPage->EnableWindow(TRUE);
pPage->ShowWindow(TRUE);
pPage->Invalidate();
// transfer data
// pPage->UpdateData(FALSE);
m_nActivePage = nPage;
// set focus to tab control
SetFocus();
return TRUE;
}
void CeTabSheet::RemovePage(CeTabPage *pPage)
{
int nPage = FindPage(pPage);
RemovePage(nPage);
}
void CeTabSheet::RemovePage(int nPage)
{
m_arPages.Remove(nPage); // remove the page from array
m_tabCtrl.DeleteItem(nPage); // remove the tab from control
// fix up current page if neccessary
if (nPage == m_nActivePage)
if (m_arPages.GetSize() > 0)
SetActivePage(m_arPages[0]);
else
m_nActivePage = -1;
}
LRESULT CeTabSheet::OnNotify(int nCtrlId, LPNMHDR pNMH, bool& bHandled)
{
if (1000 == pNMH->idFrom)
{
switch (pNMH->code)
{
case TCN_SELCHANGE:
bHandled = true;
return OnNotifyTabChanged();
case TCN_SELCHANGING:
bHandled = true;
return OnNotifyTabChanging();
}
}
return TRUE;
}
LRESULT CeTabSheet::OnNotifyTabChanged()
{
int nCurSel = m_tabCtrl.GetCurSel();
if (nCurSel != -1)
SetActivePage(nCurSel);
// OK
return 0;
}
LRESULT CeTabSheet::OnNotifyTabChanging()
{
CeTabPage *pPage = GetActivePage();
// if (pPage && ! pPage->UpdateData())
// // failed data transfer
// return 1;
return 0;
}
int CeTabSheet::OnCreate(LPCREATESTRUCT lpCS, bool& bHandled)
{
CeRect rc(lpCS->x, lpCS->y, lpCS->x + lpCS->cx, lpCS->y + lpCS->cy);
DWORD dwStyles =
WS_VISIBLE |
WS_CHILD |
TCS_TABS |
TCS_SINGLELINE |
TCS_RAGGEDRIGHT |
TCS_FOCUSNEVER;
if (! m_tabCtrl.Create(dwStyles, rc, m_hWnd, 1000))
return -1;
bHandled = false; // allow call to the default
return 0;
}
void CeTabSheet::OnPaint( bool& bHandled )
{
bHandled = false;
}
/*
BOOL CeTabSheet::OnEraseBkgnd(CDC* pDC)
{
if (GetPageCount() > 0)
{
CRect rectWnd;
// get the area available for children
GetPageRect(rectWnd);
ScreenToClient(rectWnd);
// exclude it from painting
pDC->ExcludeClipRect(rectWnd);
}
// Don't erase the children's area, we will
// be either on top or below, if below we're painted last
// and will over write, if on top then it will flash
// more than neccassary if we do it so let the
// child page erase instead
return KXTabCtrl::OnEraseBkgnd(pDC);
}
*/
void CeTabSheet::OnSize( UINT nType, int cx, int cy, bool& bHandled )
{
// Do base class adjustments
CeRect rcClient;
GetClientRect(rcClient);
m_tabCtrl.SetWindowPos(NULL, rcClient,
SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER);
if (m_tabCtrl.GetItemCount() <= 0)
return;
// Size the active page to fit within borders
CeRect rectWnd;
GetPageRect(rectWnd);
// convert to client coords
ScreenToClient(rectWnd);
// Note: want to keep Z-order, move and resize....
GetActivePage()->SetWindowPos(NULL, rectWnd,
SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER);
GetActivePage()->Invalidate();
}
/*
BOOL CeTabSheet::ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags)
{
if (m_tabCtrl.ModifyStyle(dwRemove, dwAdd, nFlags))
{
// Reposition child windows
CeRect rectWnd;
// calc the area available for children
GetPageRect(rectWnd);
// convert to client coords
ScreenToClient(rectWnd);
HWND hWndInsertAfter = m_hWnd;
for (int ii = 0; ii < m_arPages.GetSize(); ii++)
{
// Note: want to keep Z-order, move and resize....
// required to keep the tab order in line....
CeTabPage* pPage = GetPage(ii);
if (! ::IsWindow(pPage->m_hWnd))
continue;
pPage->SetWindowPos(hWndInsertAfter,
rectWnd.left, rectWnd.top, rectWnd.Width(), rectWnd.Height(),
SWP_NOACTIVATE|SWP_NOREDRAW);
pWndInsertAfter = pPage->m_hWnd;
}
// fix ordering
// if (GetStyle() & (KTCS_RIGHT|KTCS_BOTTOM))
// {
// // tab goes AFTER all pages, move it back
// SetWindowPos(pWndInsertAfter, 0, 0, 0, 0,
// SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_NOREDRAW);
// }
GetPage(m_nActivePage)->Invalidate();
return TRUE;
}
return FALSE;
}
*/
void CeTabSheet::GetPageRect(LPRECT lpRect)
{
GetClientRect(lpRect);
m_tabCtrl.AdjustRect(FALSE, lpRect);
}