Click here to Skip to main content
15,883,734 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 278.3K   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 "CeWnd.h"
#include "CeDialog.h"
#include "CeMisc.h"
#include "CeString.h"

#ifdef IDC_STATIC
#undef IDC_STATIC
#endif
#define IDC_STATIC		(65535)		// all static controls

CeSet<HWND, HWND> CeDialog::m_setModeless;

///////////////////////////////////////////////////////////////////////////////
//
// CeDialog - Dialog implementation class
//
///////////////////////////////////////////////////////////////////////////////

bool CeDialog::IsDialogMsg(MSG* pMsg)
{
	HWND hWnd;
	for (POSITION pos = m_setModeless.GetStartPosition(); NULL != pos; )
	{
		m_setModeless.GetNextAssoc(pos, hWnd);

		if (::IsDialogMessage(hWnd, pMsg))
			return true;
	}

	return false;
}

/*static*/
BOOL CALLBACK CeDialog::DlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	CeDialog* pDlg = (CeDialog*) ::GetWindowLong(hDlg, DWL_USER);

//	TRACE(_T("pDlg = %x, hDlg = %x, uMsg = 0x%x, wParam = %x, lParam = %x\n"), pDlg, hDlg, uMsg, wParam, lParam);

	if (NULL == pDlg)
	{
		if (WM_INITDIALOG == uMsg)
		{
			pDlg = (CeDialog*) lParam;
			CHW_ASSERT(ISVALIDPTR(pDlg, sizeof *pDlg));

			::SetWindowLong(hDlg, DWL_USER, (LONG) pDlg);
			pDlg->OnFirstMessage(hDlg);
			pDlg->m_hWnd = hDlg;
		}
		else
		{
			//
			// we don't know ANYTHING about this window
			// this normally happens for the WM_SETFONT and 0x210 messages
			//
			//TRACE0("WARNING: Received dialog message from UNKNOWN WINDOW\n");
			return FALSE;
		}
	}
	else
	{
		CHW_ASSERT(ISVALIDPTR(pDlg, sizeof *pDlg));
		CHW_ASSERT(pDlg->m_hWnd == hDlg);
	}

	// keep message for default call
	pDlg->m_cemsg.hwnd = hDlg;
	pDlg->m_cemsg.uMsg = uMsg;
	pDlg->m_cemsg.wParam = wParam;
	pDlg->m_cemsg.lParam = lParam;

	bool bHandled = false;		// not handled by default

//	LRESULT lResult = 0;

	// encapsulate external calls in exception handlers, CE doesn't do a 
	// good job of showing exception conditions in the UI
	__try
	{
		//
		// dialog procs differ from windows procs in the result value
		// returned, save the result of the message handling and set that value
		// as the DWL_MSGRESULT, return wether it was handled or not
		// winprocs just return the value instead
		//
		LRESULT lResult = pDlg->ProcessMessage(uMsg, wParam, lParam, bHandled);

		if (bHandled)
		{
			//
			// for these messages just return, no need to set the DWL_MSGRESULT
			//
			switch (uMsg)
			{
			case WM_COMPAREITEM:
			case WM_VKEYTOITEM:
			case WM_CHARTOITEM:
			case WM_INITDIALOG:
			case WM_QUERYDRAGICON:
			case WM_CTLCOLORMSGBOX:
			case WM_CTLCOLOREDIT:
			case WM_CTLCOLORLISTBOX:
			case WM_CTLCOLORBTN:
			case WM_CTLCOLORDLG:
			case WM_CTLCOLORSCROLLBAR:
			case WM_CTLCOLORSTATIC:
				return lResult;
			}

			// set this immeaditely before returning or we may get trounced by another call
			pDlg->SetWindowLong(DWL_MSGRESULT, lResult);
		}
		else
		{
			//pDlg->Default();
			//bHandled = true;
		}

		if (_LAST_WM_MESSAGE == uMsg)
		{
			// we received the LAST message we're going to to get
			// unsubclass the window
			if (NULL != pDlg->m_lpfnOldWndProc)
				::SetWindowLong(pDlg->m_hWnd, DWL_DLGPROC, (LONG) pDlg->m_lpfnOldWndProc);

			// reset the user data (this pointer)
			::SetWindowLong(pDlg->m_hWnd, DWL_USER, 0);

			// clear out window handle
			pDlg->m_hWnd = NULL;

			// allow derived classes to clean up after window is destroyed
			pDlg->OnFinalMessage(hDlg);
		}
	}
    __except (EXCEPTION_EXECUTE_HANDLER)
	{
		::MessageBox(NULL,
			_T("Window message termainated abnormally by an exception"),
			_T("Fatal"), MB_OK | MB_ICONSTOP);
	}

	// good-bye
	return bHandled;
}


CeDialog::CeDialog(LPCTSTR lpTemplateName)
{
	m_lpTemplateName = lpTemplateName;
	m_bModal = false;
}


CeDialog::CeDialog(UINT nDlgID)
{
	m_lpTemplateName = MAKEINTRESOURCE(nDlgID);
	m_bModal = false;
}

CeDialog::~CeDialog()
{
	if (! m_bModal)
		m_setModeless.RemoveKey(m_hWnd);
}


BOOL CeDialog::Create(LPCTSTR lpTemplateName, HWND hWndParent, HINSTANCE hInst)
{
	CHW_ASSERT(NULL == m_hWnd);			// don't create twice
	CHW_ASSERT(hWndParent != NULL);		// need a parent/owner for modeless/child dialogs

	m_bModal = false;

	if (NULL == lpTemplateName)
		lpTemplateName = m_lpTemplateName;

	if (hInst == NULL)
		// use the applications instance if the user didn't specify
		hInst = CeGetAppInstance();

	CHW_ASSERT(NULL != hInst);
	CHW_ASSERT(NULL != lpTemplateName);

	HWND hDlg = ::CreateDialogParam(hInst,
		lpTemplateName,
		hWndParent,
		(DLGPROCCAST) DlgProc,
		(LPARAM) this);

	m_setModeless.AddKey(m_hWnd);
	return (hDlg != NULL && hDlg == m_hWnd);
}

int CeDialog::DoModal(LPCTSTR lpTemplateName, HWND hWndParent, HINSTANCE hInst)
{
	CHW_ASSERT(NULL == m_hWnd);

	m_bModal = true;

	if (NULL == lpTemplateName)
		lpTemplateName = m_lpTemplateName;

	if (hInst == NULL)
		// use the applications instance if the user didn't specify
		hInst = CeGetAppInstance();

	if (hWndParent == NULL)
		// use the main/app window if not specified
		hWndParent = CeGetAppWindow();
	else if (::GetWindowLong(hWndParent, GWL_STYLE) & WS_CHILD)
		hWndParent = GetTopLevelWindow();

	CHW_ASSERT(NULL != hInst);
	CHW_ASSERT(NULL != lpTemplateName);
	CHW_ASSERT(NULL != hWndParent);

	return ::DialogBoxParam(hInst,
		lpTemplateName,
		hWndParent,
		(DLGPROCCAST) DlgProc,
		(LPARAM) this);
}


///////////////////////////////////////////////////////////////////////////////
//
// Default - Calls either the default window procedure or the
//           subclassed window procedure for the active message
//
///////////////////////////////////////////////////////////////////////////////
LRESULT CeDialog::Default()
{
	if (m_lpfnOldWndProc)
	{
		// we subclassed somebody elses dialog proc
#ifdef STRICT
		return ::CallWindowProc((WNDPROC) m_lpfnOldWndProc, m_cemsg.hwnd,
			m_cemsg.uMsg, m_cemsg.wParam, m_cemsg.lParam);
#else
		return ::CallWindowProc((FARPROC) m_lpfnOldWndProc, m_cemsg.hwnd,
			m_cemsg.uMsg, m_cemsg.wParam, m_cemsg.lParam);
#endif
	}
	else
		return FALSE;
}

///////////////////////////////////////////////////////////////////////////////
//
// CeDialog::ProcessMessage - 
//
///////////////////////////////////////////////////////////////////////////////
LRESULT CeDialog::ProcessMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
	LRESULT lRet = 0;

	switch (uMsg)
	{
	case WM_INITDIALOG:
		bHandled = true;
		return OnInitDialog();
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
			// In Windows CE (starting with 3.0) you no longer
			// get a BN_CLICKED, instead you get the control ID
			// and a 0x1000 

			case IDCANCEL:
				//if (HIWORD(wParam) == BN_CLICKED)
				OnCancel();
				bHandled = true;
				break;

			case IDOK:
				//if (HIWORD(wParam) == BN_CLICKED)
				OnOK();
				bHandled = true;
				break;

			case IDC_STATIC:
				if (HIWORD(wParam) == STN_CLICKED)
				{
					HWND hStatic = (HWND) lParam;
					HWND hNext = ::GetWindow(hStatic, GW_HWNDNEXT);

					CeString str(hStatic), strNext(hNext);
					TRACE(_T("%s / %s\n"), (LPCTSTR) str, (LPCTSTR) strNext);

					if (hNext != NULL)
						SendMessage(WM_NEXTDLGCTL, (WPARAM) hNext, MAKELPARAM(TRUE, 0)); 
				}
				bHandled = true;
				break;

			default:
				lRet = OnCommand(wParam, lParam, bHandled);
		}
		return FALSE;

	default:
		lRet = CeMsgWnd::ProcessMessage(uMsg, wParam, lParam, bHandled);
		break;
	}

	return lRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// Dialog message virtual functions
//
///////////////////////////////////////////////////////////////////////////////

// special message, handled by default
BOOL CeDialog::OnInitDialog()
{
	if (m_bModal)
		CenterWindow();

	return TRUE;
}

void CeDialog::OnCancel()
{
	if (m_bModal)
		EndDialog(IDCANCEL);

	TRACE0("CeDialog: OnCancel()\n");
}

void CeDialog::OnOK()
{
	if (m_bModal)
		EndDialog(IDOK);

	TRACE0("CeDialog: OnOK()\n");
}


///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////
BOOL CeScrollDialog::OnInitDialog() 
{
	CeDialog::OnInitDialog();
	
	CeRect rect;
	GetClientRect(&rect);
	m_cxOrig = rect.Width();
	m_cyOrig = rect.Height();
	
	m_bVertSBVisible = FALSE;
	m_bHorzSBVisible = FALSE;
	
	m_bInit = TRUE;
	
	// adjust window size, if desired by caller
	if (0 != m_nWidth || 0 != m_nHeight)
	{
		CeRect rect;
		int nSBVWidth = ::GetSystemMetrics(SM_CXVSCROLL);
		int nSBHHeight = ::GetSystemMetrics(SM_CYHSCROLL);
		
		GetWindowRect(&rect);
		
		int nWidth  = (0 == m_nWidth ? rect.Width() + nSBVWidth : m_nWidth);
		int nHeight = (0 == m_nHeight ? rect.Height() + nSBHHeight : m_nHeight);
		
		MoveWindow(rect.TopLeft().x, rect.TopLeft().y, nWidth, nHeight);
	}
	
	return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////
LRESULT CeScrollDialog::OnMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled)
{
	switch (uMsg)
	{
	case WM_VSCROLL:
		bHandled = true;
		OnVScroll((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND) lParam);
		break;

	case WM_HSCROLL:
		bHandled = true;
		OnHScroll((int)LOWORD(wParam), (short)HIWORD(wParam), (HWND) lParam);
		break;
	}

	return 0;
}


int CeScrollDialog::SetScrollInfo(int fnBar, int nMin, int nMax, int nPage)
{
	SCROLLINFO scrollinfo;
	
	scrollinfo.cbSize = sizeof(scrollinfo);
	scrollinfo.fMask = SIF_PAGE | SIF_RANGE;
	scrollinfo.nMin = nMin;
	scrollinfo.nMax = nMax;
	scrollinfo.nPage = nPage; 
	
	return CeDialog::SetScrollInfo(fnBar, &scrollinfo);
}


///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////
void CeScrollDialog::OnSize(UINT nType, int cx, int cy, bool& bHandled) 
{
	CeDialog::OnSize(nType, cx, cy, bHandled);

	if (! m_bInit || SIZE_RESTORED != nType)
		return;

	bHandled = true;
	
	if (cy < m_cyOrig)
	{
		// make scrollbar visible, if necessary
		m_bVertSBVisible = TRUE;
		
		int nPos = GetScrollPos(SB_VERT);
		
		// check for need to scroll window
		if (nPos + cy > m_cyOrig)
		{
			ScrollWindowEx(0, (nPos + cy) - m_cyOrig, SW_ERASE|SW_INVALIDATE|SW_SCROLLCHILDREN);
			nPos = m_cyOrig - cy;
		}

		// set the range
		SetScrollInfo(SB_VERT, 0, m_cyOrig - 1, cy);

		// adjust scroll position
		SetScrollPos(SB_VERT, nPos);
	}
	else
	{
		if (m_bVertSBVisible)
		{
			// get rid of the scrollbar and move the window to the
			// appropriate position
			int nPos = GetScrollPos(SB_VERT);

			if (nPos)
				ScrollWindowEx(0, nPos, SW_ERASE|SW_INVALIDATE|SW_SCROLLCHILDREN);

			// set the range to empty
			SetScrollInfo(SB_VERT, 0, m_cyOrig - 1, cy);
		}

		m_bVertSBVisible = FALSE;
	}

	if (cx < m_cxOrig)
	{
		// make scrollbar visible, if necessary
		if (!m_bHorzSBVisible)
		{
			//ShowScrollBar(SB_HORZ, TRUE);
			m_bHorzSBVisible = TRUE;
		}
		
		int nPos = GetScrollPos(SB_HORZ);
		
		// check for need to scroll window
		if (nPos + cx > m_cxOrig)
		{
			ScrollWindowEx((nPos + cx) - m_cxOrig, 0, 
				SW_ERASE | SW_INVALIDATE | SW_SCROLLCHILDREN );
			nPos = m_cxOrig - cx;
		}
		
		// set scrollbar parameters
		SetScrollInfo(SB_HORZ, 0, m_cxOrig-1, cx);
		
		// adjust scroll position
		SetScrollPos(SB_HORZ, nPos);
	}
	else
	{
		// make scrollbar invisible, if necessary
		if (m_bHorzSBVisible)
		{
			// get rid of the scrollbar and move the window to the
			// appropriate position
			int nPos = GetScrollPos(SB_VERT);

			if (nPos)
				ScrollWindowEx(nPos, 0, SW_ERASE|SW_INVALIDATE|SW_SCROLLCHILDREN);

			// set scrollbar parameters - empty hides them
			SetScrollInfo(SB_HORZ, 0, m_cxOrig-1, cx);

			m_bHorzSBVisible = FALSE;
		}
	}
}


// scroll amount that corresponds to a "line"
static const int LINE_AMOUNT=20;

///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////
void CeScrollDialog::OnHScroll(UINT nSBCode, UINT nPos, HWND hScroll) 
{
	UNUSED_ALWAYS(hScroll);

	if (! m_bHorzSBVisible)
		// nothing; no scrollbar
		return;

	int nMin, nMax, nNew, nOrig = GetScrollPos(SB_HORZ);
	
	CeRect rect;
	GetClientRect(&rect);
	GetScrollRange(SB_HORZ, &nMin, &nMax);
	
	switch (nSBCode)
	{
	case SB_BOTTOM:			nNew = nMax;					break;
	case SB_LINERIGHT:		nNew = nOrig + LINE_AMOUNT;		break;
	case SB_LINELEFT:		nNew = nOrig - LINE_AMOUNT;		break;
	case SB_PAGEDOWN:		nNew = nOrig + rect.Width();	break;
	case SB_PAGEUP:			nNew = nOrig - rect.Width();	break;
	case SB_TOP:			nNew = 0;						break;

	//�Drag scroll box to specified position.
	// The current position is provided in nPos.
	case SB_THUMBTRACK:		nNew = nPos;					break;
		
	default:
		nNew = nOrig;
		break;
	}
	
	if (nNew < 0)
		nNew = 0;
	else
	{
		int nLimit = nMax - rect.Width() + 1;
		if (nNew > nLimit)
			nNew = nLimit;
	}

	TRACE(_T("H: New: %d Orig: %d Min: %d Max: %d\n"),
		nNew, nOrig, nMin, nMax);

	if (nNew != nOrig)
	{
		ScrollWindowEx(nOrig-nNew, 0, SW_ERASE|SW_INVALIDATE|SW_SCROLLCHILDREN);
		SetScrollPos(SB_HORZ, nNew);
	}
}


///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////
void CeScrollDialog::OnVScroll(UINT nSBCode, UINT nPos, HWND hScroll) 
{
	if (! m_bVertSBVisible)
		// nothing; no scrollbar
		return;

	int nMin, nMax, nNew, nOrig = GetScrollPos(SB_VERT);
	
	CeRect rect;
	GetClientRect(&rect);
	GetScrollRange(SB_VERT, &nMin, &nMax);
	
	switch (nSBCode)
	{
	case SB_BOTTOM: 	nNew = nMax;					break;
	case SB_LINEDOWN:	nNew = nOrig + LINE_AMOUNT;		break;
	case SB_LINEUP:		nNew = nOrig - LINE_AMOUNT;		break;
	case SB_PAGEDOWN:	nNew = nOrig + rect.Height();	break;
	case SB_PAGEUP:		nNew = nOrig - rect.Height();	break;
	case SB_TOP:		nNew = 0;						break;

	//�Drag scroll box to specified position.
	// The current position is provided in nPos.
	case SB_THUMBTRACK:	nNew = nPos;					break;

	default:
		nNew = nOrig;
		break;
	}


	if (nNew < 0)
		nNew = 0;
	else 
	{
		int nLimit = nMax - rect.Height() + 1;
		if (nNew > nLimit)
			nNew = nLimit;
	}

	TRACE(_T("V: New: %d Orig: %d Min: %d Max: %d\n"),
		nNew, nOrig, nMin, nMax);
	
	if (nNew != nOrig)
	{
		ScrollWindowEx(0, nOrig - nNew, SW_ERASE|SW_INVALIDATE|SW_SCROLLCHILDREN);
		SetScrollPos(SB_VERT, nNew);
	}
}

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