www.pudn.com > isee_code01231.zip > CurModule.cpp


// CurModule.cpp : Defines the initialization routines for the DLL. 
// 
 
#include "stdafx.h" 
#include "CurModule.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
static char ModuleProcessImgType[]="CUR";			// 本模块能处理的图像类型 
static char WriterList[]="YZ";						// 本模块的作者列表 
static char WriterMess[]="Hello!!! 这里光标的给^_^";// 作者留言 
 
// 
//	Note! 
// 
//		If this DLL is dynamically linked against the MFC 
//		DLLs, any functions exported from this DLL which 
//		call into MFC must have the AFX_MANAGE_STATE macro 
//		added at the very beginning of the function. 
// 
//		For example: 
// 
//		extern "C" BOOL PASCAL EXPORT ExportedFunction() 
//		{ 
//			AFX_MANAGE_STATE(AfxGetStaticModuleState()); 
//			// normal function body here 
//		} 
// 
//		It is very important that this macro appear in each 
//		function, prior to any calls into MFC.  This means that 
//		it must appear as the first statement within the  
//		function, even before any object variable declarations 
//		as their constructors may generate calls into the MFC 
//		DLL. 
// 
//		Please see MFC Technical Notes 33 and 58 for additional 
//		details. 
// 
 
//		在图像读写模块中,如果想分配内存,请使用API函数GlobalAlloc() 
//		,如果想释放内存请使用GlobalFree()函数。不要使用诸如:new 
//		、malloc()等函数。这是为了使各模块之间可以异地释放内存。 
// 
// 
 
///////////////////////////////////////////////////////////////////////////// 
// CIcoModuleApp 
 
BEGIN_MESSAGE_MAP(CCurModuleApp, CWinApp) 
	//{{AFX_MSG_MAP(CIcoModuleApp) 
		// NOTE - the ClassWizard will add and remove mapping macros here. 
		//    DO NOT EDIT what you see in these blocks of generated code! 
	//}}AFX_MSG_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CIcoModuleApp construction 
 
CCurModuleApp::CCurModuleApp() 
{ 
	// TODO: add construction code here, 
	// Place all significant initialization in InitInstance 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// The one and only CIcoModuleApp object 
 
CCurModuleApp theApp; 
 
// 接口函数声明 — 第一层,唯一与外界联系的接口 
int WINAPI AccessCURModule(INFOSTR *pInfo) 
{ 
	// 这个函数可以不作修改的使用,除非你的返回值多于两种。 
 
	switch(pInfo->comm) 
	{ 
	case	CMD_GETPROCTYPE:	// 获取本模块能处理的图像类型 
		_fnCMD_GETPROCTYPE(pInfo); 
		break; 
	case	CMD_GETWRITERS:		// 获取本模块的作者列表,多人时用逗号分隔 
		_fnCMD_GETWRITERS(pInfo); 
		break; 
	case	CMD_GETWRITERMESS:	// 获取作者们的留言 
		_fnCMD_GETWRITERMESS(pInfo); 
		break; 
	case	CMD_GETBUILDID:		// 获取图像模块内部版本号 
		_fnCMD_GETBUILDID(pInfo); 
		break; 
	case	CMD_IS_VALID_FILE:	// 判断指定文件是否是有效的WMF文件 
		_fnCMD_IS_VALID_FILE(pInfo); 
		break; 
	case	CMD_GET_FILE_INFO:	// 获取指定文件的信息 
		_fnCMD_GET_FILE_INFO(pInfo); 
		break; 
	case	CMD_LOAD_FROM_FILE:	// 从指定图像文件中读取数据 
		_fnCMD_LOAD_FROM_FILE(pInfo); 
		break; 
	case	CMD_SAVE_TO_FILE:	// 将数据保存到指定文件中 
		_fnCMD_SAVE_TO_FILE(pInfo); 
		break; 
	case	CMD_IS_SUPPORT:		// 查询某个命令是否被支持 
		_fnCMD_IS_SUPPORT(pInfo); 
		break; 
	case	CMD_RESIZE:			// 从新获取指定尺寸的图像位数据(只适用于矢量图像) 
		_fnCMD_RESIZE(pInfo); 
		break; 
	default: 
		pInfo->result = ER_ILLCOMM; // 非法命令 
		ASSERT(FALSE);			// 调用者的程序设计有问题 :-) 
		break; 
	} 
 
	// 执行命令成功返回1, 失败返回0 
	return (pInfo->result==ER_SUCCESS)? 1:0; 
} 
 
 
 
 
 
// 命令解释函数 — 第二层解释函数 
//********************************************************************// 
 
// 操作命令解释函数---解释:CMD_IS_SUPPORT命令 
// 查询某个命令是否被支持 
void _fnCMD_IS_SUPPORT(INFOSTR *pInfo) 
{ 
	// 这个函数是为客户程序查询时使用,如果你实现了对某个命令的 
	// 解释,可修改相应的case中的设置,使其返回ER_SUCCESS,这就 
	// 表示你的模块已经支持该命令了。同时,现在的这个文件中已包 
	// 含了对前四个命令的解释,你只需向还未支持的命令函数中添加 
	// 代码即可。 
 
	ASSERT(pInfo->result == ER_EMPTY); 
 
	switch(pInfo->annexdata.cmAnnData)		  
	{ 
	case	CMD_GETPROCTYPE:	// 获取本模块能处理的图像类型 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_GETWRITERS:		// 获取本模块的作者列表,多人时用逗号分隔 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_GETWRITERMESS:	// 获取作者们的留言 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_GETBUILDID:		// 获取图像模块内部版本号 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_IS_VALID_FILE:	// 判断指定文件是否是有效的CUR文件 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_GET_FILE_INFO:	// 获取指定文件的信息 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_LOAD_FROM_FILE:	// 从指定图像文件中读取数据 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_SAVE_TO_FILE:	// 将数据保存到指定文件中 
		pInfo->result = ER_NOTSUPPORT; 
		break; 
	case	CMD_IS_SUPPORT:		// 查询某个命令是否被支持 
		pInfo->result = ER_SUCCESS; 
		break; 
	case	CMD_RESIZE:			// 获取指定尺寸的图像(只适用于矢量图像) 
		pInfo->result = ER_NOTSUPPORT; 
		break; 
	default: 
		pInfo->result = ER_NOTSUPPORT; 
		break; 
	} 
} 
 
 
// 操作命令解释函数---解释:CMD_GETPROCTYPE命令 
// 获取本模块能处理的图像类型,如:BMP,PCX等等 
void _fnCMD_GETPROCTYPE(INFOSTR *pInfo) 
{ 
	// 这是预定义的函数代码,你可以不必修改的使用。 
 
	// 根据接口定义,此时附加数据应被清空为0,所以下此断言 
	ASSERT(pInfo->annexdata.scAnnData[0] == 0); 
	ASSERT(pInfo->result == ER_EMPTY); 
	// 复制能处理的类型字符串 
	::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)ModuleProcessImgType,  
		sizeof(ModuleProcessImgType)); 
 
	pInfo->result = ER_SUCCESS; 
} 
 
 
 
// 操作命令解释函数---解释:CMD_GETWRITER命令 
// 获取本模块的作者列表,多人时用逗号分隔 
void _fnCMD_GETWRITERS(INFOSTR *pInfo) 
{ 
	// 这是预定义的函数代码,你可以不必修改的使用。 
 
	// 根据接口定义,此时附加数据应被清空为0,所以下此断言 
	ASSERT(pInfo->annexdata.scAnnData[0] == 0); 
	ASSERT(pInfo->result == ER_EMPTY); 
	// 复制开发者名单串 
	::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterList,  
		sizeof(WriterList)); 
 
	pInfo->result = ER_SUCCESS; 
} 
 
 
// 操作命令解释函数---解释:CMD_GETWRITERMESS命令 
// 获取作者们的留言 
void _fnCMD_GETWRITERMESS(INFOSTR *pInfo) 
{ 
	// 这是预定义的函数代码,你可以不必修改的使用。 
 
	// 根据接口定义,此时附加数据应被清空为0,所以下此断言 
	ASSERT(pInfo->annexdata.scAnnData[0] == 0); 
	ASSERT(pInfo->result == ER_EMPTY); 
	// 复制开发者们的留言字符串 
	::CopyMemory((PVOID)pInfo->annexdata.scAnnData, (PVOID)WriterMess,  
		sizeof(WriterMess)); 
 
	pInfo->result = ER_SUCCESS; 
} 
 
 
 
// 操作命令解释函数---解释:CMD_GETBUILDID命令 
// 获取图像模块内部版本号 
void _fnCMD_GETBUILDID(INFOSTR *pInfo) 
{ 
	// 这是预定义的函数代码,你可以不必修改的使用。 
 
	// 根据接口定义,此时annexdata.dwAnnData应被设为0,所以下此断言 
	ASSERT(pInfo->annexdata.dwAnnData == 0); 
	ASSERT(pInfo->result == ER_EMPTY); 
	// 填写内部版本号码 
	pInfo->annexdata.dwAnnData = MODULE_BUILDID; 
 
	pInfo->result = ER_SUCCESS; 
} 
 
 
 
// 操作命令解释函数---解释:CMD_IS_VALID_FILE命令 
// 判断指定文件是否是有效的CUR文件 
void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo) 
{ 
	CFile file; 
	ICONDIR icondir; 
	DWORD dwSize; 
	UINT uRet; 
 
	// 检验入口参数是否符合接口定义 
	ASSERT(pInfo->result == ER_EMPTY); 
	ASSERT(pInfo->annexdata.iAnnData == 0); 
	ASSERT(::strlen(pInfo->filename)); 
	ASSERT(pInfo->state == PKST_NOTVER); 
 
	ASSERT(pInfo); 
 
	// 设初值 
	pInfo->result = ER_SUCCESS; 
	pInfo->annexdata.iAnnData = 0;	 
 
	// 先判断指定的文件是否存在 
	if (!IsFileExist(pInfo->filename)) 
		pInfo->result = ER_COMMINFOERR; 
	else 
	{ 
		// 打开指定文件 
		if (!file.Open(pInfo->filename, CFile::modeRead)) 
		{ 
			pInfo->result = ER_FILERWERR;	// 打开文件时出错 
			return; 
		} 
 
		// 获取文件的长度(以字节为单位) 
		dwSize = file.GetLength(); 
 
		// 用长度判断 
		if (dwSize < sizeof(ICONDIR)) 
		{ 
			// 这不是一个光标文件,光标文件的长度起码大于图标目录 
			// 结构的长度 
			file.Close();					 
			return; 
		} 
 
		// 读取光标文件信息头结构,并检查它的有效性 
		file.SeekToBegin(); 
		uRet  = file.Read((LPSTR)&icondir, sizeof(ICONDIR)); 
		if (uRet != sizeof(ICONDIR)) 
		{ 
			// 读文件时出错 
			pInfo->result = ER_FILERWERR;	 
			file.Close(); 
			return; 
		} 
 
		// 判断文件标志 
		if ((icondir.idReserved != 0)||(icondir.idType != CURTYPE)) 
		{ 
			file.Close();					 
			return; 
		} 
 
		// 起码应该有一幅图像 
		if (icondir.idCount < 1)	 
		{ 
			file.Close();					 
			return; 
		} 
		 
		// 到此,大致可以表明该文件是一个有效的ICO文件,iAnnData变量设为1 
		pInfo->annexdata.iAnnData = 1; 
		// 表示通过校验 
		pInfo->state = PKST_PASSVER;	 
 
		file.Close(); 
	} 
} 
 
 
 
 
// 操作命令解释函数---解释:CMD_GET_FILE_INFO命令 
// 获取指定文件的信息 
void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo) 
{ 
	CFile file; 
	CFileStatus	status; 
	LPICONDIR lpIR; 
	LPIMGINFO lpII; 
	UINT i; 
	SIZE size; 
 
	// 检验入口参数是否符合接口定义 
	ASSERT(pInfo->result == ER_EMPTY); 
	ASSERT(::strlen(pInfo->filename)); 
	// 此时,该文件必需是一个已存在的、并且是有效的ICO文件 
	ASSERT(pInfo->state == PKST_PASSVER); 
	// 客户模块必需要先将imginfo清空为0 
	ASSERT(pInfo->imginfo.imgtype == IMT_NULL); 
 
	// 打开指定文件 
	if (!file.Open(pInfo->filename, CFile::modeRead)) 
	{ 
		pInfo->result = ER_FILERWERR; 
		return; 
	} 
 
	// 读取ICO文件的信息 
	if ((lpIR = ReadIconInfo(file)) == NULL) 
	{ 
		// 因读文件时出错或内存不足而调用失败 
		file.Close(); 
		// 此处只能写一种错误原因,因为读盘失败的 
		// 可能性比较大,所以写了读写文件错的代码 
		pInfo->result = ER_FILERWERR; 
		return; 
	} 
 
	// 分配图像信息结构所需空间 
	lpII = (LPIMGINFO)::GlobalAlloc(GPTR, lpIR->idCount*sizeof(IMGINFO)); 
	if (!lpII) 
	{ 
		::GlobalFree((void*)lpIR); 
		file.Close(); 
		pInfo->result = ER_MEMORYERR; 
		return; 
	} 
	 
	// 获取图标中每一副图像的尺寸数据 
	for (i=0;iidCount;i++) 
	{ 
		lpII[i].index = i; 
		_get_image_info(lpIR, i, (LPSIZE)&(lpII[i].imgsize), (int*)&(lpII[i].colnum)); 
		_get_string_info((LPSIZE)&(lpII[i].imgsize), lpII[i].colnum, lpII[i].string, (LPSIZE)&(lpII[i].txtsize)); 
	} 
 
	// 对图像结构数组进行排序(以图像宽度从小到大,:-) 
	_do_sort(lpIR->idCount, lpII); 
 
	// 获得图标综合图像尺寸 
	_get_synthesis_imgsize(lpIR->idCount, lpII, &size); 
 
 
	LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo; 
 
	// 获取文件的长度、图像的宽度、高度等信息 
	lpImgInfoStr->imgtype = IMT_RESSTATIC; 
	lpImgInfoStr->imgformat = IMF_ICO; 
	lpImgInfoStr->filesize = file.GetLength(); 
	// 以下的宽度、高度是指综合图像的宽、高 
	lpImgInfoStr->width = size.cx; 
	lpImgInfoStr->height = size.cy; 
	// 因为这是综合图像的位深,所以锁定为32位 
	lpImgInfoStr->bitcount = 32; 
	lpImgInfoStr->compression = ICS_RGB; 
	// 每一图像行所占的字节数(DWORD对齐,并且只对非压缩位图有效) 
	lpImgInfoStr->linesize = WIDTHBYTES(size.cx*32); 
	lpImgInfoStr->imgnumbers = 1; 
	// 表示不可编辑 
	lpImgInfoStr->imgchang = 1;		 
 
	// 获取文件最后的修改日期(月在高字节,日在低字节) 
	file.GetStatus(status); 
	lpImgInfoStr->year = (WORD)status.m_mtime.GetYear(); 
	lpImgInfoStr->monday = (WORD)status.m_mtime.GetMonth(); 
	lpImgInfoStr->monday <<= 8; 
	lpImgInfoStr->monday |= (WORD)status.m_mtime.GetDay(); 
 
	// 获取文件最后的修改时间(字序:最高—0, 2—时,1—分,0—秒) 
	lpImgInfoStr->time = status.m_mtime.GetHour(); 
	lpImgInfoStr->time <<= 8; 
	lpImgInfoStr->time |= status.m_mtime.GetMinute(); 
	lpImgInfoStr->time <<= 8; 
	lpImgInfoStr->time |= status.m_mtime.GetSecond(); 
	lpImgInfoStr->time &= 0xffffff; 
 
	::GlobalFree((void*)lpII); 
	::GlobalFree((void*)lpIR); 
 
	file.Close(); 
 
	// 设置出口数据 
	pInfo->state = PKST_PASSINFO; 
	pInfo->result = ER_SUCCESS; 
 
	return; 
} 
 
 
 
// 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令 
// 从指定图像文件中读取数据 
void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo) 
{ 
	// 检验入口参数是否符合接口定义 
	ASSERT(pInfo->result == ER_EMPTY); 
	ASSERT(::strlen(pInfo->filename)); 
	// 此时,该文件必需是一个已存在的、有效的ICO文件,并且数据包中 
	// 含有该文件的信息(imginfo结构中) 
	ASSERT(pInfo->state == PKST_PASSINFO); 
	ASSERT(pInfo->imginfo.imgformat == IMF_ICO); 
	ASSERT(pInfo->pImgInfo == NULL); 
	// 必需设置标准图像格式信息 
	ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER)); 
	ASSERT(pInfo->pLineAddr != NULL); 
	ASSERT(pInfo->_pbdata != NULL); 
 
	CFile file; 
	LPICONDIR lpIR; 
	LPIMGINFO lpII; 
	UINT i; 
 
	if (pInfo->fpProgress) 
	{ 
		if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 6)) 
		{	// 如果进度函数返回1,则说明用户想中断操作,返回。 
			pInfo->result = ER_USERBREAK; 
			return; 
		} 
	} 
 
	// 打开指定文件 
	if (!file.Open(pInfo->filename, CFile::modeRead)) 
	{ 
		pInfo->result = ER_FILERWERR; 
		return; 
	} 
	file.Seek(0, CFile::begin); 
 
	// 读取ICO文件的信息 
	if ((lpIR = ReadIconInfo(file)) == NULL) 
	{ 
		// 因读文件时出错或内存不足而调用失败 
		file.Close(); 
		// 此处只能写一种错误原因,因为读盘失败的 
		// 可能性比较大,所以写了读写文件错的代码 
		pInfo->result = ER_FILERWERR; 
		return; 
	} 
 
	// 分配图像信息结构所需空间 
	lpII = (LPIMGINFO)::GlobalAlloc(GPTR, lpIR->idCount*sizeof(IMGINFO)); 
	if (!lpII) 
	{ 
		::GlobalFree((void*)lpIR); 
		file.Close(); 
		pInfo->result = ER_MEMORYERR; 
		return; 
	} 
	 
	// 获取图标中每一副图像的尺寸数据 
	for (i=0;iidCount;i++) 
	{ 
		lpII[i].index = i; 
		_get_image_info(lpIR, i, (LPSIZE)&(lpII[i].imgsize), (int*)&(lpII[i].colnum)); 
		_get_string_info((LPSIZE)&(lpII[i].imgsize), lpII[i].colnum, lpII[i].string, (LPSIZE)&(lpII[i].txtsize)); 
	} 
 
	// 对图像结构数组进行排序(以图像宽度从小到大,:-) 
	_do_sort(lpIR->idCount, lpII); 
 
	PBYTE lpBits; 
	HBITMAP hBmp; 
	HBITMAP hCurBmp; 
	RECT	rect; 
	HWND hWnd = ::GetDesktopWindow(); 
	HDC hDC = ::GetDC(hWnd); 
 
	hBmp = CreateDIBSection(hDC, (LPBITMAPINFO)&(pInfo->sDIBInfo),  
		DIB_RGB_COLORS, (void**)&lpBits, NULL, 0); 
	if (hBmp == NULL) 
	{ 
		::GlobalFree((void*)lpIR); 
		::GlobalFree((void*)lpII); 
		file.Close(); 
		::ReleaseDC(hWnd, hDC); 
		pInfo->result = ER_SYSERR; 
		return;		// 操作系统不稳定 
	} 
 
	// 将图像的背景色设置为白 
	HDC hMemDC = ::CreateCompatibleDC(hDC); 
	HDC hSouDC = ::CreateCompatibleDC(hDC); 
	HBITMAP hOldSouBmp; 
	HBITMAP hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBmp); 
	rect.left = 0; rect.top = 0; rect.right = pInfo->imginfo.width; 
	rect.bottom = pInfo->imginfo.height; 
	// 将图像的背景填充为系统定义的白色 
	::FillRect(hMemDC, (CONST RECT*)&rect, (HBRUSH)::GetStockObject(WHITE_BRUSH)); 
 
 
	int currentimg;					// 当前待处理的图像 
	int currentheight = BORDERSPEC;	// 当前高度行坐标 
	int mp = pInfo->imginfo.width/2;// 中点X坐标 
	int ul, ut, dr, db; 
 
	for (i=0;iidCount;i++) 
	{ 
		currentimg = lpII[i].index; 
 
		ul = mp-lpII[i].imgsize.cx/2; 
		ut = currentheight; 
		dr = ul+lpII[i].imgsize.cx; 
		db = ut+lpII[i].imgsize.cy; 
 
		// 获得图标文件中的指定图像 
		hCurBmp = _get_hbmp(file, lpIR, lpII, i); 
		if (!hCurBmp) 
		{ 
			::SelectObject(hMemDC, hOldBmp); 
			::DeleteDC(hSouDC); 
			::DeleteDC(hMemDC); 
			::ReleaseDC(hWnd, hDC); 
 
			::GlobalFree((void*)lpIR); 
			::GlobalFree((void*)lpII); 
			::DeleteObject(hBmp); 
			file.Close(); 
			pInfo->result = ER_SYSERR;	// 操作系统不稳定 
			return; 
		} 
 
		// 将图像复制到主位图中 
		hOldSouBmp = (HBITMAP)::SelectObject(hSouDC, hCurBmp); 
		::BitBlt(hMemDC, ul, ut, dr-ul, db-ut, hSouDC, 0, 0, SRCCOPY); 
		::SelectObject(hSouDC, hOldSouBmp); 
		::DeleteObject(hCurBmp); 
		 
		currentheight += lpII[i].imgsize.cy; 
		currentheight += IMGTXTSPEC; 
 
		// 计算字符串的显示位置 
		ul = mp-lpII[i].txtsize.cx/2; 
		ut = currentheight; 
		dr = ul+lpII[i].txtsize.cx; 
		db = ut+lpII[i].txtsize.cy; 
		rect.left = ul; rect.top = ut; rect.right = dr; rect.bottom = db; 
 
		// 绘制图标的描述字符串 
		::DrawText(hMemDC, lpII[i].string, lstrlen(lpII[i].string),  
			(RECT*)&rect, DT_SINGLELINE|DT_CENTER|DT_NOCLIP); 
 
		currentheight += lpII[i].txtsize.cy; 
		currentheight += TXTIMGSPEC; 
	} 
 
	::SelectObject(hMemDC, hOldBmp); 
	::DeleteDC(hSouDC); 
	::DeleteDC(hMemDC); 
	::ReleaseDC(hWnd, hDC); 
 
	// 将图像复制到数据包中 
	::memmove((void*)pInfo->_pbdata, (const void*)lpBits,  
		WIDTHBYTES(pInfo->sDIBInfo.bmi.biWidth*pInfo->sDIBInfo.bmi.biBitCount)*pInfo->imginfo.height); 
 
	::DeleteObject(hBmp); 
 
	::GlobalFree((void*)lpII); 
	::GlobalFree((void*)lpIR); 
	file.Close(); 
 
	// 执行成功 
	pInfo->state = PKST_INFOANDBITS; 
	pInfo->modify = 0; 
	pInfo->result = ER_SUCCESS; 
 
	if (pInfo->fpProgress)	// 结束进度条,此调用不再支持用户中断 
		(*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE); 
} 
 
 
 
// 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令 
// 将数据保存到指定文件中 
void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo) 
{ 
	// 这个命令不一定要解释,你可以参考本图像格式的具体境况来决定 
	// 是否解释该命令。 
	// 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值: 
	// -----------------------------------------------------------------> 
 
	pInfo->result = ER_NOTSUPPORT; 
} 
 
 
 
 
// 操作命令解释函数---解释:CMD_RESIZE命令 
// 重新获取指定尺寸的图像位数据(只适用于矢量图像) 
void _fnCMD_RESIZE(INFOSTR *pInfo) 
{ 
	// 这个命令一般的图像读写模块不需要支持,它只适用于矢量图像, 
	// 比如WMF、EMF之类。 
	// 如果你想解释该命令,请在下面加入代码,并修改pInfo->result的返回值: 
	// -----------------------------------------------------------------> 
 
	pInfo->result = ER_NOTSUPPORT; 
} 
 
 
 
 
/************************************************************************* 
 * 
 * IsFileExist() 
 *  
 * 参数说明: 
 * 
 * char *lpFileName		- 待判断的文件路径和名称(文件名) 
 * 
 * 返回值: 
 * 
 * BOOL					- 如果指定的文件存在返回TRUE,否则返回FALSE。 
 *  
 * 描述: 
 * 
 * 判断指定的文件是否存在 
 *  
 * 该文件必需可以被读和写 
 * 
 ************************************************************************/ 
 
 
BOOL IsFileExist(char *lpFileName) 
{ 
	CFile	file; 
	BOOL	bExist = FALSE;	// 文件存在是TRUE,不存在是FALSE 
	CFileException	e; 
 
	// 确定指定的文件是否存在 
	if (file.Open(lpFileName, CFile::modeReadWrite|CFile::shareDenyNone, &e)) 
	{ 
		bExist = TRUE; 
		file.Close(); 
	} 
	else 
	{ 
		// 可能有其他程序正在处理此文件 
		switch(e.m_cause) 
		{ 
		case	CFileException::tooManyOpenFiles: 
		case	CFileException::accessDenied: 
		case	CFileException::sharingViolation: 
		case	CFileException::lockViolation: 
			return TRUE; 
		case	CFileException::fileNotFound: 
		case	CFileException::badPath: 
		case	CFileException::invalidFile: 
		case	CFileException::hardIO: 
		default: 
			return FALSE; 
		} 
	} 
 
	return bExist; 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: ReadIconInfo 
* 
*     PURPOSE:  获取指定ICO文件的信息(包括图像个数、图像尺寸、位深等) 
* 
*     PARAMS:   CFile& file - 图标文件类引用 
* 
*     RETURNS:  LPICONDIR - NULL 失败(由读文件或内存不足引起),非NULL 
*                           表示成功,返回值是一个指向ICONDIR的指针 
* 
\****************************************************************************/ 
LPICONDIR ReadIconInfo(CFile& file) 
{ 
	ICONDIR	icondir; 
	int uRet, infosize; 
 
	// 读取图标文件信息头结构 
	file.SeekToBegin(); 
	uRet  = file.Read((LPSTR)&icondir, sizeof(ICONDIR)); 
	if (uRet != sizeof(ICONDIR)) 
		return NULL; 
 
	ASSERT(icondir.idCount >= 1); 
 
	// 计算图标信息块的尺寸 
	infosize = sizeof(ICONDIR)+(icondir.idCount-1)*sizeof(ICONDIRENTRY); 
 
	// 分配用于存放图标信息的缓冲区内存块 
	LPICONDIR lpIR = (LPICONDIR)::GlobalAlloc(GPTR, infosize); 
	if (!lpIR) 
		return NULL; 
 
	// 读取图标信息 
	file.SeekToBegin(); 
	uRet  = file.Read((LPSTR)lpIR, infosize); 
	if (uRet != infosize) 
	{ 
		::GlobalFree(lpIR); 
		return NULL; 
	} 
 
	return lpIR; 
} 
 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: ReadICOHeader 
* 
*     PURPOSE:  读取ICO文件的头结构中的图像个数 
* 
*     PARAMS:   CFile& file - CFile类目标的引用 
* 
*     RETURNS:  UINT - 文件中图标图像的个数,-1表示失败 
* 
\****************************************************************************/ 
UINT ReadICOHeader(CFile& file) 
{ 
	ICONDIR	dir; 
 
	TRY 
	{ 
		file.SeekToBegin(); 
		file.Read((void*)&dir, sizeof(ICONDIR)); 
	} 
	CATCH(CFileException, e) 
	{ 
		return (UINT)-1;	// 读文件时出错 
	} 
	END_CATCH 
     
    return (UINT)dir.idCount; 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: FindDIBits 
* 
*     PURPOSE:  定位在CF_DIB格式的DIB图像数据中位数据的地址 
* 
*     PARAMS:   LPSTR lpbi - 指向CF_DIB内存块的指针 
* 
*     RETURNS:  LPSTR - 指向位数据的指针 
* 
\****************************************************************************/ 
LPSTR FindDIBBits(LPSTR lpbi) 
{ 
   return (lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi )); 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: DIBNumColors 
* 
*     PURPOSE:  计算指定DIB的调色板中颜色的个数 
* 
*     PARAMS:   LPSTR lpbi - 指向CF_DIB内存块 
* 
*     RETURNS:  WORD - 调色板中颜色项的个数 
* 
\****************************************************************************/ 
WORD DIBNumColors(LPSTR lpbi) 
{ 
    WORD wBitCount; 
    DWORD dwClrUsed; 
 
    dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed; 
 
	// 如果文件指定了实际使用的颜色个数,则直接使用这个值 
    if (dwClrUsed) 
        return (WORD)dwClrUsed; 
 
	// 否则通过位深度值进行相应的计算 
    wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount; 
 
    switch (wBitCount) 
    { 
        case 1: return 2; 
        case 4: return 16; 
        case 8:	return 256; 
        default:return 0; 
    } 
    return 0; 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: PaletteSize 
* 
*     PURPOSE:  计算调色板的尺寸 
* 
*     PARAMS:   LPSTR lpbi - 指向CF_DIB内存块 
* 
*     RETURNS:  WORD - 调色板的尺寸(以字节为单位) 
* 
\****************************************************************************/ 
WORD PaletteSize(LPSTR lpbi) 
{ 
    return (DIBNumColors(lpbi) * sizeof(RGBQUAD)); 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: BytesPerLine 
* 
*     PURPOSE:  计算扫描行的宽度(以字节为单位) 
* 
*     PARAMS:   LPBITMAPINFOHEADER lpBMIH - 指向CF_DIB内存块中BITMAPINFOHEADER 
*                                           的指针 
* 
*     RETURNS:  DWORD - 扫描行的宽度。(注:DIB扫描行的宽度是DWORD对齐的) 
* 
\****************************************************************************/ 
DWORD BytesPerLine(LPBITMAPINFOHEADER lpBMIH) 
{ 
    return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount); 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: _get_image_info 
* 
*     PURPOSE:  获得指定图像的宽、高尺寸及颜色数目 
* 
*     PARAMS:   LPICONDIR lpIR - 图标原始数组数组 
*				int index - 得获取尺寸的图像之索引 
*				LPSIZE lpSize - 接收尺寸的变量 
*				int *pColnum - 接收颜色数目的变量 
* 
*     RETURNS:   -  
* 
\****************************************************************************/ 
void _get_image_info(LPICONDIR lpIR, int index, LPSIZE lpSize, int *pColnum) 
{ 
	ASSERT(index <= lpIR->idCount); 
 
	lpSize->cx = lpIR->idEntries[index].bWidth; 
	lpSize->cy = lpIR->idEntries[index].bHeight; 
	*pColnum = lpIR->idEntries[index].bColorCount; 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: _get_string_info 
* 
*     PURPOSE:  获得指定图像宽、高字符串的尺寸及字符串 
* 
*     PARAMS:   LPSIZE lpImgSize - 图像尺寸数据 
*				int colnum - 图像的颜色数目 
*				LPTSTR lpString - 接收字符串的变量 
*				LPSIZE lpTxtSize - 接收文本尺寸的变量 
* 
*     RETURNS:   -  
* 
\****************************************************************************/ 
void _get_string_info(LPSIZE lpImgSize, int colnum, LPTSTR lpString, LPSIZE lpTxtSize) 
{ 
	ASSERT(lpImgSize); 
 
	// 获取图像尺寸字符串 
	sprintf((char*)lpString, "%d*%d*%d", lpImgSize->cx, lpImgSize->cy, colnum); 
 
	HWND hWnd = ::GetDesktopWindow(); 
	HDC  hDC  = ::GetDC(hWnd); 
 
	// 获取字符串的长度 
	::GetTextExtentPoint32(hDC, lpString, lstrlen((LPCTSTR)lpString), lpTxtSize);  
	 
	::ReleaseDC(hWnd, hDC); 
 
	return; 
} 
 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: _get_synthesis_imgsize 
* 
*     PURPOSE:  计算综合图像的尺寸(就是将所有格式的图像 
*				拼接在一起的总尺寸) 
* 
*     PARAMS:   int imgcount - 有多少副图像 
*				LPIMGINFO lpImgInfo - 图像数据数组首指针 
*						(注:此时的数组必需已被排序) 
*				LPSIZE lpSize - 接收综合尺寸的变量 
* 
*     RETURNS:   -  
* 
\****************************************************************************/ 
void _get_synthesis_imgsize(int imgcount, LPIMGINFO lpImgInfo, LPSIZE lpSize) 
{ 
	SIZE	size; 
 
	ASSERT(imgcount >= 1); 
	ASSERT(lpImgInfo); 
	ASSERT(lpSize); 
 
	// imgcount-1 就是结构数组中最后一个项,因为该数组 
	// 已经经过了排序,所以最后一个就是最宽的一个 
	size.cx = lpImgInfo[imgcount-1].imgsize.cx; 
 
	// 如果字串的宽度超出了图像的宽度,则取字串宽度 
	if (lpImgInfo[imgcount-1].txtsize.cx > size.cx) 
		size.cx = lpImgInfo[imgcount-1].txtsize.cx; 
 
	// 加上边界宽度 
	size.cx += BORDERSPEC*2; 
 
 
	// 计算综合图像高度 
	size.cy = BORDERSPEC; 
 
	// 综合图像高度的计算方法是: 
	// 上边界+图像高度+图像到文本间隔+文本高度+ 
	// 文本到图像间隔+第二副图像高度+图像到文本间 
	// 隔+ ..... +底边界 
	for (int i=0;icx = size.cx; 
	lpSize->cy = size.cy; 
} 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: _do_sort 
* 
*     PURPOSE:  将图标图像信息数组根据图像的宽度进行排序 
* 
*     PARAMS:   int imgcount - 有多少副图像 
*				LPIMGINFO lpImgInfo - 图像数据数组首指针 
* 
*     RETURNS:   - 返回后,数组中的数据将从小到大的被排序 
* 
\****************************************************************************/ 
void _do_sort(int imgcount, LPIMGINFO lpImgInfo) 
{ 
	int i, j, sortcount; 
	IMGINFO imgtmp; 
 
	// 初始化起始值 
	sortcount = imgcount-1; 
 
	// 起泡排序法 
	for (i=0;i lpImgInfo[j+1].imgsize.cx) 
			{ 
				// 交换数据 
				::memcpy((void*)&imgtmp, (const void*)&lpImgInfo[j], sizeof(IMGINFO)); 
				::memcpy((void*)&lpImgInfo[j], (const void*)&lpImgInfo[j+1], sizeof(IMGINFO)); 
				::memcpy((void*)&lpImgInfo[j+1], (const void*)&imgtmp, sizeof(IMGINFO)); 
			} 
		} 
	} 
} 
 
 
 
 
/**************************************************************************** 
* 
*     FUNCTION: _get_hbmp 
* 
*     PURPOSE:  获取指定图像的句柄 
* 
*     PARAMS:   CFile& file - 图标文件目标 
*				LPICONDIR lpIR - 原始图像数据数组 
*				LPIMGINFO lpImgInfo - 图像数据数组首指针 
*				int index - 指定获取句柄的图像索引(排序后的索引) 
* 
*     RETURNS:  HBITMAP - 图像的句柄,失败返回NULL 
* 
\****************************************************************************/ 
HBITMAP _get_hbmp(CFile& file, LPICONDIR lpIR, LPIMGINFO lpImgInfo, int index) 
{ 
	HBITMAP hBmp, hXORBmp, hANDBmp; 
	HBITMAP hOldBmp, hOldBmp2; 
 
	// 图像所占字节数 
	DWORD imgsize = lpIR->idEntries[lpImgInfo[index].index].dwBytesInRes;	 
	// 图像数据偏移 
	DWORD imgoffset = lpIR->idEntries[lpImgInfo[index].index].dwImageOffset;	 
 
 
	// 分配用于存放指定DF_DIB数据的内存块 
	PBYTE lpDIB = (PBYTE)::GlobalAlloc(GPTR, imgsize); 
	if (!lpDIB) 
		return NULL; 
 
	// 读取图像的DF_DIB数据 
	file.Seek(imgoffset, CFile::begin); 
 
	if (file.ReadHuge((void*)lpDIB, imgsize) != imgsize) 
	{ 
		::GlobalFree(lpDIB); 
		return NULL; 
	} 
 
	// 该高度值是XOR图与AND图高度的和,所以得除2 
	((LPBITMAPINFOHEADER)lpDIB)->biHeight /= 2; 
 
	RECT rect; 
	HWND hWnd = ::GetDesktopWindow(); 
	HDC  hDC  = ::GetDC(hWnd); 
	HDC  hMemDC = ::CreateCompatibleDC(hDC); 
	 
	// 创建目标图像 
	hBmp = ::CreateCompatibleBitmap(hDC, lpImgInfo[index].imgsize.cx,lpImgInfo[index].imgsize.cy); 
	if (!hBmp) 
	{ 
		::GlobalFree(lpDIB); 
		::ReleaseDC(hWnd, hDC); 
		::DeleteDC(hMemDC); 
		return NULL; 
	} 
 
	hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBmp); 
 
	rect.left = rect.top = 0; 
	rect.right = lpImgInfo[index].imgsize.cx; 
	rect.bottom = lpImgInfo[index].imgsize.cy; 
	// 将图像填充为白色 
	::FillRect(hMemDC, (CONST RECT*)&rect, (HBRUSH)::GetStockObject(WHITE_BRUSH)); 
 
	::SelectObject(hMemDC, hOldBmp); 
 
 
 
	// 创建XOR图像 
	hXORBmp = ::CreateCompatibleBitmap(hDC, lpImgInfo[index].imgsize.cx,lpImgInfo[index].imgsize.cy); 
	if (!hXORBmp) 
	{ 
		::DeleteObject(hBmp); 
		::GlobalFree(lpDIB); 
		::ReleaseDC(hWnd, hDC); 
		::DeleteDC(hMemDC); 
		return NULL; 
	} 
 
	::SetDIBits(hDC, hXORBmp, 0, lpImgInfo[index].imgsize.cy,  
		(const void*)::FindDIBBits((LPSTR)lpDIB), (CONST BITMAPINFO *)lpDIB, DIB_RGB_COLORS); 
 
 
	// 创建AND图像 
	hANDBmp = ::CreateBitmap(lpImgInfo[index].imgsize.cx,  
					lpImgInfo[index].imgsize.cy, 1, 1, NULL); 
	if (!hANDBmp) 
	{ 
		::DeleteObject(hXORBmp); 
		::DeleteObject(hBmp); 
		::GlobalFree(lpDIB); 
		::ReleaseDC(hWnd, hDC); 
		::DeleteDC(hMemDC); 
		return NULL; 
	} 
 
	LPBITMAPINFO	lpbmi; 
 
	lpbmi = (LPBITMAPINFO)::GlobalAlloc(GPTR, sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*2); 
	if (!lpbmi) 
	{ 
		::DeleteObject(hANDBmp); 
		::DeleteObject(hXORBmp); 
		::DeleteObject(hBmp); 
		::GlobalFree(lpDIB); 
		::ReleaseDC(hWnd, hDC); 
		::DeleteDC(hMemDC); 
		return NULL; 
	} 
 
	lpbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
	lpbmi->bmiHeader.biBitCount = 1; 
	lpbmi->bmiHeader.biClrImportant = 0; 
	lpbmi->bmiHeader.biClrUsed = 0; 
	lpbmi->bmiHeader.biCompression = BI_RGB; 
	lpbmi->bmiHeader.biHeight = ((LPBITMAPINFOHEADER)lpDIB)->biHeight; 
	lpbmi->bmiHeader.biPlanes = 1; 
	lpbmi->bmiHeader.biSizeImage = 0; 
	lpbmi->bmiHeader.biWidth = ((LPBITMAPINFOHEADER)lpDIB)->biWidth; 
	lpbmi->bmiHeader.biXPelsPerMeter = 0; 
	lpbmi->bmiHeader.biYPelsPerMeter = 0; 
    lpbmi->bmiColors[0].rgbRed = 0; 
    lpbmi->bmiColors[0].rgbGreen = 0; 
    lpbmi->bmiColors[0].rgbBlue = 0; 
    lpbmi->bmiColors[0].rgbReserved = 0; 
    lpbmi->bmiColors[1].rgbRed = 255; 
    lpbmi->bmiColors[1].rgbGreen = 255; 
    lpbmi->bmiColors[1].rgbBlue = 255; 
    lpbmi->bmiColors[1].rgbReserved = 0; 
 
	::SetDIBits(hMemDC, hANDBmp, 0, lpImgInfo[index].imgsize.cy,  
		(const void*)((PBYTE)::FindDIBBits((LPSTR)lpDIB) + \ 
						WIDTHBYTES(lpImgInfo[index].imgsize.cx*((LPBITMAPINFOHEADER)lpDIB)->biBitCount) * \ 
						lpImgInfo[index].imgsize.cy),  
		lpbmi, DIB_RGB_COLORS); 
 
	::GlobalFree(lpbmi); 
 
 
 
	// 合成图像 
	HDC  hMemDC2 = ::CreateCompatibleDC(hDC); 
 
	hOldBmp = (HBITMAP)::SelectObject(hMemDC, hBmp); 
	hOldBmp2 = (HBITMAP)::SelectObject(hMemDC2, hANDBmp); 
	::BitBlt(hMemDC, 0, 0, lpImgInfo[index].imgsize.cx, lpImgInfo[index].imgsize.cy, hMemDC2, 0, 0, SRCAND); 
	::SelectObject(hMemDC2, hXORBmp); 
	::BitBlt(hMemDC, 0, 0, lpImgInfo[index].imgsize.cx, lpImgInfo[index].imgsize.cy, hMemDC2, 0, 0, SRCINVERT); 
	::SelectObject(hMemDC2, hOldBmp2); 
	::SelectObject(hMemDC, hOldBmp); 
 
 
	// 释放无关资源 
	::DeleteDC(hMemDC2); 
	::DeleteDC(hMemDC); 
	::ReleaseDC(hWnd, hDC); 
	::GlobalFree(lpDIB); 
	::DeleteObject(hANDBmp); 
	::DeleteObject(hXORBmp); 
 
	// 返回合成位图 
	return hBmp; 
}