Click here to Skip to main content
15,893,814 members
Articles / Web Development / HTML

A Comprehensive CE Class Library to Replace ATL and MFC

Rate me:
Please Sign up or sign in to vote.
4.48/5 (14 votes)
4 Oct 2000CPOL 281.8K   998   70  
A collection of classes for CE that do not use ATL or MFC, plus an FTP client, database viewer, and sample application that solves beam deflection equations.
#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, HINSTANCE hInst)
{
	return CeWnd::Create(WC_TABCONTROL, hWndParent, rect, NULL, dwStyle, 0, nID, hInst);
}

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_dwTabStyle = 0;
	m_hInst = NULL;
    m_nActivePage = -1;
}


CeTabSheet::Create(DWORD dwStyle, const RECT& rect, HWND hWndParent, UINT nID, HINSTANCE hInst)
{
	m_hInst = hInst;

	// mask off the styles we never use, save them for the tab control create
	// however...

	m_dwTabStyle = dwStyle & 0xffff;

	dwStyle &= 0xffff0000;
	return CeWnd::Create(NULL, hWndParent, rect, NULL, dwStyle, 0, nID, hInst);
}


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);

	if (m_hWnd == NULL)
		// adding before creation, will be added at create time
		return;

    int nItem;		// page's item number

	if (! (m_dwTabStyle & TCS_VERTICAL))
	{
	    // add the item to the end of the tab
	    if ( ! (nItem = m_tabCtrl.InsertItem( m_tabCtrl.GetItemCount(), pPage->GetTabTitle(), nBitmap)) )
	    {
			// show it and set whatever internal info we need
			SetActivePage(nItem);
	    }
	}
	else
	{
	    // add the item to the end of the tab
	    if ( ! (nItem = m_tabCtrl.InsertItem( m_tabCtrl.GetItemCount(), _T(""), nBitmap)) )
	    {
			// show it and set whatever internal info we need
			SetActivePage(nItem);
	    }
	}
}

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;

    CeTabPage* pActive = GetPage(m_nActivePage);
	if (pActive)
	{
		if(! pActive->OnKillActive())
			// can't go there...
			return FALSE;

		// call as documented for MFC
		pActive->OnOK();
	}

	CeTabPage* pPage = GetPage(nPage);
    CeRect rectWnd;

    // calc the area available for children
    GetPageRect(rectWnd);

	// not created yet? do that
    if (! ::IsWindow(pPage->m_hWnd))
    {
        // first display do create
        if (! pPage->Create(pPage->GetID(), m_hWnd, m_hInst))
			return FALSE;
	}
    
	// don't bother with the return value...
	if (! pPage->OnSetActive())
		return FALSE;

	// set position before tab, tab will now be after
	// all pages, the z-order of the pages doesn't matter since
	// they are always hidden when not active
    pPage->SetWindowPos(HWND_TOP, 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();
    
    m_nActivePage = nPage;
    
    // don't set focus to tab control
	// SetFocus();

    return TRUE;
}

void CeTabSheet::RemovePage(CeTabPage *pPage)
{
    int nPage = FindPage(pPage);
    RemovePage(nPage);
}

void CeTabSheet::RemovePage(int nPage)
{
	if (m_arPages.GetCount() <= nPage)
		// non-existant page
		return;

	// hide the window and disable it if it has been created
	// otherwise it will get in the way, the caller 
	// can close it if necessary, otherwise it will be reused
	// if added back in without creation
	CeTabPage* pPage = m_arPages[nPage];
	if (pPage->IsWindow())
	{
		pPage->ShowWindow(SW_HIDE);
		pPage->EnableWindow(FALSE);
	}

	// remove the page from array
    m_arPages.Remove(nPage);

	// remove the tab from control
    m_tabCtrl.DeleteItem(nPage);
    
    // fix up current page if neccessary
    if (nPage == m_nActivePage)
        if (m_arPages.GetSize() > 0)
        SetActivePage(0);
    else
        m_nActivePage = -1;
}


void CeTabSheet::Apply()
{
    for (int ii = 0; ii < m_arPages.GetSize(); ii++)
	{
		if ((NULL != m_arPages[ii]) && (NULL != m_arPages[ii]->m_hWnd))
		{
			m_arPages[ii]->OnApply();
		}
	}
}


void CeTabSheet::Reset()
{
    for (int ii = 0; ii < m_arPages.GetSize(); ii++)
	{
		if ((NULL != m_arPages[ii]) && (NULL != m_arPages[ii]->m_hWnd))
		{
			m_arPages[ii]->OnReset();
		}
	}
}


LRESULT CeTabSheet::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
	switch (uMsg)
	{
	case WM_SETFONT:
		bHandled = true;
		if (m_tabCtrl.m_hWnd)
			m_tabCtrl.SetFont((HFONT) wParam, LOWORD(lParam));
		break;
	}

	return 0;
}


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)
{
//
// Style note: right and bottom are the same, verticle changes it, bottom
//			   doesn't work in the emulator though
//		TCS_RIGHT |
//		TCS_BOTTOM |
//		TCS_VERTICAL |
//
	if (m_dwTabStyle == 0)
		m_dwTabStyle = TCS_TABS | TCS_SINGLELINE | TCS_RAGGEDRIGHT | TCS_FOCUSNEVER;

	m_dwTabStyle |= (WS_VISIBLE | WS_CHILD);

	CeRect rc(lpCS->x, lpCS->y, lpCS->x + lpCS->cx, lpCS->y + lpCS->cy);

    if (! m_tabCtrl.Create(m_dwTabStyle, rc, m_hWnd, 1000, m_hInst))
        return -1;

	// check for delayed creat and do so here
	if (m_arPages.GetSize() > 0)
	{
		int nItem;		// page's item number


		for (int ii = 0; ii < m_arPages.GetSize(); ii++)
		{
			if (! (m_dwTabStyle & TCS_VERTICAL))
			{
				// add the item to the end of the tab
				if ( ! (nItem = m_tabCtrl.InsertItem( m_tabCtrl.GetItemCount(), m_arPages[ii]->GetTabTitle())) )
				{
					// show it and set whatever internal info we need
					SetActivePage(nItem);
				}
			}
			else
			{
				// add the item to the end of the tab
				if ( ! (nItem = m_tabCtrl.InsertItem( m_tabCtrl.GetItemCount(), _T(""))) )
				{
					// show it and set whatever internal info we need
					SetActivePage(nItem);
				}
			}
		}
	}

    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);
        
        // 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);
	m_tabCtrl.SetWindowPos(NULL, rcClient, SWP_NOACTIVATE|SWP_NOZORDER);
    if (m_tabCtrl.GetItemCount() <= 0)
        return;
    
    // Size the active page to fit within borders
    CeRect rectWnd;
    GetPageRect(rectWnd);

    // Note: want to keep Z-order, move and resize....
	CeTabPage* pActive = GetActivePage();
	if (pActive)
	{
		pActive->SetWindowPos(NULL, rectWnd, SWP_NOACTIVATE|SWP_NOZORDER);
		pActive->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);

        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)
{
	m_tabCtrl.GetClientRect(lpRect);
	m_tabCtrl.AdjustRect(FALSE, lpRect);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions