Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

A comprehensive CE class library to replace ATL and MFC

, 4 Oct 2000
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.
kgwince-old.zip
WinCe
BeamEx
app.ico
BeamEx.dsp
BeamEx.dsw
BeamEx.ini
BeamEx.plg
bitmap1.bmp
bmp00001.bmp
bmp00002.bmp
calc.bmp
calc16.bmp
circ_cross.ico
cir_cross.ico
cross_4.ico
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico00005.ico
ico00008.ico
ico00009.ico
ico00010.ico
icon1.ico
icon2.ico
icon4.ico
id_downl.bmp
Install
BeamEx.inf
BeamEx.ini
BeamEx.MIPS_PPCBW.CAB
BeamEx.MIPS_PPCColor.CAB
BeamEx.SH3_PPCColor.CAB
Setup.exe
i_cross.ico
l_cross.ico
magenic.ico
mssccprj.scc
obl_corss.ico
obl_cross.ico
options.bmp
options1.bmp
ping16.bmp
rect_cross.ico
scene_5.ico
scene_6.ico
tri_cross.ico
vssver.scc
CeLib
CeLabel.inl
CeLib.aps
CeLib.dsp
CeLib.dsw
CeLib.old
CeLib.plg
CeLib.vcp
CeMisc.inl
CeProperty.inl
CeTab.inl
CeWnd.inl
mssccprj.scc
vssver.scc
WinLib.dsp
WinLib.dsw
dbView
bitmap1.bmp
bmp00001.bmp
db5.bmp
dbView.aps
DbView.dsp
dbView.dsw
dbView.old
dbView.plg
DbView.vcp
deldb.bp2
deldb5.bmp
delrec.bp2
delrecor.bmp
help16.bmp
help4.bmp
icon1.ico
icon2.ico
Install
dbView.inf
dbView.ini
Setup.exe
magenic.bmp
magenic.ico
mssccprj.scc
vssver.scc
ftpView
appicon.ico
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bmp00001.bmp
bmp00002.bmp
db5.bmp
deldb.bp2
delrec.bp2
FtpView.dsp
ftpView.dsw
FtpView.old
ftpView.plg
FtpView.vcl
FtpView.vcp
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico171.ico
ico35.ico
icon1.ico
icon2.ico
imagelis.bmp
IMAGES.bmp
Install
ftpView.inf
ftpView.ini
Setup.exe
vssver.scc
magenic.bmp
magenic.ico
mssccprj.scc
options.bmp
options1.bmp
seperato.bmp
vssver.scc
Setup
ico101.ico
Setup.aps
Setup.dsp
setup.ico
Setup.plg
WinCe.dsw
WinLib.dsw
kgwince.zip
app.ico
BeamEx.dsp
BeamEx.dsw
BeamEx.ini
BeamEx.plg
BeamEx.vcl
BeamEx.vcp
bitmap1.bmp
bmp00001.bmp
bmp00002.bmp
calc.bmp
calc16.bmp
circ_cross.ico
cir_cross.ico
cross_4.ico
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico00005.ico
ico00008.ico
ico00009.ico
ico00010.ico
icon1.ico
icon2.ico
icon4.ico
id_downl.bmp
BeamEx.inf
BeamEx.ini
Setup.exe
i_cross.ico
l_cross.ico
magenic.ico
mssccprj.scc
obl_corss.ico
obl_cross.ico
options.bmp
options1.bmp
ping16.bmp
rect_cross.ico
scene_5.ico
scene_6.ico
tri_cross.ico
vssver.scc
CeFtp.vcp
CeFtp.vcw
CeLabel.inl
CeLib.aps
CeLib.dsp
CeLib.dsw
CeLib.plg
CeLib.vcl
CeLib.vcp
CeMisc.inl
CeProperty.inl
CeTab.inl
CeWnd.inl
mssccprj.scc
vssver.scc
WinLib.dsp
WinLib.dsw
bitmap1.bmp
bitmap2.bmp
bmp00001.bmp
db5.bmp
DbView.dsp
dbView.dsw
dbView.plg
DbView.vcl
DbView.vcp
deldb.bp2
deldb5.bmp
delrec.bp2
delrecor.bmp
help16.bmp
help4.bmp
icon1.ico
icon2.ico
dbView.inf
dbView.ini
Setup.exe
magenic.bmp
magenic.ico
menu1_5.bmp
mssccprj.scc
vssver.scc
appicon.ico
bitmap1.bmp
bitmap2.bmp
bitmap3.bmp
bitmap4.bmp
bmp00001.bmp
bmp00002.bmp
db5.bmp
deldb.bp2
delrec.bp2
FtpView.dsp
ftpView.dsw
ftpView.plg
FtpView.vcl
FtpView.vcp
FtpView.vcw
help16.bmp
help4.bmp
ico00001.ico
ico00002.ico
ico171.ico
ico35.ico
icon1.ico
icon2.ico
imagelis.bmp
IMAGES.bmp
ftpView.inf
ftpView.ini
Setup.exe
vssver.scc
magenic.bmp
magenic.ico
mssccprj.scc
newmenu.bmp
options.bmp
options1.bmp
rcdata1.bin
seperato.bmp
toolbar1.bmp
vssver.scc
WinCe.dsw
WinCe.vcw
///////////////////////////////////////////////////////////////////////////////
//
//
//
///////////////////////////////////////////////////////////////////////////////


#include "StdAfx.h"
#include "CeDebug.h"
#include "CeWnd.h"
#include "CeMisc.h"

#include "CeArray.h"
#include "CeMgr.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000


CeChildMgr::CeChildInfo::CeChildInfo()
{
	m_hWndChild = NULL;
	m_nFlags = 0;
	::SetRectEmpty(&m_rcOriginal);
	m_sizeMin.cy = m_sizeMin.cy = 0;
	::SetRectEmpty(&m_rcMove);
	m_sizeAssocLabelDelta = CeSize(0,0);
	m_hWndLabel = NULL;
	::SetRectEmpty(&m_rcLabel);
	m_hWndSpinner = NULL;
	::SetRectEmpty(&m_rcSpinner);
};


CeChildMgr::CeChildMgr()
{
	m_hWnd = NULL;
	::SetRectEmpty(&m_rcOriginal);
	::SetRectEmpty(&m_rcLastParent);
}


CeChildMgr::~CeChildMgr()
{
}


BOOL CeChildMgr::Manage(HWND hChild, UINT nFlags)
{
	ASSERT( hChild );
	ASSERT( ::GetParent(hChild) );
	
	CeChildInfo cInfo;
	
	if (m_hWnd == NULL)
	{
		// Gather information about controlling window
		m_hWnd = ::GetParent(hChild);
		::GetClientRect(m_hWnd, &m_rcOriginal);
	}
	
	CeWnd wnd;
	wnd.Attach(m_hWnd);
	
	ASSERT( ::GetParent(hChild) == m_hWnd);
	
	// We store an hWnd rather than a CeWnd so that
	// you can call Register with a CeWnd object that may
	// only be temporary (and yet be attached to a persistant
	// hWnd).
	cInfo.m_hWndChild = hChild;
	
	// Store resize mode
	cInfo.m_nFlags = nFlags;
	
	// Store original size of rectangle for some resize operations.
	::GetWindowRect(cInfo.m_hWndChild, &cInfo.m_rcOriginal);
	wnd.ScreenToClient(cInfo.m_rcOriginal);
	
	// Hack, set to value from user or from non-client size
	CeRect rectClient;
	::GetClientRect(cInfo.m_hWndChild, &rectClient);
	cInfo.m_sizeMin.cx = cInfo.m_rcOriginal.Width() - rectClient.Width();
	cInfo.m_sizeMin.cy = cInfo.m_rcOriginal.Height() - rectClient.Height();
	
	// If AL_FIX_ASSOC_LABEL flag is on, then get previous sibling item
	// and store in cInfo the distance from right edge of associated label 
	// to left edge of pWnd.
	if(nFlags & (AL_FIX_LABEL|AL_FIX_LABEL_ABOVE))
	{
		HWND hWndLabel = ::GetWindow(cInfo.m_hWndChild, GW_HWNDPREV);
		
		// If this assertion fails, the window does not have a previous sibling.
		// Perhaps AL_FIX_LABEL shouldn't be used.
		ASSERT(hWndLabel);
		
		CeRect rectPrev;
		::GetWindowRect(hWndLabel, &rectPrev);
		wnd.ScreenToClient(rectPrev);

		cInfo.m_sizeAssocLabelDelta.cx = cInfo.m_rcOriginal.left - rectPrev.right;
		cInfo.m_sizeAssocLabelDelta.cy = rectPrev.top - cInfo.m_rcOriginal.top;
		
		cInfo.m_hWndLabel = hWndLabel;
	}

	if (nFlags & AL_FIX_SPINNER)
	{
		HWND hWndSpin = ::GetWindow(cInfo.m_hWndChild, GW_HWNDNEXT);

		ASSERT(hWndSpin);
	
		CeRect rectNext;
		::GetWindowRect(hWndSpin, &rectNext);
		wnd.ScreenToClient(rectNext);
		
		cInfo.m_sizeAssocSpinDelta.cx = rectNext.left - cInfo.m_rcOriginal.right;
		cInfo.m_sizeAssocSpinDelta.cy = rectNext.top - cInfo.m_rcOriginal.top;
		
		cInfo.m_hWndSpinner = hWndSpin;
	}

	// Add the CLayoutInfo object to our collection.
	m_arrayInfo.Add(&cInfo);
	
	wnd.Detach();

	// Return "handle" (really just index into array) as return
	// value.  Might use as parameter for future "modifier" functions.
	return m_arrayInfo.GetUpperBound();
}

//
// TODO:
// 1. don't move if it didn't move
// 2. try hiding all, moving all, showing all
//

void CeChildMgr::OnSize(UINT nType, int /*cx*/, int /*cy*/)
{
	int nMax = m_arrayInfo.GetSize();
	
	if (SIZE_MINIMIZED == nType || nMax <= 0)
		return;
	
	ASSERT(m_hWnd);
	CeWnd wnd;
	wnd.Attach(m_hWnd);
	
	CeRect rectParent;
	::GetClientRect(m_hWnd, &rectParent);

	// Walk all controls in collection.
	for (int ii = 0; ii < nMax; ii++)
	{
		CeChildInfo *pInfo = &(m_arrayInfo[ii]);
		
		// validate hWnd
		if (! ::IsWindow(pInfo->m_hWndChild))
		{
			ASSERT(0);
			// mark for removal instead of error condition?
			continue;
		}
		
		// get current location
		CeRect rectWnd;
		::GetWindowRect(pInfo->m_hWndChild, rectWnd);
		wnd.ScreenToClient(rectWnd);
		
		// get the new size
		CeSize sizeNew = CalcSize(pInfo, rectParent);
		
		//
		// Handle X positioning
		//
		
		if (pInfo->m_nFlags & (AL_ANCHOR_RIGHT | AL_PROP_ADJUST_HORZPOS))
		{
			// Original distance from right edge of parent to control.
			int nDistToRight = m_rcOriginal.right - pInfo->m_rcOriginal.right;
			
			if (pInfo->m_nFlags & AL_ANCHOR_RIGHT)
			{
				// Preserve distance to right edge of parent.
				rectWnd.right = rectParent.right - nDistToRight;
			}
			else // if(pInfo->dwLayoutMode & AL_PROP_ADJUST_HORZPOS)
			{
				// To find the proportionally scaled position, we calculate where the original
				// top left point would lie in scaled coordinate frame.
				// (We use top left instead of center so that controls of differing sizes
				// still move together...)
				
				CePoint ptOrigTopLeft = pInfo->m_rcOriginal.TopLeft();            
				

				CePoint ptNewTopLeft(
					(ptOrigTopLeft.x * rectParent.Width()) / m_rcOriginal.Width(),
					(ptOrigTopLeft.y * rectParent.Height()) / m_rcOriginal.Height()
					);
//					::MulDiv(ptOrigTopLeft.x, rectParent.Width(), m_rcOriginal.Width()),
//					::MulDiv(ptOrigTopLeft.y, RectHeight(rectParent), RectHeight(m_rcOriginal)) 
				
				// New right edge is the new left edge plus new width.
				rectWnd.right = ptNewTopLeft.x + sizeNew.cx;
			}
			
			// Establish left edge.
			rectWnd.left = rectWnd.right - sizeNew.cx;
		}
		else // if(pInfo->dwLayoutMode & AL_ANCHOR_LEFT)
		{
			// Simple - new right is old left plus new width.
			rectWnd.right = rectWnd.left + sizeNew.cx;
		}
		
		//
		// Handle Y positioning
		//
		
		if (pInfo->m_nFlags & (AL_ANCHOR_BOTTOM | AL_PROP_ADJUST_VERTPOS))
		{
			// Original distance from bottom of parent to bottom of control.
			int nDistToBottom = m_rcOriginal.bottom - pInfo->m_rcOriginal.bottom;
			
			if(pInfo->m_nFlags & AL_ANCHOR_BOTTOM)
			{
				// Preserve distance to bottom edge of parent.              
				rectWnd.bottom = rectParent.bottom - nDistToBottom;
			}
			else  // if(pInfo->m_nFlags & AL_PROP_ADJUST_VERTPOS)
			{
				// To find the proportionally scaled position, we calculate where the original
				// top left point would lie in scaled coordinate frame.
				// (We use top left instead of center so that controls of differing sizes
				// still move together...)
				
				CePoint ptOrigTopLeft = pInfo->m_rcOriginal.TopLeft();            
				
				CePoint ptNewTopLeft(
					(ptOrigTopLeft.x * rectParent.Width()) / m_rcOriginal.Width(),
					(ptOrigTopLeft.y * rectParent.Height()) / m_rcOriginal.Height()
					);
				
				// New bottom edge is the new top edge plus new width.
				rectWnd.bottom = ptNewTopLeft.y + sizeNew.cy;
			}
			
			// Establish top edge.
			rectWnd.top = rectWnd.bottom - sizeNew.cy;
			if (rectWnd.top > rectWnd.bottom)
				rectWnd.top = rectWnd.bottom;
		}
		else // if(pInfo->m_nFlags & AL_ANCHOR_TOP)
		{
			// Simple = new bottom is old top plus new height.
			rectWnd.bottom = rectWnd.top + sizeNew.cy;
			if (rectWnd.bottom < rectWnd.top)
				rectWnd.bottom = rectWnd.top;
		}
		
		// If AL_FIX_LABEL flag set, then adjust previous sibling (e.g. a text label)
		// to have same distance from this window as it did in the beginning...
		// (i.e. label's right edge to this window's left edge).
		if (pInfo->m_nFlags & (AL_FIX_LABEL|AL_FIX_LABEL_ABOVE))
		{
			CeRect rectAssoc;
			::GetWindowRect(pInfo->m_hWndLabel, rectAssoc);
			
			int nAssocWidth = rectAssoc.Width();
			rectAssoc.right  = rectWnd.left - pInfo->m_sizeAssocLabelDelta.cx;
			rectAssoc.left   = rectAssoc.right - nAssocWidth;
			
			int nAssocHeight = RectHeight(rectAssoc);
			rectAssoc.top    = rectWnd.top + pInfo->m_sizeAssocLabelDelta.cy;
			rectAssoc.bottom = rectAssoc.top + nAssocHeight;
			
			pInfo->m_rcLabel = rectAssoc;
		}

		// If AL_FIX_SPINNER flag set, then adjust spinner sibling
		// to have same distance from this window as it did in the beginning...
		// (i.e. spinner's left edge to this window's right edge).
		if (pInfo->m_nFlags & AL_FIX_SPINNER)
		{
			CeRect rectAssoc;
			::GetWindowRect(pInfo->m_hWndSpinner, rectAssoc);
			
			int nAssocWidth  = rectAssoc.Width();
			rectAssoc.left   = rectWnd.right + pInfo->m_sizeAssocSpinDelta.cx;
			rectAssoc.right  = rectAssoc.left + nAssocWidth;

			int nAssocHeight = RectHeight(rectAssoc);
			rectAssoc.top    = rectWnd.top + pInfo->m_sizeAssocSpinDelta.cy;
			rectAssoc.bottom = rectAssoc.top + nAssocHeight;
			
			pInfo->m_rcSpinner = rectAssoc;
		}

		
		if (RectHeight(rectWnd) < pInfo->m_sizeMin.cy &&
			rectWnd.Width()  < pInfo->m_sizeMin.cx)
		{
			// move nothing, we just can't right now
			return;
		}
		
		pInfo->m_rcMove = rectWnd;
	}

	// Preserve for next time through.
	m_rcLastParent = rectParent;

	if (! DetectCollision())
	{

#if !defined(_WIN32_WCE)
		// Preallocate the number of windows
		// it will increase if the number includes labels
		HDWP hDWP = ::BeginDeferWindowPos(nMax);

		for (ii = 0; ii < nMax; ii++)
		{
			CeChildInfo* pInfo= &(m_arrayInfo[ii]);
			
			hDWP = ::DeferWindowPos(hDWP,
				pInfo->m_hWndChild, NULL,
				pInfo->m_rcMove.left, pInfo->m_rcMove.top,
				pInfo->m_rcMove.Width(), RectHeight(pInfo->m_rcMove),
				SWP_NOZORDER);

			if (pInfo->m_nFlags & (AL_FIX_LABEL|AL_FIX_LABEL_ABOVE))
				hDWP = ::DeferWindowPos(hDWP,
					pInfo->m_hWndLabel, NULL,
					pInfo->m_rcLabel.left, pInfo->m_rcLabel.top,
					pInfo->m_rcLabel.Width(), RectHeight(pInfo->m_rcLabel),
					SWP_NOZORDER);

			if (pInfo->m_nFlags & AL_FIX_SPINNER)
				hDWP = ::DeferWindowPos(hDWP,
					pInfo->m_hWndSpinner, NULL,
					pInfo->m_rcSpinner.left, pInfo->m_rcSpinner.top,
					pInfo->m_rcSpinner.Width(), RectHeight(pInfo->m_rcSpinner),
					SWP_NOZORDER);
		}

		::EndDeferWindowPos(hDWP);

#else  // _WIN32_WCE

		// No violated contraints on positioning
		// move all the windows to their new places
		
		for (ii = 0; ii < nMax; ii++)
		{
			CeChildInfo* pInfo= &(m_arrayInfo[ii]);
			
			::MoveWindow(pInfo->m_hWndChild,
				pInfo->m_rcMove.left, pInfo->m_rcMove.top,
				pInfo->m_rcMove.Width(), RectHeight(pInfo->m_rcMove),
				TRUE);
			
			if (pInfo->m_nFlags & (AL_FIX_LABEL|AL_FIX_LABEL_ABOVE))
				::MoveWindow(pInfo->m_hWndLabel,
				pInfo->m_rcLabel.left, pInfo->m_rcLabel.top,
				pInfo->m_rcLabel.Width(), RectHeight(pInfo->m_rcLabel),
				TRUE);

			if (pInfo->m_nFlags & AL_FIX_SPINNER)
				::MoveWindow(pInfo->m_hWndSpinner,
				pInfo->m_rcSpinner.left, pInfo->m_rcSpinner.top,
				pInfo->m_rcSpinner.Width(), RectHeight(pInfo->m_rcSpinner),
				TRUE);
		}

		// Another pass for those controls that don't handle
		// being on top of one another for any amount of time
		for (ii = 0; ii < nMax; ii++)
		{
			CeChildInfo* pInfo= &(m_arrayInfo[ii]);

			::InvalidateRect(pInfo->m_hWndChild, NULL, TRUE);
			if (pInfo->m_nFlags & AL_FIX_LABEL)
				::InvalidateRect(pInfo->m_hWndLabel, NULL, TRUE);
			if (pInfo->m_nFlags & AL_FIX_SPINNER)
				::InvalidateRect(pInfo->m_hWndSpinner, NULL, TRUE);
		}
#endif
	}

	wnd.Detach();
}


SIZE CeChildMgr::CalcSize(CeChildInfo *pInfo, CeRect &rcParent)
{
	// Default to no change
	SIZE sizeRet;
	
	sizeRet.cx = pInfo->m_rcOriginal.Width();
	sizeRet.cy = pInfo->m_rcOriginal.Height();
	
	if (pInfo->m_nFlags & AL_ADJUST_WIDTH)
	{
		// Adjust width by same as parent has changed
		sizeRet.cx += rcParent.Width() - m_rcOriginal.Width();
	}
	else if (pInfo->m_nFlags & AL_PROP_ADJUST_WIDTH)
	{
		// Adjust width proportionally to parent change.
		// (orig wnd width/orig parent width)*(new parent width) = new wnd width
		// new left = new right - new wnd width.
		sizeRet.cx = (pInfo->m_rcOriginal.Width() * rcParent.Width()) / m_rcOriginal.Width();
	}
	
	if (pInfo->m_nFlags & AL_ADJUST_HEIGHT)
	{
		// Adjust height by same as parent change.
		sizeRet.cy += rcParent.Height() - m_rcOriginal.Height();
	}
	else if (pInfo->m_nFlags & AL_PROP_ADJUST_HEIGHT)
	{
		// Adjust height proportionally to parent change.
		// (orig wnd height/orig parent height)*(new parent height) = new wnd height
		// new top = new bottom - new wnd height.
		sizeRet.cy = (pInfo->m_rcOriginal.Height() * rcParent.Height()) / m_rcOriginal.Height();
	}
	
	return sizeRet;
}

/*
void CeChildMgr::MsgBoxCurrentSize(CeWnd *pWnd)
{
	CeRect rect;
	pWnd->GetWindowRect(rect);
	
	long baseunits = ::GetDialogBaseUnits();
	int baseunitX  = LOWORD(baseunits);
	int baseunitY  = HIWORD(baseunits);
	
	int dialogunitX = (rect.Width() * 4) / baseunitX;  
	int dialogunitY = (rect.Height() * 8) / baseunitY; 
	
	CString str;
	str.Format("Pixel Width: %d\n" 
		"Pixel Height: %d\n"
		"Dialog Unit Width: %d\n"
		"Dialog Unit Height: %d",
		rect.Width(), rect.Height(), dialogunitX, dialogunitY);
	
	pWnd->MessageBox(str, NULL, MB_ICONINFORMATION);
}
*/

// Call this when handling WM_GETMINMAXINFO, for example:
// lpMMI->ptMinTrackSize = CAutoLayout::SizeDialogToScreen(250,210);
POINT CeChildMgr::SizeDialogToScreen(int nDialogX, int nDialogY)
{
	POINT ptRet;
	
	long baseunits = ::GetDialogBaseUnits();
	int  baseunitX = LOWORD(baseunits);
	int  baseunitY = HIWORD(baseunits);
	
	ptRet.x = (nDialogX * baseunitX) / 4;  
	ptRet.y = (nDialogY * baseunitY) / 8; 
	
	return ptRet;
}


// This works...but there is not much that you can do with it.
BOOL CeChildMgr::DetectCollision()
{
	int nMax = m_arrayInfo.GetSize();
	BOOL bCollide = FALSE;
	
	for (int ii = 0; ii < nMax && ! bCollide; ii++)
	{
		// check to see if we would go too small
		CeSize size = m_arrayInfo[ii].m_rcMove.Size();
		if (size.cx < m_arrayInfo[ii].m_sizeMin.cx ||
			size.cy < m_arrayInfo[ii].m_sizeMin.cy)
			return TRUE;
		
		for (int jj = 0; jj < nMax; jj++)
		{
			if (jj == ii)
				continue;
			
			CeRect rectIntersect;
			
			// check for collision of controls, but only 
			// if one is not contained within another
			if (rectIntersect.IntersectRect(m_arrayInfo[ii].m_rcMove, m_arrayInfo[jj].m_rcMove) && 
				rectIntersect != m_arrayInfo[ii].m_rcMove && 
				rectIntersect != m_arrayInfo[jj].m_rcMove)
				return TRUE;
		}
	}
	
	return FALSE;
}


// Offset ALL child controls by size, this function
// works for all children, not just the managed ones
void CeChildMgr::OffsetChildren(HWND hWnd, CeSize size)
{
	CeRect rcChild;

	for (HWND hChild = ::GetWindow(hWnd, GW_CHILD); hChild; hChild = ::GetNextSibling(hChild))
	{
		::GetWindowRect(hChild, &rcChild);    // screen coordinates

		//::ScreenToClient(hWnd, &rcChild);    // to parent coordinates
		::ScreenToClient(hWnd, (LPPOINT)&rcChild);
		::ScreenToClient(hWnd, ((LPPOINT)&rcChild)+1);

		size = ::OffsetRect(rcChild, size.cx, size.cy);
		::MoveWindow(hChild, rcChild.left, rcChild.top, rcChild.Width(), rcChild.Height(), TRUE);
	}
}


void CeChildMgr::ValidateChildBkgnd(HDC hDC, HWND hWnd)
{
	HRGN rgn;
	CeRect rcClip;
	TCHAR szClass[64];

	// Because of bugs in the Windows GDI in ExcludeClipRect() specifically
	// that cause the clipping box to be truncated to the size of
	// the physical device coordinates, we need to build the update region
	// by hand, we do this by creating an update region from the clipping rectangle
	// set in the DC as passed to me (which we assume us accurate at this point, which it should be
	// if somebody didn't call ExcludeClipRect() on it.
	// Then I difference out the child controls from the update region, this appears to work properly
	// in all circumstances.

	GetClipBox(hDC, rcClip);
	rgn = CreateRectRgnIndirect(rcClip);
	//SelectClipRgn(hDC, &rgn, RGN_COPY);
	SelectClipRgn(hDC, rgn);

	// Iterate through all the children and exclude them from the
	// DCs clipping rectangle
	for (HWND hChild = ::GetWindow(hWnd, GW_CHILD); hChild; hChild = ::GetNextSibling(hChild))
	{
		// skip windows that aren't visible
		if (! IsWindowVisible(hChild))
			continue;

		// Doesn't mean anything, could be that the child is disabled from input
		// but contains meaningful data
		//ASSERT(pChild->IsWindowEnabled());

		::GetClassName(hChild, szClass, 64);
		
		// skip group boxes, they rely on being hollow
		// and on the parent painting it's background
		// also
		if (_tcsicmp(szClass, _T("BUTTON")) || (GetWindowStyle(hChild) & 0xF) != BS_GROUPBOX)
		{
			CeRect rcChild;
			::GetWindowRect(hChild, &rcChild);    // screen coordinates

			//::ScreenToClient(hWnd, &rcChild);    // to parent coordinates
			::ScreenToClient(hWnd, (LPPOINT)&rcChild);
			::ScreenToClient(hWnd, ((LPPOINT)&rcChild)+1);
			
			// the old way, before I was required to use regions
			//pDC->ExcludeClipRect(rectChild);

			// exclude it from painting
			SetRectRgn(rgn, rcChild.left, rcChild.top, rcChild.right, rcChild.bottom);
			//SelectClipRgn(&hDC, rgn, RGN_DIFF);
			SelectClipRgn(hDC, rgn);
		}
	}
}



// Adjusts the parent rectangle, useful for things like
// adding dialog bars to the parents client area
// and then adjust the controls with fixed distances
// to the parents borders
void CeChildMgr::AdjustArea(const SIZE& sizeDelta, BOOL bTopLeft)
{
	int nMax = m_arrayInfo.GetSize();
	if (nMax <= 0)
		// nothing managed
		return;
	
	// expand or shrink client area managed
	m_rcOriginal.right += sizeDelta.cx;
	m_rcOriginal.bottom += sizeDelta.cy;
	
	if (!bTopLeft)
		return;
	
	// Walk all controls in collection.
	for (int ii = 0; ii < nMax; ii++)
	{
		CeChildInfo *pInfo = &(m_arrayInfo[ii]);
		if (pInfo->m_hWndChild)
			pInfo->m_rcOriginal.OffsetRect(sizeDelta);
		if (pInfo->m_hWndLabel)
			pInfo->m_rcLabel.OffsetRect(sizeDelta);
		if (pInfo->m_hWndSpinner)
			pInfo->m_rcSpinner.OffsetRect(sizeDelta);
	}
}

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)

About the Author

Kenny G

United States United States
No Biography provided

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 5 Oct 2000
Article Copyright 2000 by Kenny G
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid