Przepraszam, ale wprowadziłem cię w błąd z rozpędu. W załączniku odpowiedni program do tego typu plików.
#include & lt; stdlib.h & gt; 
#include " crc.h " 
#include & lt; memory.h & gt; 
//#include " global.h " 
const unsigned int crc_16_l_table[ CRC_TAB_SIZE ] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
///////////////////////////////////////////////////////////////////
//CRC Table
///////////////////////////////////////////////////////////////////
/*********************************************************************/
unsigned int crc_16_l_calc(char* buf_ptr,unsigned int len)
{
unsigned int i;
unsigned short crc = 0;
while (len--!=0)
{
for(i = 0x80; i !=0 ; i = i & gt; & gt; 1)
{
if((crc & 0x8000) !=0 )
{
crc = crc & lt; & lt; 1 ;
crc = crc ^ 0x1021;
}
else
{
crc = crc & lt; & lt; 1 ;
} 
if((*buf_ptr & i) != 0 )
{
crc = crc ^ 0x1021;
}
}
buf_ptr++;
}
	
	return (crc);
}
/**---------------------------------------------------------------------------*
** FUNCTION *
** unsigned short cm_decode_msg(uchar_ptr *dest, byte *src) * 
** *	 
** DESCRIPTION *
** This function decodes the message of the source and restore the *
** decoded message to the destination buffer. *
** *
** INPUT *
** size: Size of the source buffer in byte. *
** src: Pointer of the input message. *
** *
** OUTPUT *
** dest: Pointer of the decoded message. *
** *
** RETURN VALUE *
** If the function is successful, return the size of the decoded message. *
** Else it returns CRC_ERROR : 0 or NO_END_FLAG : 0. *
** *	 
** DEPENDENCIES *
** extern word crc_16_l_calc(const void *src, word size); *
**---------------------------------------------------------------------------*/
int decode_msg(char* input_buf, int input_size, 
char **output_buf, int *output_len,int bcrc)
{
	unsigned short crc; /* CRC value*/	
	char *src_ptr; /* source buffer pointer*/
	int dest_len; /* output buffer length*/
char *dest_ptr; /* dest buffer pointer*/
register int curr;
/* Check if exist End Flag.*/
	src_ptr = input_buf;	
	dest_len = 0;
if( input_size & lt; 4 )
{
return 0;
}
/* Get the total size to be allocated for decoded message.*/
for( curr = 1; curr & lt; input_size - 1; curr++)
{
switch(*(src_ptr + curr))
{
case HDLC_ESCAPE:
curr++;
dest_len ++;
break;
default:
dest_len++;
break; 
}
} 
	/* Allocate meomory for decoded message*/
dest_ptr = NULL;
dest_ptr = (char *)malloc(dest_len);
/* Memory Free fail.*/
if(dest_ptr == NULL)
{
return 0;
}
memset(dest_ptr, 0, dest_len);
	curr = 0;
	dest_len = 0;
/* Do de-escape.*/
for( curr = 1; curr & lt; input_size - 1; curr++)
{
switch(*(src_ptr + curr))
{
case HDLC_ESCAPE:
curr++;
*(dest_ptr + dest_len) = *(src_ptr + curr) ^ HDLC_ESCAPE_MASK;
break;
default:
*(dest_ptr + dest_len) = *(src_ptr + curr);
break; 
}
		dest_len = dest_len + 1;
}
	
/* CRC Check. */	
if(bcrc)
{
crc = crc_16_l_calc(dest_ptr, dest_len);
if (crc != CRC_16_L_OK)
{
free(dest_ptr);	 
return 0;
}
}
else
{
/*
crc = crc_32_l_calc(dest_ptr, dest_len);
if ((crc & 0xFFFF) != CRC_16_L_OK)
{
free(dest_ptr);	 
return FALSE;
}
*/ 
crc = frm_chk((unsigned short *)dest_ptr, dest_len);
if (0 != crc)
{
free(dest_ptr);	 
return 0;
}
}	
*(output_buf) = dest_ptr;
*(output_len) = dest_len - CRC_CHECK_SIZE ;
	
return 1;
}
/**---------------------------------------------------------------------------*
** FUNCTION *
** word cm_encode_msg() * 
** *	 
** DESCRIPTION *
** This function encodes the message of the input message and restore *
** the encoded message to the dest bufffer. *
** *
** INPUT *
** size: Size of the source buffer in byte. *
** src: Pointer of the input message. *
** *
** OUTPUT *
** dest: Pointer of the encoded message. *
** *
** RETURN VALUE *
** Return the size of the coded message. *
** *	 
** DEPENDENCIES *
** extern word crc_16_l_calc(const void *src, word size); *
**---------------------------------------------------------------------------*/
int encode_msg(char* input_buf, int input_size, 
char **output_buf, int *output_len, int bcrc)
{
	unsigned short crc; /* CRC value*/
	char *src_ptr; /* source buffer pointer*/
	int dest_len; /* output buffer length*/
char *dest_ptr; /* dest buffer pointer*/
char high_crc, low_crc;
register int curr;
/* CRC Check. */
src_ptr = input_buf;
/* CRC Check. */	
if(bcrc)
{
crc = crc_16_l_calc(src_ptr, input_size);
}
else
{
//crc = crc_32_l_calc(src_ptr, input_size);
crc = frm_chk((unsigned short *)src_ptr, input_size);
/*
unsigned short SoruceValue, DestValue;
SoruceValue = crc;
DestValue = 0; 
CONVERT_SHORT(SoruceValue, DestValue); 
crc = DestValue;*/
} 
	high_crc = (crc & gt; & gt; 8) & 0xFF;
	low_crc = crc & 0xFF;
/* Get the total size to be allocated.*/
	dest_len = 0;
	for (curr = 0; curr & lt; input_size; curr++)
	{
		switch (*(src_ptr+curr))
		{
		case HDLC_FLAG:
		case HDLC_ESCAPE:
			dest_len += 2;
			break;
		default:
			dest_len++;
			break;
		}
	}
	
	switch (low_crc)
	{
	case HDLC_FLAG:
	case HDLC_ESCAPE:
		dest_len += 2;
		break;
	default:
		dest_len++;
	}
	
	switch (high_crc)
	{
	case HDLC_FLAG:
	case HDLC_ESCAPE:
		dest_len += 2;
		break;
	default:
		dest_len++;
	}
dest_ptr = (char *)malloc((dest_len + 2));
/* Memory Allocate fail.*/
if(dest_ptr == NULL)
{
return 0;
}
	*dest_ptr = HDLC_FLAG;
dest_len = 1;
/* do escape*/
for (curr = 0; curr & lt; input_size; curr++)
	{
		switch (*(src_ptr+curr))
		{
		case HDLC_FLAG:
		case HDLC_ESCAPE:
			*(dest_ptr + dest_len++) = HDLC_ESCAPE;
			*(dest_ptr + dest_len++) = *(src_ptr + curr) ^ HDLC_ESCAPE_MASK;
			break;
		default:
			*(dest_ptr + dest_len++) = *(src_ptr + curr);
			break;
		}
	}
	
	switch (high_crc)
	{
	case HDLC_FLAG:
case HDLC_ESCAPE:
		*(dest_ptr + dest_len++) = HDLC_ESCAPE;
		*(dest_ptr + dest_len++) = high_crc ^ HDLC_ESCAPE_MASK;
		break;
	default:
		*(dest_ptr + dest_len++) = high_crc;
	}
	switch (low_crc)
	{
	case HDLC_FLAG:
case HDLC_ESCAPE:
		*(dest_ptr + dest_len++) = HDLC_ESCAPE;
		*(dest_ptr + dest_len++) = low_crc ^ HDLC_ESCAPE_MASK;
		break;
	default:
		*(dest_ptr + dest_len++) = low_crc;
	}
	
	
	*(dest_ptr + dest_len++) = HDLC_FLAG;
*output_buf = dest_ptr;
*output_len = dest_len;
	return 1;
}
unsigned short frm_chk(unsigned short *src, int len)
{
unsigned int sum = 0;
unsigned short SourceValue, DestValue;
unsigned short lowSourceValue, hiSourceValue;
/* Get sum value of the source.*/
while (len & gt; 1)
{
SourceValue = *src++;
DestValue = 0; 
lowSourceValue = ( SourceValue & 0xFF00 ) & gt; & gt; 8;
hiSourceValue = ( SourceValue & 0x00FF ) & lt; & lt; 8;
DestValue = lowSourceValue | hiSourceValue;
sum += DestValue;
len -= 2;
}
if (len == 1)
{
sum += *( (unsigned char *) src );
}
sum = (sum & gt; & gt; 16) + (sum & 0x0FFFF);
sum += (sum & gt; & gt; 16);
return (~sum); 
}
/*********************************************************************/
unsigned int crc_32_l_calc(char* buf_ptr,unsigned int len)
{
unsigned int data, crc_16;
len *= 8;
for (crc_16 = CRC_16_L_SEED ; len & gt; = 8; len -= 8, buf_ptr++) 
{
crc_16 = crc_16_l_table[ (crc_16 ^ *buf_ptr) & 0x00ff ] ^ (crc_16 & gt; & gt; 8);
}
if (len != 0) 
{
data = ((unsigned short) (*buf_ptr)) & lt; & lt; (16-8);
while (len-- != 0) 
{
if ( ((crc_16 ^ data) & 0x01) != 0 )
{
crc_16 & gt; & gt; = 1;
crc_16 ^= CRC_16_L_POLYNOMIAL;
} 
else 
{
crc_16 & gt; & gt; = 1;
}
data & gt; & gt; = 1;
}
}
return( ~crc_16 );
}
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by BMAFrame.rc
//
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 9000
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 9000
#define _APS_NEXT_SYMED_VALUE 9000
#endif
#endif
// BMAFrame.h : main header file for the BMAFRAME DLL
//
#if !defined(AFX_BMAFRAME_H__6EFD7319_CCD8_4E7B_91B5_5AF4887CFD2D__INCLUDED_)
#define AFX_BMAFRAME_H__6EFD7319_CCD8_4E7B_91B5_5AF4887CFD2D__INCLUDED_
#if _MSC_VER & gt; 1000
#pragma once
#endif // _MSC_VER & gt; 1000
#ifndef __AFXWIN_H__
	#error include 'stdafx.h' before including this file for PCH
#endif
#include " resource.h " 		// main symbols
/////////////////////////////////////////////////////////////////////////////
// CBMAFrameApp
// See BMAFrame.cpp for the implementation of this class
//
class CBMAFrameApp : public CWinApp
{
public:
	CBMAFrameApp();
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CBMAFrameApp)
	public:
	virtual BOOL InitInstance();
	//}}AFX_VIRTUAL
	//{{AFX_MSG(CBMAFrameApp)
		// NOTE - the ClassWizard will add and remove member functions here.
		// DO NOT EDIT what you see in these blocks of generated code !
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_BMAFRAME_H__6EFD7319_CCD8_4E7B_91B5_5AF4887CFD2D__INCLUDED_)
// XmlConfigParse.cpp: implementation of the CXmlConfigParse class.
//
//////////////////////////////////////////////////////////////////////
#include " stdafx.h " 
#include " XmlConfigParse.h " 
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define FILE_OMIT_FLAG 2
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXmlConfigParse::CXmlConfigParse()
{
	m_xmlConfig.Close();
	m_mapProductInfo.RemoveAll();
	m_mapProductEnable.RemoveAll();
	m_aProductList.RemoveAll();
	m_pCurProduct = NULL;
	m_bOK = FALSE;
	m_strBaseConfig = _T( " " );
	m_mapPrdCfg.RemoveAll();
}
CXmlConfigParse::CXmlConfigParse(LPCTSTR lpcstrFileName)
{
	if(!Init(lpcstrFileName))
	{
		return;	
	}
	m_pCurProduct = NULL;
}
CXmlConfigParse::~CXmlConfigParse()
{
	Clear();
}
void CXmlConfigParse::Clear()
{
	m_bOK = FALSE;
	m_pCurProduct = NULL;
	int nCount = m_aProductList.GetSize();
	PPRODUCT_INFO_T pProd;
	for(int i = 0; i & lt; nCount; i++)
	{
		m_mapProductInfo.Lookup(m_aProductList[i],pProd);
		
		if(pProd != NULL)
		{
			pProd- & gt; Clear();
			delete pProd;
		}
	}
	m_mapProductInfo.RemoveAll();
	m_mapProductEnable.RemoveAll();
	m_aProductList.RemoveAll();	
	m_mapPrdCfg.RemoveAll();
}
BOOL CXmlConfigParse::Init(LPCTSTR lpszFileName,int nFlag /*= 0*/)
{
	if(!lpszFileName)
	{
		AfxMessageBox( _T( " The file name must not be empty! " ) );
		return FALSE;
	}
	m_strBaseConfig = lpszFileName;
if(nFlag == 0)
	{
		Clear();
		CString strBasePath= lpszFileName;
		int nFind = strBasePath.ReverseFind(_T('\\'));
		strBasePath = strBasePath.Left(nFind);
		
		m_bOK = LoadAllProductInfo(strBasePath);
	}
	else
	{
// 		m_aProductList.RemoveAll();
// 		m_mapProductInfo.RemoveAll();
// 		m_mapProductEnable.RemoveAll();
// 		m_mapPrdCfg.RemoveAll();
		
		m_bOK = _LoadProductInfo(lpszFileName,TRUE);	
	}
	return m_bOK;
	
}
/**
* Get the number of products
*
* @return Returns dwCount,the number of products
*/ 
DWORD CXmlConfigParse::GetProductCount()
{	
	return m_aProductList.GetSize();
}
/**
* Get product names
*
* @param arrProductNameList: store the names; 
*/ 
/*void CXmlConfigParse::GetProductNameList(CStringArray & arrProductNameList)
{
	LPXNode lpChild;
	lpChild = m_xmlConfig.GetChild(_T( " ProductList " ) );
	XNodes childs;
	childs = lpChild- & gt; GetChilds(_T( " Product " ) );
	int nCount = childs.size();
	CString strAttValue;
	for( int i = 0; i & lt; nCount; i++)
	{
		strAttValue= childs[i]- & gt; GetAttrValue(_T( " name " ));
		ASSERT(!strAttValue.IsEmpty());
		arrProductNameList.Add(strAttValue);
	}
	childs.clear();
}*/
/**
* Get product names
*
* @param pProductNameList: store the names; 
* @param dwSize: original pProductNameList spaces size; 
* @param dwRealSize: real used size; 
*/ 
void CXmlConfigParse::GetProductNameList(LPTSTR pProductNameList,DWORD dwSize,DWORD & dwRealSize)
{
	int nCount = m_aProductList.GetSize();
	CString strName;
	dwRealSize = 0;
	memset(pProductNameList,0,dwSize*sizeof(_TCHAR));
	for( int i = 0; i & lt; nCount; i++)
	{
		strName= m_aProductList.GetAt(i);
		ASSERT(!strName.IsEmpty());
		dwRealSize+=strName.GetLength();
		if(dwRealSize & gt; = dwSize)
		{
			break;
		}
		_tcscat(pProductNameList,(LPCTSTR)strName);
		pProductNameList[dwRealSize]=_T(';');
		dwRealSize++; //+';'
		//arrProductNameList.Add(strAttValue);
	}
	pProductNameList[dwRealSize] = _T('\0');
}
PPRODUCT_INFO_T CXmlConfigParse::GetProdInfo(LPCTSTR lpszProductName)
{
	ASSERT(lpszProductName != NULL);
BOOL bOk = m_mapProductInfo.Lookup(lpszProductName,m_pCurProduct);
	if(!bOk)
	{
		m_pCurProduct = NULL;
	}
	return m_pCurProduct;
}
/**
* Release this
*/ 
void CXmlConfigParse::Release()
{
	Clear();
	delete this;
}
BOOL CXmlConfigParse::Success()
{
	return m_bOK;
}
BOOL CXmlConfigParse::LoadAllProductInfo(LPCTSTR lpszConfigBase)
{
	CString strWildPath = lpszConfigBase;
	strWildPath += _T( " \\*.xml " );
	CFileFind finder;
	BOOL bFound;
	bFound = finder.FindFile(strWildPath);
	CStringArray aFilePath;
	CObArray aTime;
	CString strPath;
	CString strName;
	CString strBaseConfg = m_strBaseConfig;
	int nFind = strBaseConfg.ReverseFind(_T('\\'));
strBaseConfg = strBaseConfg.Right(strBaseConfg.GetLength() - nFind -1);
//	CTime *pCurTime;
	CTime lmCurTime;
	int i=0;
	while(bFound)
	{
		bFound = finder.FindNextFile();
	 strName = finder.GetFileName();
		if(strName.CompareNoCase(_T( " BMAConfigSchema.xml " )) == 0 ||
			strName.CompareNoCase(strBaseConfg)== 0)
		{
			continue;
		}
		else if(strName.Right(4).CompareNoCase(_T( " .xml " )) == 0)
		{
			strPath = finder.GetFilePath();
			finder.GetLastWriteTime(lmCurTime);
			
			int nCount = aFilePath.GetSize();
			if(nCount == 0)
			{
				aFilePath.Add(strPath);
				//pCurTime= new CTime(lmCurTime);
				aTime.Add((CObject *) & lmCurTime);
			}
			else
			{
				for(i=0; i & lt; nCount;i++)
				{
					if(lmCurTime & gt; = *(CTime*)aTime[i])
					{
						aTime.InsertAt(i,(CObject *) & lmCurTime);
						aFilePath.InsertAt(i,strPath);
						break;
					}
				}
				if(i & gt; =nCount)
				{
					aTime.Add((CObject *) & lmCurTime);
					aFilePath.Add(strPath);
				}
			}
			
		}
	}
/*
	m_aProductList.RemoveAll();
	m_mapProductInfo.RemoveAll();
	m_mapProductEnable.RemoveAll();
	m_mapPrdCfg.RemoveAll();
*/
	aFilePath.Add(m_strBaseConfig);
int nFileCount = aFilePath.GetSize();
	
	if(nFileCount == 0)
		return FALSE;
	
BOOL bOk = TRUE;
	for(i=0;i & lt; nFileCount;i++)
	{
		bOk = _LoadProductInfo(aFilePath.GetAt(i));
		if(!bOk)
			return FALSE;
	}
	return TRUE;
}
BOOL CXmlConfigParse::_Init(LPCTSTR lpszConfigName)
{
	_ASSERTE(lpszConfigName != NULL);
	// Open file
	CString strText;
	CString strNotes;
	CFile file;
	if ( !file.Open( lpszConfigName, CFile::modeRead ) )
	{
		AfxMessageBox( _T( " Unable to open xml config file " ) );
		return FALSE;
	}
	int nFileLen = (int)file.GetLength();
	
	// Allocate buffer for binary file data
	char* pBuffer = new char[nFileLen + 1];
	memset(pBuffer,0,nFileLen + 1);
	nFileLen = file.Read( pBuffer, nFileLen );
	file.Close();
	pBuffer[nFileLen] = '\0';
	
	_TCHAR *pBufferU = NULL;
	if(pBuffer[0] != (UCHAR)0xFF || pBuffer[1] != (UCHAR)0xFE)//not unicode 
	{
		pBufferU = new _TCHAR[nFileLen+1];
		memset(pBufferU,0,sizeof(_TCHAR)*(nFileLen + 1));
		MultiByteToWideChar(CP_ACP,0,pBuffer,nFileLen+1,pBufferU,nFileLen+1);
		strText.Empty();
		strText = pBufferU;
	}
	else
	{
		strText = (LPTSTR)pBuffer;
	}
	
	delete [] pBuffer;
	pBuffer = NULL;
	if(pBufferU != NULL)
	{
		delete [] pBufferU;
		pBufferU = NULL;
	}
	
	CString strXmlRet;
	strXmlRet = m_xmlConfig.Load(strText);
	strText.Empty();
	if(strXmlRet.IsEmpty())
	{
		return FALSE;
	}
	return TRUE;
}
BOOL CXmlConfigParse::_LoadProductInfo(LPCTSTR lpszConfigName,BOOL bChangePrdName/*= FALSE*/)
{
	BOOL bRet = _Init(lpszConfigName);
	if(!bRet)
		return FALSE;
	PPRODUCT_INFO_T pProuctInfo = NULL;
	PPRODUCT_INFO_T pFindProuctInfo = NULL;
	LPXNode lpChild;
	lpChild = m_xmlConfig.GetChild(_T( " ProductList " ) );
	if(lpChild == NULL) //check
		return FALSE;
	XNodes xnProductNodes;
	xnProductNodes = lpChild- & gt; GetChilds(_T( " Product " ) );
	int nCount = xnProductNodes.size();
	CString strCurSchemeName;
	CString strValue;
	int nValue;
	int nNvBkpItem;
	int i,j,k;
	UINT uEnable;
	for( i = 0; i & lt; nCount; i++)
	{		
		strValue= xnProductNodes[i]- & gt; GetAttrValue(_T( " name " ));
		ASSERT(!strValue.IsEmpty());
		if(strValue.IsEmpty())
		{
			continue;
		}
		if(bChangePrdName)
		{
			strValue.TrimLeft();
			strValue.Insert(0,_T( " PAC_ " ));
		}
		CString strEnable = xnProductNodes[i]- & gt; GetAttrValue(_T( " enable " ));
		nValue = 1;
		_stscanf( strEnable, _T( " %d " ), & nValue);
	
		pFindProuctInfo = NULL;
		if(!bChangePrdName)
		{
			//already exist
			if(m_mapProductInfo.Lookup(strValue,pFindProuctInfo))
			{		
				continue;
			}
			uEnable = 1;
			if(m_mapProductEnable.Lookup(strValue,uEnable) & & uEnable == 0 )
			{				
				continue;				
			}
			else
			{
				m_mapProductEnable.SetAt(strValue,(UINT)nValue);
				if(nValue == 0) //
				{
					continue;
				}
			}
		}
		else // PAC file config must be high level
		{
			//already exist,must remove it and use this one
			if(m_mapProductInfo.Lookup(strValue,pFindProuctInfo))
			{		
				if(pFindProuctInfo != NULL)
				{
					pFindProuctInfo- & gt; Clear();
					delete pFindProuctInfo;
					pFindProuctInfo = NULL;
				}
				m_mapProductInfo.RemoveKey(strValue);
			}
			m_mapProductEnable.SetAt(strValue,(UINT)1);
		}
pProuctInfo = new PRODUCT_INFO_T;
		m_aProductList.Add(strValue);
		m_mapProductInfo.SetAt(strValue,pProuctInfo);
		m_mapPrdCfg.SetAt(strValue,lpszConfigName);
		_tcscpy(pProuctInfo- & gt; szProductName,strValue);
		strCurSchemeName=xnProductNodes[i]- & gt; GetChildValue(_T( " SchemeName " ));
			
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " FlashTypeID " ));
_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwFlashType = nValue;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " Mode " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwMode = nValue;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " ProductComment " ));
		lstrcpyn(pProuctInfo- & gt; szComment,strValue,MAX_PATH+1);
nValue = 0;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " NvBaseAddrChangeFlag " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwNvBaseChangeFlag = nValue;
		nValue = 0;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " NvNewBasePosition " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwNvNewBasePosition= nValue;
		
		nValue = 0;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " NVOrgFlag " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwNVOrgFlag = nValue;
		nValue = 0;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " NVOrgBasePosition " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwNVOrgBasePosition= nValue;
		
		nValue = 0;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " OmaDMFlag " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; dwOmaDMFlag= nValue;	
		
		nValue = 0;
		strValue = xnProductNodes[i]- & gt; GetChildValue(_T( " RebootByAT " ));
		_stscanf( strValue, _T( " %d " ), & nValue);
		pProuctInfo- & gt; bRebootByAT = (BYTE)nValue;
		// for NV backup 
LPXNode lpNvBackup = NULL;
		lpNvBackup = xnProductNodes[i]- & gt; GetChild(_T( " NVBackup " ));
		if(lpNvBackup != NULL) // if " NVBackup " exist
		{
			nValue = 0;
			strValue = lpNvBackup- & gt; GetAttrValue(_T( " backup " ));
			_stscanf( strValue, _T( " %d " ), & nValue);
			pProuctInfo- & gt; dwNvBackupFlag = nValue;
			
			if(nValue != 0)
			{
				XNodes xnNvBkpList;
				xnNvBkpList = lpNvBackup- & gt; GetChilds(_T( " NVItem " ));
				pProuctInfo- & gt; dwNvBackupItemCount = xnNvBkpList.size();
				nNvBkpItem = pProuctInfo- & gt; dwNvBackupItemCount;
				if(nNvBkpItem != 0)
				{
					pProuctInfo- & gt; paNvBackupItem = new NV_BACKUP_ITEM_T[nNvBkpItem];
					memset(pProuctInfo- & gt; paNvBackupItem,0,sizeof(NV_BACKUP_ITEM_T)*nNvBkpItem);
					
					for(j = 0; j & lt; nNvBkpItem;j++)
					{
						PNV_BACKUP_ITEM_T pNBIT = pProuctInfo- & gt; paNvBackupItem + j;
							
						strValue = xnNvBkpList[j]- & gt; GetAttrValue(_T( " name " ));
						_tcscpy(pNBIT- & gt; szItemName,strValue);
						
						strValue = xnNvBkpList[j]- & gt; GetAttrValue(_T( " backup " ));
						nValue = 0;
						_stscanf(strValue,_T( " %d " ), & nValue);
						pNBIT- & gt; wIsBackup = (WORD)nValue;
						strValue = xnNvBkpList[j]- & gt; GetChildAttrValue(_T( " BackupFlag " ),_T( " use " ));
						nValue = 0;
						_stscanf(strValue,_T( " %d " ), & nValue);
						pNBIT- & gt; wIsUseFlag = (WORD)nValue;
						strValue = xnNvBkpList[j]- & gt; GetChildValue(_T( " ID " ));
						_stscanf(strValue,_T( " 0x%x " ), & (pNBIT- & gt; dwID));
						
						if(pNBIT- & gt; wIsUseFlag == 1)
						{
							XNodes xnNvFlagList;
							LPXNode lpxnFlag;
							lpxnFlag = xnNvBkpList[j]- & gt; GetChild(_T( " BackupFlag " ));
							if(lpxnFlag == NULL)
							{
								delete [] pProuctInfo- & gt; paNvBackupItem;
								pProuctInfo- & gt; paNvBackupItem = NULL;
								delete pProuctInfo;
								pProuctInfo = NULL;
								return FALSE;							
							}
							
							xnNvFlagList = lpxnFlag- & gt; GetChilds(_T( " NVFlag " ));
							int nNvFlagCount = xnNvFlagList.size();
							if(nNvFlagCount & gt; MAX_NV_BACKUP_FALG_NUM)
							{
								nNvFlagCount = MAX_NV_BACKUP_FALG_NUM;
							}
							pNBIT- & gt; dwFlagCount = (DWORD)nNvFlagCount;	
							//TRACE(_T( " %s: NvFlagCount:%d\n " ),pProuctInfo- & gt; szProductName,nNvFlagCount);
						
							for(k=0; k & lt; nNvFlagCount;k++)
							{		
								strValue = xnNvFlagList[k]- & gt; GetAttrValue(_T( " name " ));
								_tcscpy(pNBIT- & gt; nbftArray[k].szFlagName,strValue);
								
								strValue = xnNvFlagList[k]- & gt; GetAttrValue(_T( " check " ));
								_stscanf( strValue, _T( " %d " ), & (pNBIT- & gt; nbftArray[k].dwCheck));
							}
							xnNvFlagList.clear();
						}
					}
				}
				xnNvBkpList.clear();
			}			
		}
//////////////////////////////////////////////////////////////////////////
		// for Chips
		/*
		 * & lt; Chips enable= " 0 " & gt; 
		 *		 & lt; ChipItem id= " 0x222 " name= " L2 " / & gt; 
		 *		 & lt; ChipItem id= " 0x777 " name= " L7 " / & gt; 
		 * & lt; /Chips & gt; 
		*/
LPXNode lpChips = NULL;
		lpChips = xnProductNodes[i]- & gt; GetChild(_T( " Chips " ));
		if(lpChips != NULL) // if " Chips " exist
		{
			nValue = 0;
			strValue = lpChips- & gt; GetAttrValue(_T( " enable " ));
			_stscanf( strValue, _T( " %d " ), & nValue);
			pProuctInfo- & gt; tChips.bEnable = nValue;
			
			if(nValue != 0)
			{
				XNodes xnChipList;
				xnChipList = lpChips- & gt; GetChilds(_T( " ChipItem " ));
				UINT nChipCount = xnChipList.size(); 
				pProuctInfo- & gt; tChips.dwCount = nChipCount;			
				if(nChipCount != 0)
				{
					pProuctInfo- & gt; tChips.pChips = new CHIPITEM_T[nChipCount];
					memset(pProuctInfo- & gt; tChips.pChips,0,sizeof(CHIPITEM_T)*nChipCount);
					
					for(j = 0; j & lt; (int)nChipCount;j++)
					{
						CHIPITEM_PTR pChipItem = pProuctInfo- & gt; tChips.pChips + j;					
						strValue.Empty();
						strValue = xnChipList[j]- & gt; GetAttrValue(_T( " id " ));
						nValue = 0;
						_stscanf(strValue,_T( " 0x%X " ), & nValue);
						pChipItem- & gt; dwID = (DWORD)nValue;
						strValue.Empty();
						strValue = xnChipList[j]- & gt; GetAttrValue(_T( " name " ));
						_tcscpy(pChipItem- & gt; szName,strValue);
					}					
				}
				xnChipList.clear();
			}			
		}
////////////////////////////////////////////////////////////////////////// 
LPXNode lpSpecialStrings = NULL;
		lpSpecialStrings = xnProductNodes[i]- & gt; GetChild(_T( " SpecialStrings " ));
		if(lpSpecialStrings != NULL) // if " SpecialStrings " exist
		{
			nValue = 0;
			strValue = lpSpecialStrings- & gt; GetAttrValue(_T( " enable " ));
			_stscanf( strValue, _T( " %d " ), & nValue);			
			if(nValue != 0)
			{
				XNodes xnSpecialStrList;
				xnSpecialStrList = lpSpecialStrings- & gt; GetChilds(_T( " SString " ));
				int nSSItem = xnSpecialStrList.size();				
				if(nSSItem != 0)
				{
					pProuctInfo- & gt; pSpecialStrings = new SPECIAL_STRING_ARR;
					
					for(j = 0; j & lt; nSSItem;j++)
					{
						SPECIAL_STRING_PTR pSString = new SPECIAL_STRING_T;
							
						strValue = xnSpecialStrList[j]- & gt; GetAttrValue(_T( " name " ));
						_tcscpy(pSString- & gt; szName,strValue);
						
						strValue = xnSpecialStrList[j]- & gt; GetAttrValue(_T( " content " ));
						_tcscpy(pSString- & gt; szContent,strValue);
						strValue = xnSpecialStrList[j]- & gt; GetAttrValue(_T( " included " ));
						_tcscpy(pSString- & gt; szIncluedFileID,strValue);
						
				
						XNodes xnLinkedFileList;						
						xnLinkedFileList = xnSpecialStrList[j]- & gt; GetChilds(_T( " LinkedFile " ));
						int nLFNodeCount = xnLinkedFileList.size();
						
						if(nLFNodeCount & gt; 0)
						{
							pSString- & gt; pLinkedFileIDs = new LINKED_FILE_ARR;
							for(k=0; k & lt; nLFNodeCount;k++)
							{	
								LINKED_FILE_PTR pLinkedFile = new LINKED_FILE_T;
								strValue = xnLinkedFileList[k]- & gt; GetAttrValue(_T( " id " ));
								_tcscpy(pLinkedFile- & gt; szFileID,strValue);
								
								strValue = xnLinkedFileList[k]- & gt; GetAttrValue(_T( " download " ));
								_stscanf( strValue, _T( " %d " ), & (pLinkedFile- & gt; dwDLFlag));
								pSString- & gt; pLinkedFileIDs- & gt; push_back(pLinkedFile);
							}
						}					
						pProuctInfo- & gt; pSpecialStrings- & gt; push_back(pSString);
						
						xnLinkedFileList.clear();
					}
				
				}
				xnSpecialStrList.clear();
			}
		}
//////////////////////////////////////////////////////////////////////////
		
		LPXNode lpSchemeListNode = m_xmlConfig.GetChild( _T( " SchemeList " ) );
		XNodes xnSchemeNodeList;
		xnSchemeNodeList = lpSchemeListNode- & gt; GetChilds(_T( " Scheme " ));
		int nSchemeCount = xnSchemeNodeList.size();
		
		for(j = 0; j & lt; nSchemeCount;j++)
		{
			strValue= xnSchemeNodeList[j]- & gt; GetAttrValue(_T( " name " ));
			ASSERT(!strValue.IsEmpty());
			
			if(strValue.Compare(strCurSchemeName)==0)
			{
				XNodes xnFileNodeList;
				xnFileNodeList = xnSchemeNodeList[j]- & gt; GetChilds(_T( " File " ));
				pProuctInfo- & gt; dwFileCount = xnFileNodeList.size();
				int nFileCount = (int)(pProuctInfo- & gt; dwFileCount);
				if(nFileCount & gt; 0)
				{
					pProuctInfo- & gt; pFileInfoArr = new FILE_INFO_T[nFileCount];
					memset(pProuctInfo- & gt; pFileInfoArr,0,sizeof(FILE_INFO_T)*nFileCount);
					for(k=0;k & lt; nFileCount;k++)
					{
						PFILE_INFO_T pFIT = pProuctInfo- & gt; pFileInfoArr + k;
						
						nValue = 0;
						strValue = xnFileNodeList[k]- & gt; GetAttrValue(_T( " backup " ));
						_stscanf( strValue, _T( " %d " ), & nValue);
						pFIT- & gt; isBackup = (BYTE)nValue;
			
						strValue = xnFileNodeList[k]- & gt; GetChildValue(_T( " ID " ));	
						_tcscpy(pFIT- & gt; szID,strValue);
						
						strValue.Empty();
						strValue = xnFileNodeList[k]- & gt; GetChildValue(_T( " IDAlias " ));	
						if(!strValue.IsEmpty())
						{
							_tcscpy(pFIT- & gt; szIDAlias,strValue);
						}
						else
						{
							_tcscpy(pFIT- & gt; szIDAlias,pFIT- & gt; szID);
						}
						
						strValue = xnFileNodeList[k]- & gt; GetChildValue(_T( " Type " ));
						_tcscpy(pFIT- & gt; szType,strValue);
						
						strValue = xnFileNodeList[k]- & gt; GetChildValue(_T( " Flag " ));
						pFIT- & gt; dwFlag = (DWORD)_ttoi(strValue);
						
						strValue = xnFileNodeList[k]- & gt; GetChildValue(_T( " CheckFlag " ));
						pFIT- & gt; dwCheckFlag = (DWORD)_ttoi(strValue);
						
						strValue = xnFileNodeList[k]- & gt; GetChildValue(_T( " Description " ));
						_tcscpy(pFIT- & gt; szFileDescript,strValue);
						XNodes nxBlockList;
						nxBlockList = xnFileNodeList[k]- & gt; GetChilds(_T( " Block " ));
						int nBlockCount = nxBlockList.size();
						if(nBlockCount & gt; MAX_BLOCK_NUM)
							nBlockCount = MAX_BLOCK_NUM;
						
						pFIT- & gt; dwBlockCount = (DWORD)nBlockCount;
						for(int t=0; t & lt; nBlockCount;t++)
						{		
							strValue = nxBlockList[t]- & gt; GetChildValue(_T( " Base " ));
							_stscanf( strValue, _T( " 0x%X " ), & (pFIT- & gt; arrBlock[t].dwBase));
							
							strValue = nxBlockList[t]- & gt; GetChildValue(_T( " Size " ));
							_stscanf( strValue, _T( " 0x%X " ), & (pFIT- & gt; arrBlock[t].dwSize));
						}
						nxBlockList.clear();
					}
				}
				xnFileNodeList.clear();
				
				break;
			}
		}
xnSchemeNodeList.clear();
		if(j & gt; = nSchemeCount)
		{
			//TRACE(_T( " Product scheme[%s] is not exist!\r\n " ),strCurSchemeName);			
			continue;
		}
	}
	xnProductNodes.clear();	
	_Close();
	return TRUE;
}
void CXmlConfigParse::_Close()
{
	m_xmlConfig.Close();
}
LPTSTR CXmlConfigParse::GetConfigFile(LPCTSTR lpszProductName)
{
	ASSERT(lpszProductName != NULL);
	static CString strConfigFile = _T( " " );
BOOL bOk = m_mapPrdCfg.Lookup(lpszProductName,strConfigFile);
	if(!bOk)
	{
		return NULL;
	}
	return (LPTSTR)(LPCTSTR)strConfigFile;
}
#if !defined(AFX_LISTEDITCTRL_H__3C02B0B1_A395_11D1_9799_002018026B76__INCLUDED_)
#define AFX_LISTEDITCTRL_H__3C02B0B1_A395_11D1_9799_002018026B76__INCLUDED_
#if _MSC_VER & gt; = 1000
#pragma once
#endif // _MSC_VER & gt; = 1000
// ListEditCtrl.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CListEditCtrl window
class CListEditCtrl : public CEdit
{
// Construction
public:
	CListEditCtrl(int iItem, int iSubItem, const CString & sInitText);
// Attributes
public:
// Operations
public:
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CListEditCtrl)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	//}}AFX_VIRTUAL
// Implementation
public:
	virtual ~CListEditCtrl(){};
private:	
	int m_iItem;
	int m_iSubItem;	
	CString m_strInitText;
	BOOL m_bVK_ESCAPE;
	// Generated message map functions
protected:
	//{{AFX_MSG(CListEditCtrl)
	afx_msg void OnKillFocus(CWnd* pNewWnd);
	afx_msg void OnNcDestroy();
	afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);	
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_LISTEDITCTRL_H__3C02B0B1_A395_11D1_9799_002018026B76__INCLUDED_)
// FlashOptPage.cpp : implementation file
//
#include " stdafx.h " 
#include " dloader.h " 
#include " FlashOptPage.h " 
#include " EdtBtnCtrl.h " 
#include " BMAGlobal.h " 
#include " SettingsSheet.h " 
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifndef _lint // bad pc-lint
extern BOOL g_bInitSheet;
#endif
static _TCHAR g_sz_SEC_READFLASH[]		= _T( " ReadFlash " );
static _TCHAR g_sz_KEY_FLASH[] = _T( " flash " );
#define READ_FLASH 0 
#define ERASE_FLASH 1
#define WRITE_FLASH 2
/////////////////////////////////////////////////////////////////////////////
// CFlashOptPage property page
IMPLEMENT_DYNCREATE(CFlashOptPage, CPropertyPage)
CFlashOptPage::CFlashOptPage() : CPropertyPage(CFlashOptPage::IDD)
{
	//{{AFX_DATA_INIT(CFlashOptPage)
	m_bTmpActiveRead = FALSE;	
	m_bTmpActiveErase = FALSE;
	m_bTmpActiveWrite = FALSE;
	m_bTmpEraseAll = FALSE;	
	//}}AFX_DATA_INIT
	m_agReadFlash.RemoveAll();
	m_bActiveRead = m_bTmpActiveRead;
	m_bActiveErase = m_bTmpActiveErase;
	m_bActiveWrite = m_bTmpActiveWrite;
	m_bEraseAll = m_bTmpEraseAll;
}
CFlashOptPage::~CFlashOptPage()
{
/*lint -save -e1551 */
	Clear();
	m_agReadFlash.RemoveAll();
	m_agEraseFlash.RemoveAll();
	m_agWriteFlash.RemoveAll();
/*lint -restore */
}
void CFlashOptPage::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFlashOptPage)
	DDX_Control(pDX, IDC_FOD_LST_WRITE, m_lstWrite);
	DDX_Control(pDX, IDC_FOD_LST_ERASE, m_lstErase);
	DDX_Control(pDX, IDC_FOD_LST_READ, m_lstRead);
	DDX_Check(pDX, IDC_FOD_CHK_ACTIVE_READ_FLASH, m_bTmpActiveRead);	
	DDX_Check(pDX, IDC_FOD_CHK_ACTIVE_ERASE_FLASH, m_bTmpActiveErase);
	DDX_Check(pDX, IDC_FOD_CHK_ACTIVE_WRITE_FLASH, m_bTmpActiveWrite);
	DDX_Check(pDX, IDC_FOD_CHK_ERASE_ALL, m_bTmpEraseAll);	
	//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CFlashOptPage, CPropertyPage)
	//{{AFX_MSG_MAP(CFlashOptPage)
	ON_NOTIFY(NM_CLICK, IDC_FOD_LST_READ, OnClickLstRead)
	ON_NOTIFY(LVN_ENDLABELEDIT, IDC_FOD_LST_READ, OnEndlabeleditLstRead)
	ON_BN_CLICKED(IDC_FOD_BTN_DEL, OnBtnClear)
	ON_BN_CLICKED(IDC_FOD_CHK_ACTIVE_READ_FLASH, OnChkActiveReadFlash)
	ON_BN_CLICKED(IDC_FOD_BTN_DELE, OnEraseClear)
	ON_BN_CLICKED(IDC_FOD_BTN_DELW, OnWriteClear)
	ON_BN_CLICKED(IDC_FOD_CHK_ACTIVE_ERASE_FLASH, OnChkActiveEraseFlash)
	ON_BN_CLICKED(IDC_FOD_CHK_ACTIVE_WRITE_FLASH, OnChkActiveWriteFlash)
	ON_NOTIFY(NM_CLICK, IDC_FOD_LST_ERASE, OnClickLstErase)
	ON_NOTIFY(NM_CLICK, IDC_FOD_LST_WRITE, OnClickLstWrite)
	ON_NOTIFY(LVN_ENDLABELEDIT, IDC_FOD_LST_ERASE, OnEndlabeleditLstErase)
	ON_NOTIFY(LVN_ENDLABELEDIT, IDC_FOD_LST_WRITE, OnEndlabeleditLstWrite)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CFlashOptPage message handlers
BOOL CFlashOptPage::OnInitDialog() 
{
	CPropertyPage::OnInitDialog();
	
	// TODO: Add extra initialization here
	InitList(m_lstRead,READ_FLASH);
	InitList(m_lstErase,ERASE_FLASH);
	InitList(m_lstWrite,WRITE_FLASH);
	
	if(!m_strIniFile.IsEmpty())
	{
		CString str;
		LoadSettings(m_strIniFile,str);
	}
	
	FillList(m_lstRead,m_agReadFlash,READ_FLASH);
	FillList(m_lstErase,m_agEraseFlash,ERASE_FLASH);
	FillList(m_lstWrite,m_agWriteFlash,WRITE_FLASH);
	m_bTmpActiveRead = m_bActiveRead;
	m_bTmpActiveErase = m_bActiveErase;
	m_bTmpActiveWrite = m_bActiveWrite;
	m_bTmpEraseAll = m_bEraseAll;
	
	UpdateData(FALSE);
	OnChkActiveReadFlash();
	OnChkActiveEraseFlash();
	OnChkActiveWriteFlash();
	
	return TRUE; // return TRUE unless you set the focus to a control
	 // EXCEPTION: OCX Property Pages should return FALSE
}
void CFlashOptPage::ClickList(NMHDR* pNMHDR,CListCtrl & ctrList,int nList)
{
	LPNMITEMACTIVATE pnia = (LPNMITEMACTIVATE)pNMHDR;
	
	CEdtBtnCtrl *pCtrl = NULL;
	int nItem = pnia- & gt; iItem;
	int nSubItem = pnia- & gt; iSubItem;
	if(nItem == -1)
	{
		int nCount = ctrList.GetItemCount();
		CString strText;
		if( nCount == 0 ||
			(nList == READ_FLASH & & !ctrList.GetItemText(nCount-1,1).IsEmpty() & & 
			!ctrList.GetItemText(nCount-1,2).IsEmpty() & & 
			!ctrList.GetItemText(nCount-1,3).IsEmpty()) ||
			(nList == ERASE_FLASH & & !ctrList.GetItemText(nCount-1,1).IsEmpty() & & 
			!ctrList.GetItemText(nCount-1,2).IsEmpty())||
			(nList == WRITE_FLASH & & !ctrList.GetItemText(nCount-1,1).IsEmpty() & & 
			!ctrList.GetItemText(nCount-1,3).IsEmpty()))
		{
			ctrList.InsertItem(nCount,_T( " " ));
			if(nCount & gt; 0)			
			{
				ctrList.SetCheck(nCount-1);
			}
			nItem = nCount;
		}	
		else if(ctrList.GetItemText(nCount-1,1).IsEmpty() & & 
			ctrList.GetItemText(nCount-1,2).IsEmpty() & & 
			ctrList.GetItemText(nCount-1,3).IsEmpty())
		{
			ctrList.DeleteItem(nCount-1);
			return;
		}
		else
		{
			return;
		}
	}
	
	if(nSubItem == 0 || (nSubItem == 3 & & nList == ERASE_FLASH) || (nSubItem == 2 & & nList == WRITE_FLASH))
	{
		return;
	}
	
	
	pCtrl = new CEdtBtnCtrl();
	
	BOOL bEnablBtn = FALSE;
	BOOL bOpenFile = FALSE;
	if(nSubItem == 3)
	{
		bEnablBtn = TRUE;
		if(nList == WRITE_FLASH)
		{
			bOpenFile = TRUE;
		}
	}
	
	if(NULL != pCtrl)
	{		
		pCtrl- & gt; EnableFileSelButton(bEnablBtn);
		pCtrl- & gt; SetBtnOpenFlag(bOpenFile);
		if(nSubItem == 1 || nSubItem == 2 )
		{
			pCtrl- & gt; SetEditFmtMode(EX_FMT_HEX);
		}
		pCtrl- & gt; m_nItem = nItem;
		pCtrl- & gt; m_nSubItem = nSubItem;
		pCtrl- & gt; m_strText = ctrList.GetItemText(nItem,nSubItem);
		if(!pCtrl- & gt; Create(IDD_EDT_BTN_DLG,FromHandle(ctrList.m_hWnd)))
		{
			AfxMessageBox(_T( " Error to create EdtBtnCtrl " ));
			return;
		}
	}
	else
	{
		return;
	}
	
	CRect rect;
	ctrList.GetSubItemRect(nItem,nSubItem,LVIR_BOUNDS,rect);
	CRect rtList;
	ctrList.GetClientRect( & rtList);
	if(rect.right & gt; rtList.right)
		rect.right = rtList.right;
	if(rect.left & lt; rtList.left)
		rect.left = rtList.left;
	if(rect.bottom & gt; rtList.bottom)
		rect.bottom = rtList.bottom;
	if(rect.top & lt; rtList.top)
		rect.top = rtList.top;
	
	pCtrl- & gt; SetWindowPos( & wndTop,rect.left,rect.top-1,rect.right-rect.left,rect.bottom-rect.top,NULL);
	
pCtrl- & gt; ShowWindow(SW_SHOW);
}
void CFlashOptPage::OnClickLstRead(NMHDR* pNMHDR, LRESULT* pResult) 
{
	ClickList(pNMHDR,m_lstRead,0);
	
	*pResult = 0;
}
void CFlashOptPage::OnEndlabeleditLstRead(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	m_lstRead.SetItemText(pDispInfo- & gt; item.iItem,pDispInfo- & gt; item.iSubItem,pDispInfo- & gt; item.pszText);
	*pResult = 0;
}
void CFlashOptPage::OnEndlabeleditLstErase(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	m_lstErase.SetItemText(pDispInfo- & gt; item.iItem,pDispInfo- & gt; item.iSubItem,pDispInfo- & gt; item.pszText);
	*pResult = 0;
}
void CFlashOptPage::OnEndlabeleditLstWrite(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	m_lstWrite.SetItemText(pDispInfo- & gt; item.iItem,pDispInfo- & gt; item.iSubItem,pDispInfo- & gt; item.pszText);
	*pResult = 0;
}
void CFlashOptPage::OnBtnClear() 
{
	// TODO: Add your control notification handler code here
	m_lstRead.DeleteAllItems();
}
BOOL CFlashOptPage::OnKillActive() 
{
	// TODO: Add your specialized code here and/or call the base class
	this- & gt; SetFocus();
	if( !g_bInitSheet)
	{
		if(m_bTmpActiveRead)
		{
			int nCount = m_lstRead.GetItemCount();
			for(int i = 0; i & lt; nCount;i++)
			{
				if(m_lstRead.GetCheck(i))
				{
					CString strBase = m_lstRead.GetItemText(i,1);
					CString strSize = m_lstRead.GetItemText(i,2);
					CString strFile = m_lstRead.GetItemText(i,3);
					if(strBase.IsEmpty() || strFile.IsEmpty() || strSize.IsEmpty())
					{
						m_lstRead.SetFocus();
						m_lstRead.SetItemState(i,LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED| LVIS_FOCUSED);
						AfxMessageBox(IDS_ERR_ITEM_EMPTY);			
						return FALSE;
					}
				}
			}
			if( nCount & gt; 0 & & m_lstRead.GetItemText(nCount-1,1).IsEmpty() & & 
				m_lstRead.GetItemText(nCount-1,2).IsEmpty() & & 
				m_lstRead.GetItemText(nCount-1,3).IsEmpty())
			{
				m_lstRead.DeleteItem(nCount-1);
			}
		}
		if(m_bTmpActiveErase)
		{
			int nCount = m_lstErase.GetItemCount();
			for(int i = 0; i & lt; nCount;i++)
			{
				if(m_lstErase.GetCheck(i))
				{
					CString strBase = m_lstErase.GetItemText(i,1);
					CString strSize = m_lstErase.GetItemText(i,2);				
					if(strBase.IsEmpty() || strSize.IsEmpty())
					{
						m_lstErase.SetFocus();
						m_lstErase.SetItemState(i,LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED| LVIS_FOCUSED);
						AfxMessageBox(IDS_ERR_ITEM_EMPTY);			
						return FALSE;
					}
				}
			}
			if( nCount & gt; 0 & & m_lstErase.GetItemText(nCount-1,1).IsEmpty() & & 
				m_lstErase.GetItemText(nCount-1,2).IsEmpty() )
			{
				m_lstErase.DeleteItem(nCount-1);
			}
		}
		if(m_bTmpActiveWrite)
		{
			CFileFind finder;
			int nCount = m_lstWrite.GetItemCount();
			for(int i = 0; i & lt; nCount;i++)
			{
				if(m_lstWrite.GetCheck(i))
				{
					CString strBase = m_lstWrite.GetItemText(i,1);
					//CString strSize = m_lstRead.GetItemText(i,2);
					CString strFile = m_lstWrite.GetItemText(i,3);
					if(strBase.IsEmpty() || strFile.IsEmpty() || (!strFile.IsEmpty() & & !finder.FindFile(strFile)))
					{
						m_lstWrite.SetFocus();
						m_lstWrite.SetItemState(i,LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED| LVIS_FOCUSED);
						if(!strFile.IsEmpty() & & !finder.FindFile(strFile))
						{
							CString strErr;
							strErr.Format(_T( " File [%s] not exist! " ),strFile);
							AfxMessageBox(strErr);
						}
						else
						{
							AfxMessageBox(IDS_ERR_ITEM_EMPTY);
						}
									
						return FALSE;
					}
				}
			}
			if( nCount & gt; 0 & & m_lstWrite.GetItemText(nCount-1,1).IsEmpty() & & 
				m_lstWrite.GetItemText(nCount-1,3).IsEmpty())
			{
				m_lstWrite.DeleteItem(nCount-1);
			}
		}
	}
	
	return CPropertyPage::OnKillActive();
}
void CFlashOptPage::OnOK() 
{
	// TODO: Add your specialized code here and/or call the base class
	UpdateData();
	m_bActiveRead = m_bTmpActiveRead;
	m_bActiveErase = m_bTmpActiveErase;
	m_bActiveWrite = m_bTmpActiveWrite;
	m_bEraseAll = m_bTmpEraseAll;	
	Clear();
	int nCount = m_lstRead.GetItemCount();
	CFileFind finder;
	int i=0;
	for(i = 0; i & lt; nCount & & m_bActiveRead;i++)
	{
		if(m_lstRead.GetCheck(i))
		{
			CString strBase = m_lstRead.GetItemText(i,1);
			CString strSize = m_lstRead.GetItemText(i,2);
			CString strFile = m_lstRead.GetItemText(i,3);
			CString strID;	
			
			if(finder.FindFile(strFile))
			{
				DWORD dwAttr = GetFileAttributes(strFile);
				if(MAXDWORD != dwAttr)
				{
					dwAttr & = ~FILE_ATTRIBUTE_READONLY;
					::SetFileAttributes(strFile,dwAttr);
				}
			}
			PFILE_INFO_T pFileInfo = new FILE_INFO_T;
			pFileInfo- & gt; arrBlock[0].dwBase = GetDigit(strBase);
			pFileInfo- & gt; arrBlock[0].dwSize = GetDigit(strSize);
			strID.Format(_T( " R%08X " ),pFileInfo- & gt; arrBlock[0].dwBase);
			_tcscpy(pFileInfo- & gt; szID,strID);
			_tcscpy(pFileInfo- & gt; szIDAlias,strID);
			_tcscpy(pFileInfo- & gt; szFilePath,strFile);
			_tcscpy(pFileInfo- & gt; szType,_T( " ReadFlashAndSave " ));
			pFileInfo- & gt; dwCheckFlag = TRUE;
			m_agFlashOpr.Add((DWORD)pFileInfo);
		}
	}
	nCount = m_lstErase.GetItemCount();
	for(i = 0; i & lt; nCount & & m_bActiveErase;i++)
	{
		if(m_lstErase.GetCheck(i))
		{
			CString strBase = m_lstErase.GetItemText(i,1);
			CString strSize = m_lstErase.GetItemText(i,2);
			CString strFile = m_lstErase.GetItemText(i,3);
			CString strID;	
			
			PFILE_INFO_T pFileInfo = new FILE_INFO_T;
			pFileInfo- & gt; arrBlock[0].dwBase = GetDigit(strBase);
			pFileInfo- & gt; arrBlock[0].dwSize = GetDigit(strSize);
			strID.Format(_T( " R%08X " ),pFileInfo- & gt; arrBlock[0].dwBase);
			_tcscpy(pFileInfo- & gt; szID,strID);
			_tcscpy(pFileInfo- & gt; szIDAlias,strID);
			//_tcscpy(pFileInfo- & gt; szFilePath,strFile);
			_tcscpy(pFileInfo- & gt; szType,_T( " EraseFlash " ));
			pFileInfo- & gt; dwCheckFlag = TRUE;
			
			m_agFlashOpr.Add((DWORD)pFileInfo);
		}
	}
	nCount = m_lstWrite.GetItemCount();
	for(i = 0; i & lt; nCount & & m_bActiveWrite;i++)
	{
		if(m_lstWrite.GetCheck(i))
		{
			CString strBase = m_lstWrite.GetItemText(i,1);
			CString strSize = m_lstWrite.GetItemText(i,2);
			CString strFile = m_lstWrite.GetItemText(i,3);
			CString strID;		
			
			PFILE_INFO_T pFileInfo = new FILE_INFO_T;
			pFileInfo- & gt; arrBlock[0].dwBase = GetDigit(strBase);
			pFileInfo- & gt; arrBlock[0].dwSize = GetDigit(strSize);
			strID.Format(_T( " W%08X " ),pFileInfo- & gt; arrBlock[0].dwBase);
			_tcscpy(pFileInfo- & gt; szID,strID);
			_tcscpy(pFileInfo- & gt; szIDAlias,strID);
			_tcscpy(pFileInfo- & gt; szFilePath,strFile);
			_tcscpy(pFileInfo- & gt; szType,_T( " CODE " ));
			pFileInfo- & gt; dwCheckFlag = TRUE;
			
			m_agFlashOpr.Add((DWORD)pFileInfo);
		}
	}
	//±£´æÉèÖÃ
	if(!m_strIniFile.IsEmpty() & & finder.FindFile(m_strIniFile))
	{
		DWORD dwAttr = GetFileAttributes(m_strIniFile);
		if(MAXDWORD != dwAttr)
		{
			dwAttr & = ~FILE_ATTRIBUTE_READONLY;
			::SetFileAttributes(m_strIniFile,dwAttr);
		}
		SaveSettings(m_strIniFile);
	}
	CPropertyPage::OnOK();
}
void CFlashOptPage::Clear()
{
	for(int i = 0; i & lt; m_agFlashOpr.GetSize(); i++)
	{
		delete [] (PFILE_INFO_T)m_agFlashOpr[i];
	}
	m_agFlashOpr.RemoveAll();
}
void CFlashOptPage::OnChkActiveReadFlash() 
{
	// TODO: Add your control notification handler code here
	UpdateData();
	if(m_bTmpActiveRead)
	{
		m_lstRead.EnableWindow(TRUE);
		GetDlgItem(IDC_FOD_BTN_DEL)- & gt; EnableWindow(TRUE);
	}
	else
	{
		m_lstRead.EnableWindow(FALSE);
		GetDlgItem(IDC_FOD_BTN_DEL)- & gt; EnableWindow(FALSE);
	}
}
BOOL CFlashOptPage::LoadSettings(LPCTSTR pFileName,CString & strErrorMsg)
{
//	UNUSED_ALWAYS(strErrorMsg);
	if(NULL == pFileName)
	{
		strErrorMsg += _T( " Configure file is empty!\n " );
		return FALSE;
	}
	m_strIniFile = pFileName;
	LoadFlashOpr(_T( " ReadFlash " ),m_agReadFlash);
	LoadFlashOpr(_T( " EraseFlash " ),m_agEraseFlash);
	LoadFlashOpr(_T( " WriteFlash " ),m_agWriteFlash); 
	return TRUE;
}
BOOL CFlashOptPage::SaveSettings(LPCTSTR pFileName)
{
	if(NULL == pFileName)
		return FALSE;
	SaveFlashOpr(m_lstRead,_T( " ReadFlash " ),pFileName);
	SaveFlashOpr(m_lstErase,_T( " EraseFlash " ),pFileName);
	SaveFlashOpr(m_lstWrite,_T( " WriteFlash " ),pFileName);
	return TRUE;
}
void CFlashOptPage::SaveFlashOpr(CListCtrl & ctrList,LPCTSTR lpszSec,LPCTSTR lpszFile)
{
	WritePrivateProfileSection(lpszSec,_T( " " ),lpszFile);
	int nCount = ctrList.GetItemCount();
	for(int i= 0; i & lt; nCount; i++)
	{
		CString strText;
		strText.Format(_T( " %d:%s:%s:%s " ),
			ctrList.GetCheck(i),
			ctrList.GetItemText(i,1).operator LPCTSTR(),
			ctrList.GetItemText(i,2).operator LPCTSTR(),
			ctrList.GetItemText(i,3).operator LPCTSTR());
		CString strKey;
		strKey.Format(_T( " %s%02d " ),g_sz_KEY_FLASH,i);		
		WritePrivateProfileString(lpszSec,strKey,strText,lpszFile);
		
	}
}
void CFlashOptPage::FillList(CListCtrl & ctrList,CStringArray & agList,int nList)
{
	int nFlashCount = agList.GetSize();
	for(int i= 0; i & lt; nFlashCount; i++)
	{
		CString strText = agList[i];
		if(strText.IsEmpty())
			continue;
		
		CString strBase;
		CString strSize;
		CString strFile;
		BOOL bCheck = FALSE;
		
		LPTSTR pBuf = strText.GetBuffer(1);
		LPTSTR pFind = _tcschr(pBuf,':');
		if(pFind != NULL)
		{
			*pFind = '\0';
			bCheck = GetDigit(pBuf);
			pBuf = pFind + 1;			
		}
		else
		{
			strText.ReleaseBuffer();			
			continue;
		}
		
		pFind = _tcschr(pBuf,':');
		if(pFind != NULL)
		{
			*pFind = '\0';
			strBase = pBuf;
			pBuf = pFind + 1;			
		}
		else
		{
			strText.ReleaseBuffer();
			continue;
		}
		
		pFind = _tcschr(pBuf,':');
		if(pFind != NULL)
		{
			*pFind = '\0';
			strSize = pBuf;
			pBuf = pFind + 1;			
		}
		else
		{
			if(nList == READ_FLASH || nList == ERASE_FLASH)
			{
				strText.ReleaseBuffer();
				continue;
			}
			
		}
		strFile = pBuf;
		
		int nCount = ctrList.GetItemCount();	
		if( /*!bCheck || */
		 ( nList == READ_FLASH & & !strBase.IsEmpty() & & !strSize.IsEmpty() & & !strFile.IsEmpty()) ||
		 ( nList == ERASE_FLASH & & !strBase.IsEmpty() & & !strSize.IsEmpty()) ||
		 ( nList == WRITE_FLASH & & !strBase.IsEmpty() & & !strFile.IsEmpty()) )
		{			
			ctrList.InsertItem(nCount,_T( " " ));
			ctrList.SetItemText(nCount,1,strBase);
			if(nList == READ_FLASH)
			{
				ctrList.SetItemText(nCount,2,strSize);
				ctrList.SetItemText(nCount,3,strFile);
			}
			else if(nList == ERASE_FLASH)
			{
				ctrList.SetItemText(nCount,2,strSize);
				ctrList.SetItemText(nCount,3,_T( " " ));
			}
			else if(nList == WRITE_FLASH)
			{
				ctrList.SetItemText(nCount,2,_T( " " ));
				ctrList.SetItemText(nCount,3,strFile);
			}			
			
			ctrList.SetCheck(nCount,bCheck);
		}
	}
	
	int nCount = ctrList.GetItemCount();
	if( nCount & gt; 0 & & ctrList.GetItemText(nCount-1,1).IsEmpty() & & 
		ctrList.GetItemText(nCount-1,2).IsEmpty() & & 
		ctrList.GetItemText(nCount-1,3).IsEmpty())
	{
		ctrList.DeleteItem(nCount-1);
	}
}
void CFlashOptPage::OnEraseClear() 
{
	// TODO: Add your control notification handler code here
	m_lstErase.DeleteAllItems();
}
void CFlashOptPage::OnWriteClear() 
{
	// TODO: Add your control notification handler code here
	m_lstWrite.DeleteAllItems();
}
void CFlashOptPage::InitList(CListCtrl & ctrList,int nList)
{
	ctrList.SetBkColor(RGB(232, 232, 232));	
	ctrList.ModifyStyle(0, LVS_SHOWSELALWAYS);
	
	DWORD dwExStyle = ctrList.GetExtendedStyle();
	dwExStyle |= LVS_EX_FULLROWSELECT;
	dwExStyle |= LVS_EX_GRIDLINES;
	dwExStyle |= LVS_EX_CHECKBOXES;
	
	ctrList.SetExtendedStyle(dwExStyle);
	
	//Load Column
	CString strClmn;
	VERIFY( strClmn.LoadString(IDS_READ_FLASH_LIST_COL) );
	
	int nLen = strClmn.GetLength();
	LPTSTR lpBuf = strClmn.GetBuffer(nLen);
	LPTSTR lpFind = _tcschr(lpBuf, _T(','));
	int nIndex = 0;
	while(lpFind != NULL)
	{
		*lpFind = _T('\0');
		if(nIndex == 0)
		{
			ctrList.InsertColumn(nIndex++,lpBuf,LVCFMT_LEFT,50);	
		}
		else
		{
			ctrList.InsertColumn(nIndex++,lpBuf,LVCFMT_LEFT,110);
		}
		lpBuf = lpFind + 1;
		lpFind = _tcschr(lpBuf, _T(','));
	}
	ctrList.InsertColumn(nIndex, lpBuf, LVCFMT_LEFT, 229 );
	strClmn.ReleaseBuffer();	
	LVCOLUMN col;	
	col.mask = LVCF_TEXT;
	col.pszText = NULL;	
	if(nList == ERASE_FLASH)
	{	
		ctrList.SetColumn(3, & col);
	}
	else if(nList == WRITE_FLASH)
	{
		ctrList.SetColumn(2, & col);
	}
}
void CFlashOptPage::OnChkActiveEraseFlash() 
{
	// TODO: Add your control notification handler code here
	UpdateData();
	if(m_bTmpActiveErase)
	{
		m_lstErase.EnableWindow(TRUE);
		GetDlgItem(IDC_FOD_BTN_DELE)- & gt; EnableWindow(TRUE);
	}
	else
	{
		m_lstErase.EnableWindow(FALSE);
		GetDlgItem(IDC_FOD_BTN_DELE)- & gt; EnableWindow(FALSE);
	}
}
void CFlashOptPage::OnChkActiveWriteFlash() 
{
	// TODO: Add your control notification handler code here
	UpdateData();
	if(m_bTmpActiveWrite)
	{
		m_lstWrite.EnableWindow(TRUE);
		GetDlgItem(IDC_FOD_BTN_DELW)- & gt; EnableWindow(TRUE);
	}
	else
	{
		m_lstWrite.EnableWindow(FALSE);
		GetDlgItem(IDC_FOD_BTN_DELW)- & gt; EnableWindow(FALSE);
	}
}
BOOL CFlashOptPage::LoadFlashOpr(LPCTSTR lpszSec, CStringArray & agList)
{
	agList.RemoveAll();
	_TCHAR szKeyValue[ MAX_BUF_SIZE ]={0}; 
GetPrivateProfileSection( lpszSec, szKeyValue, MAX_BUF_SIZE, m_strIniFile );
CStringArray arrKeyData; 
	UINT nFileCount = (UINT)EnumKeys(szKeyValue, & arrKeyData);
	for(UINT i= 0; i & lt; nFileCount; i++)
	{
		CString strText = arrKeyData[2*i+1];
		if(!strText.IsEmpty())
		{
			agList.Add(strText);
		}
	}
	return TRUE;
}
void CFlashOptPage::OnClickLstErase(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	ClickList(pNMHDR,m_lstErase,1);
	*pResult = 0;
}
void CFlashOptPage::OnClickLstWrite(NMHDR* pNMHDR, LRESULT* pResult) 
{
	// TODO: Add your control notification handler code here
	ClickList(pNMHDR,m_lstWrite,2);
	*pResult = 0;
}
//Layout.cpp
#include " stdafx.h " 
#include & lt; windowsx.h & gt; 
#include " Layout.h " 
#include & lt; malloc.h & gt; 
#if !defined(ASSERT)
#define ASSERT ATLASSERT
#endif
///////////////////////////////////////////////////////////////////////////////
// A MapDialogRect function that works for non-dialog windows.
BOOL adgMapDialogRect (HWND hwndParent, PRECT prc) {
	
	HDC hdc;
	SIZE size;
	int cxChar, cyChar;
	HFONT hfont=NULL, hfontOriginal=NULL;
	
	// This is the set of characters that Windows uses to compute the average
	// character width.
	static TCHAR szChars[] =
		__TEXT( " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " );
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(prc);
	
	// If the window is a dialog, just use MapDialogRect.
	if (GetClassWord(hwndParent, GCW_ATOM) == 32770)
		return(MapDialogRect(hwndParent, prc));
	
	// Get a device context and select the window's font into it.
	hdc = GetDC(hwndParent);
	hfont = GetWindowFont(hwndParent);
	if (hfont != NULL)
		hfontOriginal = SelectFont(hdc, hfont);
	
	// Unfortunately, we cannot use GetTextMetrics to get the average character
	// width because the TEXTMETRIC structure's tmAveCharWidth member is 
	// incorrect for proportional fonts. So, instead we compute the average
	// character width ourselves using the same technique employed by Windows
	// itself: We pass " a-zA-Z " to GetTextExtentPoint and average, rounding up.
	// (NOTE: We do not call GetTextExtentPoint32 because this function corrects
	// an error that Windows relies on)
	GetTextExtentPoint(hdc, szChars, adgARRAY_SIZE(szChars), & size);
	cyChar = size.cy;
	cxChar = ((size.cx / (adgARRAY_SIZE(szChars) / 2)) + 1) / 2;
	
	// Restore any original font and then release the device context.
	if (hfont != NULL)
		SelectFont(hdc, hfontOriginal);
	ReleaseDC(hwndParent, hdc);
	
	// Map rectangle prc based on the font dimensions (cxChar by cyChar).
	SetRect(prc, 
		prc- & gt; left * cxChar / 4, prc- & gt; top * cyChar / 8,
		prc- & gt; right * cxChar / 4, prc- & gt; bottom * cyChar / 8);
	return(TRUE);
}
int Layout_GetOppositeSide (int nSide) {
	
	int nOppositeSide=lpRIGHT;
	
	// Check assumptions.
	ASSERT(ISSIDE(nSide));
	
	switch (nSide) {
	case lpLEFT:
		nOppositeSide = lpRIGHT;
		break;
		
	case lpRIGHT:
		nOppositeSide = lpLEFT; 
		break;
		
	case lpTOP: 
		nOppositeSide = lpBOTTOM; 
		break;
		
	case lpBOTTOM: 
		nOppositeSide = lpTOP; 
		break;
		
	default: // Invalid side
		ASSERT(!__TEXT( " Invalid side " ));
		break;
	}
	return(nOppositeSide);
}
CHILD* Layout_FindChild (CHILD* pChildList, int idcChild) {
	
	CHILD *pChild;
	
	// Check assumptions.
	ASSERT(pChildList);
	ASSERT(adgINRANGE(0, idcChild, IDC_LASTCHILD));
	
	// Traverse the child list looking for an id
	for (pChild = pChildList; pChild- & gt; idc != IDC_LASTCHILD; pChild++) {
		
		// If we find idcChild, we solve the child for unknowns and return it
		if (pChild- & gt; idc == idcChild) {
			Layout_SolveChild(pChild);
			return(pChild);
		}
	}
	ASSERT(!__TEXT( " Child not found in child list " ));
	return(NULL);
}
CHILD* Layout_CreateChildList (HWND hwndParent, int* pnChildren) {
	
	int i;
	HWND hwnd, hwndFirst;
	CHILD* pChild, *pChildList;
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(pnChildren);
	
	// Count the number of child windows in hwndParent.
	hwndFirst = hwnd = GetFirstChild(hwndParent);
	for (*pnChildren = 0; IsWindow(hwnd); hwnd = GetNextSibling(hwnd)) 
		(*pnChildren)++;
	if (*pnChildren == 0)
		return(NULL);
	
	// Allocate memory for the CHILD list. This list will have an entry for
	// each child of the dialog, plus a CHILD structure for the parent window
	// (lPARENT) and one which acts as a list terminator (IDC_LASTCHILD).
	pChildList = (CHILD*)malloc((*pnChildren + 2) * sizeof(CHILD));
	ASSERT(pChildList);
	if (!pChildList)
		return(NULL);
	pChild = pChildList;
	
	// Add the special-case parent 'CHILD' structure
	pChild- & gt; idc = lPARENT;
	GetClientRect(hwndParent, & pChild- & gt; rc);
	for (i = 0; i & lt; NUMSIDES; i++)
		pChild- & gt; afMetric[i] = KNOWN;
	pChild- & gt; afMetric[lpWIDTH] = pChild- & gt; afMetric[lpHEIGHT] = UNKNOWN;
	Layout_SolveChild(pChild);
	pChild++;
	
	// Add all the real children of the dialog to the list
	hwnd = hwndFirst;
	for (; IsWindow(hwnd); hwnd = GetNextSibling(hwnd)) {
		
		// Get child's id and bounding rectangle in client coordinates
		pChild- & gt; idc = GetWindowID(hwnd);
		GetWindowRect(hwnd, & pChild- & gt; rc);
		MapWindowRect(HWND_DESKTOP, hwndParent, & pChild- & gt; rc);
		for (i = 0; i & lt; NUMSIDES; i++)
			pChild- & gt; afMetric[i] = KNOWN;
		
		// Solve for the width and height.
		pChild- & gt; afMetric[lpWIDTH] = pChild- & gt; afMetric[lpHEIGHT] = UNKNOWN;
		Layout_SolveChild(pChild);
		
		// All children are fixed, initially.
		pChild- & gt; fFixed = TRUE;
		pChild++;
	}
	
	// Terminate and return the list.
	pChild- & gt; idc = IDC_LASTCHILD;
	return(pChildList);
}
void Layout_ConvertDlgUnits (HWND hwndParent, RULE* pRules, CHILD* pChildList) {
	
	pChildList;
	RECT rc = { 0, 0, 0, 0 };
	BOOL fVertical=FALSE;
	RULE* pRule;
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(pRules);
	ASSERT(pChildList);
	
	// Traverse the rules list
	for (pRule = pRules; pRule- & gt; Action != lEND; pRule++) {
		
		// Simultaneously map the rule's offset value, vertically and
		// horizontally, from dialog units to pixels.
		rc.right = rc.bottom = pRule- & gt; nOffset;
		adgMapDialogRect(hwndParent, & rc);
		
		// Determine if the current rule affects horizontal or vertical
		// coordinates. We need to know this because dialog unit space is not
		// isometric (horizontal and vertical dialog units are not equivalent).
		switch (pRule- & gt; Action) {
			
		case lVCENTER:
fVertical = TRUE;
break;
			
		case lHCENTER:
fVertical = FALSE;
break;
			
		case lMOVE:
		case lSTRETCH:
fVertical = Layout_MetricIsVertical(pRule- & gt; ActOn.nMetric);
break;
			
		default:
ASSERT(!__TEXT( " Invalid action " ));
break;
		}
		
		// Take the correct mapped value based on the rule being applied
		pRule- & gt; nPixelOffset = fVertical ? rc.bottom : rc.right;
	} 
}
void Layout_MarkUnknowns (HWND hwndParent, RULE* pRules, CHILD* pChildList) {
	
	RULE* pRule;
	CHILD* pChildActOn;
	HWND hwnd;
	int nOtherUnknown, nOppositeSide, idc, idcFirst, idcLast;
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(pRules);
	ASSERT(pChildList);
	
	// Traverse the rule list, marking unknowns in the child list.
	for (pRule = pRules; pRule- & gt; Action != lEND; pRule++) {
		
		// Set metric flags based on the rule's proposed action
		switch (pRule- & gt; Action) {
			
		case lSTRETCH: // Metric should be stretched
			
// Find the child to be acted upon
pChildActOn = Layout_FindChild(pChildList, pRule- & gt; ActOn.idc);
ASSERT(pChildActOn);
			
// Since the child is going to be acted upon, it is no longer fixed.
pChildActOn- & gt; fFixed = FALSE;
			
// The part being acted on must be a metric.
ASSERT(ISMETRIC(pRule- & gt; ActOn.nMetric));
			
// The metric being stretched must be unknown.
pChildActOn- & gt; afMetric[pRule- & gt; ActOn.nMetric] = UNKNOWN;
			
// If the left/top or right/bottom is unknown, so is the
// width/height. If the width/height is unknown, then the
// right/bottom is also unknown.
nOtherUnknown = Layout_GetOtherUnknownMetric(pRule- & gt; ActOn.nMetric);
pChildActOn- & gt; afMetric[nOtherUnknown] = UNKNOWN;
break;
			
		case lMOVE: // Control should be moved
			
// Find the child to be acted upon
pChildActOn = Layout_FindChild(pChildList, pRule- & gt; ActOn.idc);
ASSERT(pChildActOn);
			
// Since the child is going to be acted upon, it is no longer fixed.
pChildActOn- & gt; fFixed = FALSE;
			
// The part being acted upon must be a side.
ASSERT(ISSIDE(pRule- & gt; ActOn.nSide));
			
// The side being moved is unknown.
pChildActOn- & gt; afMetric[pRule- & gt; ActOn.nSide] = UNKNOWN;
			
// So is the opposite side. But, the width/height remains known.
// (Actually, this is the primary reason for having six metrics).
nOppositeSide = Layout_GetOppositeSide(pRule- & gt; ActOn.nSide);
pChildActOn- & gt; afMetric[nOppositeSide] = UNKNOWN;
break;
			
		case lVCENTER: // Vertically center control/group
		case lHCENTER: // Horizontally center control/group
			
// We must be centering a group of one or more controls.
ASSERT(pRule- & gt; ActOn.nPart == lpGROUP);
			
// Go through the group of one or more controls
idcFirst = pRule- & gt; ActOn.idcFirst;
idcLast = pRule- & gt; ActOn.idcLast;
ASSERT(idcFirst & lt; = idcLast);
hwnd = GetFirstChild(hwndParent);
for (; IsWindow(hwnd); hwnd = GetNextSibling(hwnd)) {
				idc = GetWindowID(hwnd);
				if (adgINRANGE(idcFirst, idc, idcLast)) {
					
					// Find the child to be acted upon and set the appropriate
					// sides to unknown. Width is still known.
					pChildActOn = Layout_FindChild(pChildList, idc);
					if (pRule- & gt; Action == lHCENTER) {
						pChildActOn- & gt; afMetric[lpLEFT] = UNKNOWN;
						pChildActOn- & gt; afMetric[lpRIGHT] = UNKNOWN;
					} else {
						pChildActOn- & gt; afMetric[lpTOP] = UNKNOWN;
						pChildActOn- & gt; afMetric[lpBOTTOM] = UNKNOWN;
					}
					
					// Child acted upon is no longer fixed.
					pChildActOn- & gt; fFixed = FALSE;
				}
}
break;
			
		default:
ASSERT(!__TEXT( " Invalid action " ));
break;
		}
	}
}
int Layout_GetOtherUnknownMetric (int nUnknownMetric) {
	
	int nOtherUnknownMetric = 0;
	
	// Check assumptions.
	ASSERT(ISMETRIC(nUnknownMetric));
	
	switch (nUnknownMetric) {
	case lpLEFT:
	case lpRIGHT:
		nOtherUnknownMetric = lpWIDTH;
		break;
		
	case lpTOP: 
	case lpBOTTOM: 
		nOtherUnknownMetric = lpHEIGHT; 
		break;
		
	case lpWIDTH: 
		nOtherUnknownMetric = lpRIGHT; 
		break;
		
	case lpHEIGHT: 
		nOtherUnknownMetric = lpBOTTOM;
		break;
		
	default:
		ASSERT(!__TEXT( " Invalid metric " ));
		break;
	}
	return(nOtherUnknownMetric);
}
BOOL Layout_MetricIsVertical (int nMetric) {
	
	BOOL fMetricIsVertical = FALSE;
	
	// Check assumptions.
	ASSERT(ISMETRIC(nMetric));
	
	switch (nMetric) {
	case lpLEFT:
	case lpRIGHT:
	case lpWIDTH: 
		fMetricIsVertical = FALSE;
		break;
		
	case lpTOP: 
	case lpBOTTOM: 
	case lpHEIGHT: 
		fMetricIsVertical = TRUE;
		break;
		
	default:
		ASSERT(!__TEXT( " Invalid metric " ));
		break;
	}
	return(fMetricIsVertical);
}
void Layout_SolveChild (CHILD* pChild) {
	
	int i;
	
	// Check assumptions.
	ASSERT(pChild);
	
	// Loop through all six metrics of a child, computing values for unknown
	// metrics from values of known metrics (if any).
	for (i = 0; i & lt; NUMMETRICS; i++) {
		
		// If this metric of the child is unknown, see if it can be computed in
		// terms of other metrics which we do know.
		if (pChild- & gt; afMetric[i] == UNKNOWN) {
			
			// Compute left/top as right/bottom - width/height
			if (i & lt; 2) {
				if ((pChild- & gt; afMetric[i + 2] == KNOWN) & & 
					(pChild- & gt; afMetric[i + 4] == KNOWN)) {
					pChild- & gt; anMetric[i] = pChild- & gt; anMetric[i + 2] -
						pChild- & gt; anMetric[i + 4];
					pChild- & gt; afMetric[i] = KNOWN;
				}
			} 
			// Compute right/bottom as left/top + width/height
			else if (i & lt; 4) {
				if ((pChild- & gt; afMetric[i - 2] == KNOWN) & & 
					(pChild- & gt; afMetric[i + 2] == KNOWN)) {
					pChild- & gt; anMetric[i] = pChild- & gt; anMetric[i - 2] +
						pChild- & gt; anMetric[i + 2];
					pChild- & gt; afMetric[i] = KNOWN;
				}
			}
			// Compute width/height as right/bottom - left/top
			else {
				if ((pChild- & gt; afMetric[i - 2] == KNOWN) & & 
					(pChild- & gt; afMetric[i - 4] == KNOWN)) {
					pChild- & gt; anMetric[i] = pChild- & gt; anMetric[i - 2] -
						pChild- & gt; anMetric[i - 4];
					pChild- & gt; afMetric[i] = KNOWN;
				}
			}
		}
	}
}
BOOL Layout_CheckChild (CHILD* pChild) {
	
	static TCHAR* pszMetric[] = {
		__TEXT( " left " ), __TEXT( " top " ), __TEXT( " right " ),
			__TEXT( " bottom " ), __TEXT( " width " ), __TEXT( " height " )
	};
	
	int i;
	BOOL fOK = TRUE;
	TCHAR sz[80];
	
	// Check assumptions.
	ASSERT(pChild);
	
	// Any unknown metric indicates a problem with the rules, so we 'assert'.
	for (i = 0; i & lt; NUMMETRICS; i++) {
		if (pChild- & gt; afMetric[i] == UNKNOWN) {
			wsprintf(sz, __TEXT( " Layout couldn't find %s of id=%d " ),
				pszMetric[i], pChild- & gt; idc);
			adgMB(sz);
			fOK = FALSE;
		}
	}
	return(fOK);
}
BOOL Layout_ApplyRule (HWND hwndParent, RULE* pRules,
					 CHILD* pChildList, RULE* pRule) {
	
	CHILD* pChildRelTo, *pChildActOn, ChildRelTo;
	CHILD* pChild, *pChildListNew, *pSrc, *pDest;
	int nRules, nMetric, nChildren;
	int idcFirst, idcLast, nOffset, nCentered;
	RECT rcBounds;
	HWND hwnd, hwndFirst;
	RULE *pr, *prn, *prNew;
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(pRules);
	ASSERT(pChildList);
	ASSERT(pRule);
	
	// Find the child and part(s) that we are going to act relative to
	pChildRelTo = Layout_FindChild(pChildList, pRule- & gt; RelTo.idc);
	ASSERT(pChildRelTo);
	
	switch (pRule- & gt; RelTo.nPart) {
		
	case lpLEFT:
	case lpTOP:
	case lpRIGHT:
	case lpBOTTOM:
	case lpWIDTH:
	case lpHEIGHT:
		
		// We can't apply a rule relative to a metric that is unknown.
		if (pChildRelTo- & gt; afMetric[pRule- & gt; RelTo.nMetric] == UNKNOWN)
return(FALSE);
		break;
		
	case lpGROUP:
		
		// We can't apply a rule relative to a control unless we know its
		// left/top and right/bottom sides (for centering).
		ASSERT(pRule- & gt; RelTo.idcFirst == pRule- & gt; RelTo.idcLast);
		ASSERT((pRule- & gt; Action == lHCENTER) || (pRule- & gt; Action == lVCENTER));
		if (pRule- & gt; Action == lHCENTER) {
if ((pChildRelTo- & gt; afMetric[lpLEFT] == UNKNOWN) ||
(pChildRelTo- & gt; afMetric[lpRIGHT] == UNKNOWN))
				return(FALSE);
		} else {
if ((pChildRelTo- & gt; afMetric[lpTOP] == UNKNOWN) ||
(pChildRelTo- & gt; afMetric[lpBOTTOM] == UNKNOWN))
				return(FALSE);
		}
		break;
	}
	
	// Make a local copy of the child we are relative to. We need to do this
	// because we may need to apply a percentage to the width/height metrics
	// and we don't want to modify the actual child list.
	ChildRelTo = *pChildRelTo;
	
	// Use percentage to modify the width/height of the child we are relative to
	if ((pRule- & gt; RelTo.nMetric == lpWIDTH) || (pRule- & gt; RelTo.nMetric == lpHEIGHT)) {
		ChildRelTo.anMetric[pRule- & gt; RelTo.nMetric] *= pRule- & gt; RelTo.nPercent;
		ChildRelTo.anMetric[pRule- & gt; RelTo.nMetric] /= 100;
		Layout_SolveChild( & ChildRelTo);
	}
	
	// Apply our rule based on the action field
	switch (pRule- & gt; Action) {
		
	case lSTRETCH: // Metric should be stretched
		
		// The part being acted on must be a metric. If it is a width/height
		// metric, it must be 100% of the width/height.
		ASSERT(ISMETRIC(pRule- & gt; ActOn.nMetric));
		ASSERT(ISSIDE(pRule- & gt; ActOn.nSide) ||
(pRule- & gt; ActOn.nPercent == 100));
		
		// The part being acted relative to must be a metric.
		ASSERT(ISMETRIC(pRule- & gt; RelTo.nMetric));
		
		// Find the child being acted on and stretch the specified metric.
		pChildActOn = Layout_FindChild(pChildList, pRule- & gt; ActOn.idc);
		ASSERT(pChildActOn);
		pChildActOn- & gt; anMetric[pRule- & gt; ActOn.nMetric] =
ChildRelTo.anMetric[pRule- & gt; RelTo.nMetric] + pRule- & gt; nPixelOffset;
		pChildActOn- & gt; afMetric[pRule- & gt; ActOn.nMetric] = KNOWN;
		Layout_SolveChild(pChildActOn);
		pRule- & gt; fState = APPLIED;
		return(TRUE);
		
	case lMOVE: // Whole control should be moved
		
		// The part being moved must be a side.
		ASSERT(ISSIDE(pRule- & gt; ActOn.nSide));
		
		// The part that is being acted relative to must be a metric.
		ASSERT(ISMETRIC(pRule- & gt; RelTo.nMetric));
		
		// Find the child being acted on and move the specified side.
		pChildActOn = Layout_FindChild(pChildList, pRule- & gt; ActOn.idc);
		ASSERT(pChildActOn);
		pChildActOn- & gt; anMetric[pRule- & gt; ActOn.nSide] =
ChildRelTo.anMetric[pRule- & gt; RelTo.nMetric] + pRule- & gt; nPixelOffset;
		pChildActOn- & gt; afMetric[pRule- & gt; ActOn.nSide] = KNOWN;
		Layout_SolveChild(pChildActOn);
		pRule- & gt; fState = APPLIED;
		return(TRUE);
		
	case lVCENTER: // Vertically center a control/group
	case lHCENTER: // Horizontally center a control/group
		
		// We can only center a group of one or more controls relative to
		// another control (a single control is a 'group' of one control).
		ASSERT(pRule- & gt; ActOn.nPart == lpGROUP);
		ASSERT(pRule- & gt; RelTo.nPart == lpGROUP);
		ASSERT(pRule- & gt; RelTo.idcFirst == pRule- & gt; RelTo.idcLast);
		
		// First id in group must be less than or equal to the last id
		idcFirst = pRule- & gt; ActOn.idcFirst;
		idcLast = pRule- & gt; ActOn.idcLast;
		ASSERT(idcFirst & lt; = idcLast);
		
		// Ensure that the width/height is known for each control in the
		// group before proceeding with any centering.
		hwndFirst = GetFirstChild(hwndParent);
		for (hwnd = hwndFirst; IsWindow(hwnd); hwnd = GetNextSibling(hwnd)) {
int idc = GetWindowID(hwnd);
if (adgINRANGE(idcFirst, idc, idcLast)) {
				pChildActOn = Layout_FindChild(pChildList, idc);
				if (pRule- & gt; Action == lHCENTER) {
					if (pChildActOn- & gt; afMetric[lpWIDTH] == UNKNOWN)
						return(FALSE);
				} else {
					if (pChildActOn- & gt; afMetric[lpHEIGHT] == UNKNOWN)
						return(FALSE);
				}
}
		}
		
		// Create a new list of rules which contains the subset of rules
		// which act on controls in the centered group.
		for (nRules = 0, pr = pRules; pr- & gt; Action != lEND; pr++)
nRules++;
		nRules++;
		prNew = (RULE*)_alloca(nRules * sizeof(RULE));
		prn = prNew;
		for (pr = pRules; pr- & gt; Action != lEND; pr++) {
if (adgINRANGE(idcFirst, pr- & gt; ActOn.idc, idcLast)) {
				if (pRule- & gt; Action == lHCENTER) {
					if ((pr- & gt; ActOn.nPart == lpLEFT) || 
						(pr- & gt; ActOn.nPart == lpRIGHT)) {
						*prn++ = *pr;
					}
				} else {
					if ((pr- & gt; ActOn.nPart == lpTOP) ||
						(pr- & gt; ActOn.nPart == lpBOTTOM)) {
						*prn++ = *pr;
					}
				}
}
		}
		prn- & gt; Action = lEND;
		
		// Make a local copy of the child list and set everything to KNOWN.
		nChildren = 0;
		for (pChild = pChildList; pChild- & gt; idc != IDC_LASTCHILD; pChild++)
nChildren++;
		nChildren++;
		pChildListNew = (CHILD*)_alloca(nChildren * sizeof(CHILD));
		MoveMemory(pChildListNew, pChildList, nChildren * sizeof(CHILD));
		for (pChild = pChildListNew; pChild- & gt; idc != IDC_LASTCHILD; pChild++)
for (nMetric = 0; nMetric & lt; NUMMETRICS; nMetric++)
				pChild- & gt; afMetric[nMetric] = KNOWN;
			
			// Solve for the children being centered as a sub-problem.
			if (!Layout_ApplyRules (hwndParent, prNew, pChildListNew)) {
				ASSERT(!__TEXT( " Unable to apply rules to centered children " ));
				return(FALSE);
			}
			
			// Compute the bounding rectangle of the group
			SetRectEmpty( & rcBounds);
			hwndFirst = GetFirstChild(hwndParent);
			for (hwnd = hwndFirst; IsWindow(hwnd); hwnd = GetNextSibling(hwnd)) {
				int idc = GetWindowID(hwnd);
				if (adgINRANGE(idcFirst, idc, idcLast)) {
					pChildActOn = Layout_FindChild(pChildListNew, idc);
					UnionRect( & rcBounds, & rcBounds, & pChildActOn- & gt; rc);
				}
			}
			
			// Find the offset required to center the group's bounding rectangle
			// against the control we are relative to.
			if (pRule- & gt; Action == lHCENTER) {
				nCentered = ChildRelTo.anMetric[lpLEFT] + 
					((ChildRelTo.anMetric[lpWIDTH] -
					(rcBounds.right - rcBounds.left)) / 2);
				nOffset = nCentered - rcBounds.left;
			} else {
				nCentered = ChildRelTo.anMetric[lpTOP] + 
					((ChildRelTo.anMetric[lpHEIGHT] -
					(rcBounds.bottom - rcBounds.top)) / 2);
				nOffset = nCentered - rcBounds.top;
			}
			
			// Add in any additional offset from the rule.
			nOffset += pRule- & gt; nPixelOffset;
			
			// Go through the new child list, moving each control. 
			ASSERT(pRule- & gt; ActOn.idcFirst & lt; = pRule- & gt; ActOn.idcLast);
			for (hwnd = hwndFirst; IsWindow(hwnd); hwnd = GetNextSibling(hwnd)) {
				int idc = GetWindowID(hwnd);
				if (adgINRANGE(idcFirst, idc, idcLast)) { 
					pChildActOn = Layout_FindChild(pChildListNew, idc);
					if (pRule- & gt; Action == lHCENTER) {
						pChildActOn- & gt; anMetric[lpLEFT] += nOffset;
						pChildActOn- & gt; anMetric[lpRIGHT] += nOffset;
					} else {
						pChildActOn- & gt; anMetric[lpTOP] += nOffset;
						pChildActOn- & gt; anMetric[lpBOTTOM] += nOffset;
					}
				}
			}
			
			// Now modify the real child list based on pChildListNew.
			for (pSrc = pChildListNew, pDest = pChildList;
pSrc- & gt; idc != IDC_LASTCHILD; pSrc++, pDest++) {
				
				if (adgINRANGE(idcFirst, pSrc- & gt; idc, idcLast)) {
					if (pRule- & gt; Action == lHCENTER) {
						pDest- & gt; anMetric[lpLEFT] = pSrc- & gt; anMetric[lpLEFT];
						pDest- & gt; anMetric[lpRIGHT] = pSrc- & gt; anMetric[lpRIGHT];
						pDest- & gt; afMetric[lpLEFT] = KNOWN;
						pDest- & gt; afMetric[lpRIGHT] = KNOWN;
					} else {
						pDest- & gt; anMetric[lpTOP] = pSrc- & gt; anMetric[lpTOP];
						pDest- & gt; anMetric[lpBOTTOM] = pSrc- & gt; anMetric[lpBOTTOM];
						pDest- & gt; afMetric[lpTOP] = KNOWN;
						pDest- & gt; afMetric[lpBOTTOM] = KNOWN;
					}
				}
			}
			
			pRule- & gt; fState = APPLIED;
			return(TRUE);
			
default:
		 ASSERT(!__TEXT( " Invalid action " ));
		 return(FALSE);
}
}
BOOL Layout_ApplyRules (HWND hwndParent, RULE* pRules, CHILD* pChildList) { 
	
	RULE* pRule;
	BOOL fAppliedAtLeastOneRule, fOK = TRUE;
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(pRules);
	ASSERT(pChildList);
	
	// Based on the list of rules, mark all unknown child metrics as UNKNOWN.
	Layout_MarkUnknowns(hwndParent, pRules, pChildList);
	
	// Traverse the rule list, converting offsets from dialog units to pixels.
	Layout_ConvertDlgUnits(hwndParent, pRules, pChildList);
	
	// Mark all the rules as unapplied before attempting to apply them.
	for (pRule = pRules; pRule- & gt; Action != lEND; pRule++)
		pRule- & gt; fState = UNAPPLIED;
	
	// Loop through the rule list for as long as we are able to apply at least
	// one rule (if we make a pass through the entire list, and we are unable
	// to apply any rule, we are finished).
	do {
		fAppliedAtLeastOneRule = FALSE;
		for (pRule = pRules; pRule- & gt; Action != lEND; pRule++) {
			if (pRule- & gt; fState != APPLIED) {
				if (Layout_ApplyRule(hwndParent, pRules, pChildList, pRule))
					fAppliedAtLeastOneRule = TRUE;
			}
		}
	} while (fAppliedAtLeastOneRule);
	
	// Verify that all rules have been successfully applied.
	for (pRule = pRules; pRule- & gt; Action != lEND; pRule++) {
		ASSERT(pRule- & gt; fState == APPLIED);
		if (pRule- & gt; fState != APPLIED)
			fOK = FALSE;
	}
	return(fOK);
}
BOOL WINAPI Layout_ComputeLayout (HWND hwndParent, RULE* pRules) {
	
	HDWP hdwp;
	BOOL fOK = TRUE;
	CHILD* pChild, *pChildList;
	int nChildren;
	
	// Check assumptions.
	ASSERT(IsWindow(hwndParent));
	ASSERT(pRules);
	
	// Don't do anything to a minimized window.
	if (IsIconic(hwndParent))
		return(TRUE);
	
	// Enumerate all child windows of the dialog, allocating a CHILD structure
	// for each child, with all six metric flags set to KNOWN. To simplify
	// coding, we also add a special CHILD structure for the parent window with
	// the id lPARENT (defined in layout.h). If there are no children, or
	// memory cannot be allocated for the child list, we do nothing.
	pChildList = Layout_CreateChildList(hwndParent, & nChildren);
	if (pChildList == NULL)
		return(FALSE);
	if (nChildren == 0)
		return(TRUE);
	
	// Apply the rules from the rule list to solve for the locations of all the
	// child controls.
	
	if (!Layout_ApplyRules(hwndParent, pRules, pChildList)) {
		ASSERT(!__TEXT( " Unable to apply rules " ));
		return(FALSE);
	}
	
	
	// Simultaneously relocate all the children using DeferWindowPos.
	hdwp = BeginDeferWindowPos(0);
	ASSERT(hdwp);
	
	// Move each child in the CHILD list. We enumerate the child list starting
	// at pChildList + 1, because the first CHILD is lPARENT.
	for (pChild = pChildList + 1; pChild- & gt; idc != IDC_LASTCHILD; pChild++) {
		
		// Check child for any still-unsolved metrics. You may want to remove or
		// #ifdef out this check once your rules are known to be working.
		if (!Layout_CheckChild(pChild))
			fOK = FALSE;
		
		// Add child to DeferWindowPos list if it is not fixed.
		if (!pChild- & gt; fFixed) {
			HWND hwndChild = GetDlgItem(hwndParent, pChild- & gt; idc);
//			ASSERT(pChild- & gt; anMetric[lpWIDTH] & gt; = 0);
//			ASSERT(pChild- & gt; anMetric[lpHEIGHT] & gt; = 0);
			
			
			hdwp = DeferWindowPos(hdwp, hwndChild, NULL,
				pChild- & gt; anMetric[lpLEFT], pChild- & gt; anMetric[lpTOP], 
				pChild- & gt; anMetric[lpWIDTH], pChild- & gt; anMetric[lpHEIGHT],
				SWP_NOZORDER);
			ASSERT(hdwp);
			
			// Invalidation is necessary here because some controls (edit
			// controls in particular) don't repaint correctly under Windows NT
			// when they are moved with DeferWindowPos.
			InvalidateRect(hwndChild, NULL, TRUE);
		}
	}
	
	// It is this function call which actually moves all the windows.
	EndDeferWindowPos(hdwp);
	
	// Free the allocated list of CHILD structures
	free(pChildList);
	return(fOK);
}
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__FAD27263_5E57_4863_9DAB_A8D25896C813__INCLUDED_)
#define AFX_STDAFX_H__FAD27263_5E57_4863_9DAB_A8D25896C813__INCLUDED_
#if _MSC_VER & gt; 1000
#pragma once
#endif // _MSC_VER & gt; 1000
#define VC_EXTRALEAN		// Exclude rarely-used stuff from Windows headers
#include & lt; afxwin.h & gt; // MFC core and standard components
#include & lt; afxext.h & gt; // MFC extensions
#include & lt; afxcview.h & gt; 
#include & lt; afxdisp.h & gt; // MFC Automation classes
#include & lt; afxdtctl.h & gt; 		// MFC support for Internet Explorer 4 Common Controls
#include & lt; afxtempl.h & gt; 
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include & lt; afxcmn.h & gt; 			// MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
#include " Global.h " 
// Format of pSection
// " Key1 = data1\0Key2 = data2\0....Keyn = datan\0\0 " 
int EnumKeys(LPCTSTR pSection,CStringArray* pKeys);
long GetDigit(LPCTSTR lpszText);
void GetModuleFilePath( HMODULE hModule, LPTSTR lpszAppPath );
BOOL CreateDeepDirectory(LPCTSTR lpszDir);
BOOL GetFilePathInfo(LPCTSTR lpszFile, CStringArray & agInfo);
int SplitStr(LPCTSTR lpszStr,CStringArray & agStrs,TCHAR chSeparate = _T(','));
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__FAD27263_5E57_4863_9DAB_A8D25896C813__INCLUDED_)
#if !defined(AFX_EDITEX_H__491E6B45_E6B4_42AC_BFC0_6579B8EBF1F3__INCLUDED_)
#define AFX_EDITEX_H__491E6B45_E6B4_42AC_BFC0_6579B8EBF1F3__INCLUDED_
#if _MSC_VER & gt; 1000
#pragma once
#endif // _MSC_VER & gt; 1000
// EditEx.h : header file
//
enum {
	EX_FMT_NORMAL,
	EX_FMT_DEC,
	EX_FMT_HEX,
	EX_FMT_MAX
};
/////////////////////////////////////////////////////////////////////////////
// CEditEx window
class CEditEx : public CEdit
{
// Construction
public:
	CEditEx();
void SetFmtMode(UINT nMode);
long GetDigit();
// Attributes
protected:
// When you want to change the
// edit content,m_strOldText contains
// the current content of the edit
CString m_strOldText;
// If your input is invalid,the content will
// be restore.m_bReturn is used to avoid enter
// the update function again
BOOL m_bReturn;
// Operations
public:
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CEditEx)
	//}}AFX_VIRTUAL
// Implementation
public:
	virtual ~CEditEx();
	// Generated message map functions
protected:
	//{{AFX_MSG(CEditEx)
	//afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
	afx_msg void OnUpdate();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
private:
	UINT m_nFmtMode;
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_EDITEX_H__491E6B45_E6B4_42AC_BFC0_6579B8EBF1F3__INCLUDED_)
#if !defined(AFX_DLGPACKETSETTING_H__C0B7BCE4_4BCD_4F12_9452_20F13E53194B__INCLUDED_)
#define AFX_DLGPACKETSETTING_H__C0B7BCE4_4BCD_4F12_9452_20F13E53194B__INCLUDED_
#if _MSC_VER & gt; 1000
#pragma once
#endif // _MSC_VER & gt; 1000
// DlgPacketSetting.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CDlgPacketSetting dialog
class CDlgPacketSetting : public CDialog
{
// Construction
public:
	CDlgPacketSetting(CWnd* pParent = NULL); // standard constructor
// Dialog Data
	//{{AFX_DATA(CDlgPacketSetting)
	enum { IDD = IDD_DLG_PAKET_SETTING };
	CEdit	m_edtPrdAlias;
	CEdit	m_edtVersion;
	CEdit	m_edtPath;
	CString	m_strPath;
	CString	m_strVersion;
	CString	m_strPrdName;
	CString	m_strPrdAlias;
	//}}AFX_DATA
// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CDlgPacketSetting)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
	//}}AFX_VIRTUAL
// Implementation
protected:
	// Generated message map functions
	//{{AFX_MSG(CDlgPacketSetting)
	virtual void OnOK();
	afx_msg void OnBtnBrowse();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_DLGPACKETSETTING_H__C0B7BCE4_4BCD_4F12_9452_20F13E53194B__INCLUDED_)
// FileDlg.h: interface for the CFileDlg class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FILEDLG_H__32FC0DB1_80B1_484A_B696_F14CEA1C38D8__INCLUDED_)
#define AFX_FILEDLG_H__32FC0DB1_80B1_484A_B696_F14CEA1C38D8__INCLUDED_
#if _MSC_VER & gt; 1000
#pragma once
#endif // _MSC_VER & gt; 1000
// µ¯³ö¶Ô»°¿ò£¬ÊµÏÖÎļþºÍĿ¼ѡÔñ¹¦ÄÜ£¬¿É²Î¿¼MFCµÄCFileDialogµÄʵÏֺͰïÖú
class CFileDlg 
{
public:
void SetFileFilter( LPCTSTR pszFilter ) { m_strFilter = pszFilter; }
void SetFileExt( LPCTSTR pszExt ) { m_strExt = pszExt; }
	void SetHwnOwner(HWND hwnd) {m_hwndOwner = hwnd;}
// »ñÈ¡ÎļþµÄ·¾¶Ãû£¬Èç¹ûÎļþ²»´æÔÚ£¬·µ»ØÎª¿Õ( " " )
CString GetPathName(void);
// »ñȡĿ¼£¬Ä¿Â¼²»´æÔÚ·µ»ØÖµÎª¿Õ( " " )£¬Ä¿Â¼ÃûµÄ×îºó²»º¬\ " 
CString GetSelectDir();
public:
	CFileDlg(BOOL bOpen = TRUE);
	~CFileDlg();
private:
static int CALLBACK BrowseProc( HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData );
CString m_strFilter;
CString m_strExt;
HWND m_hwndOwner;
BOOL m_bOpen;
static _TCHAR SZ_SEL_DIR[ _MAX_PATH ];
};
#endif // !defined(AFX_FILEDLG_H__32FC0DB1_80B1_484A_B696_F14CEA1C38D8__INCLUDED_)