IcoModule.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:31k
- // IcoModule.cpp : Defines the initialization routines for the DLL.
- //
- #include "stdafx.h"
- #include "IcoModule.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- static char ModuleProcessImgType[]="ICO"; // 本模块能处理的图像类型
- static char WriterList[]="YZ"; // 本模块的作者列表
- static char WriterMess[]="HE HE ..."; // 作者留言
- //
- // 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(CIcoModuleApp, 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
- CIcoModuleApp::CIcoModuleApp()
- {
- // TODO: add construction code here,
- // Place all significant initialization in InitInstance
- }
- /////////////////////////////////////////////////////////////////////////////
- // The one and only CIcoModuleApp object
- CIcoModuleApp theApp;
- // 接口函数声明 — 第一层,唯一与外界联系的接口
- int WINAPI AccessICOModule(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: // 判断指定文件是否是有效的ICO文件
- 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命令
- // 判断指定文件是否是有效的ICO文件
- 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))
- {
- // 这不是一个ICON文件,图标文件的长度起码大于图标目录
- // 结构的长度
- 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 != ICONTYPE))
- {
- 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;i<lpIR->idCount;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;i<lpIR->idCount;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;i<lpIR->idCount;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;i<imgcount;i++)
- {
- size.cy += lpImgInfo[i].imgsize.cy;
- size.cy += IMGTXTSPEC;
- size.cy += lpImgInfo[i].txtsize.cy;
- size.cy += TXTIMGSPEC;
- }
- // 加底边界高度
- size.cy += BORDERSPEC-TXTIMGSPEC;
- lpSize->cx = 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<sortcount;i++)
- {
- for (j=0;j<(sortcount-i);j++)
- {
- // 以图像宽度为判别标准
- if (lpImgInfo[j].imgsize.cx > 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;
- }