WmfModule.cpp
上传用户:yatsl7111
上传日期:2007-01-08
资源大小:1433k
文件大小:23k
- /********************************************************************
- WmfModule.cpp - ISee图像浏览器—WMF图像读写模块实现文件
-
- 版权所有(C) 2000 VCHelp-coPathway-ISee workgroup member - YZ
- 这一程序是自由软件,你可以遵照自由软件基金会出版的GNU 通用公共许
- 可证条款来修改和重新发布这一程序。或者用许可证的第二版,或者(根
- 据你的选择)用任何更新的版本。
- 发布这一程序的目的是希望它有用,但没有任何担保。甚至没有适合特定
- 目地的隐含的担保。更详细的情况请参阅GNU通用公共许可证。
- 你应该已经和程序一起收到一份GNU通用公共许可证的副本。如果还没有,
- 写信给:
- The Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
- MA02139, USA
- 如果你在使用本软件时有什么问题或建议,用以下地址可以与我们取得联
- 系:
- http://isee.126.com
- http://www.vchelp.net
- 或:
- iseesoft@china.com
- 编写人:YZ
- E-Mail:yzfree@sina.com 或 yzfree@yeah.net
- 文件版本:
- Beta 1.1
- Build 00622
- Date 2000-6-22
- ********************************************************************/
- #include "stdafx.h"
- #include "WmfModule.h"
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- static char ModuleProcessImgType[]="WMF"; // 本模块能处理的图像类型
- static char WriterList[]="YZ"; // 本模块的作者列表
- static char WriterMess[]="很高兴能在自由软件开发组作矢量图的工作,这使我学到了不少元文件的知识^_^"; // 作者留言
- //
- // 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.
- //
- /////////////////////////////////////////////////////////////////////////////
- // CWmfModuleApp
- BEGIN_MESSAGE_MAP(CWmfModuleApp, CWinApp)
- //{{AFX_MSG_MAP(CWmfModuleApp)
- // 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()
- /////////////////////////////////////////////////////////////////////////////
- // CWmfModuleApp construction
- CWmfModuleApp::CWmfModuleApp()
- {
- // TODO: add construction code here,
- // Place all significant initialization in InitInstance
- }
- /////////////////////////////////////////////////////////////////////////////
- // The one and only CWmfModuleApp object
- CWmfModuleApp theApp;
- // 接口函数声明 — 第一层,唯一与外界联系的接口
- int WINAPI AccessWMFModule(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)
- {
- 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: // 判断指定文件是否是有效的WMF文件
- 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_SUCCESS;
- 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 = WMF_MODULE_BUILDID;
- pInfo->result = ER_SUCCESS;
- }
- // 操作命令解释函数---解释:CMD_IS_VALID_FILE命令
- // 判断指定文件是否是有效的WMF文件
- void _fnCMD_IS_VALID_FILE(INFOSTR *pInfo)
- {
- CFile file;
- DWORD dwIsAldus;
- DWORD dwSeekPos;
- DWORD dwFileSize;
- ALDUSMFHEADER aldusMFHeader;
- METAHEADER mfHeader;
- // 检验入口参数是否符合接口定义
- ASSERT(pInfo->result == ER_EMPTY);
- ASSERT(pInfo->annexdata.iAnnData == 0);
- ASSERT(::strlen(pInfo->filename));
- ASSERT(pInfo->state == PKST_NOTVER);
- // 先判断指定的文件是否存在
- if (!IsFileExist(pInfo->filename))
- pInfo->result = ER_COMMINFOERR;
- else
- {
- // 打开指定文件
- if (!file.Open(pInfo->filename, CFile::modeRead))
- {
- pInfo->result = ER_FILERWERR; // 打开文件时出错
- return;
- }
- dwFileSize = file.GetLength();
- // 用长度判断
- if (dwFileSize < sizeof(METAHEADER))
- {
- pInfo->result = ER_SUCCESS; // 这不是一个WMF文件
- pInfo->annexdata.iAnnData = 0; // WMF文件的长度起码大于
- file.Close(); // METAHEADER结构的长度
- return;
- }
- file.Seek(0, CFile::begin);
- // 读取文件头的四个字节。(如果是可放置元文件,该DWORD的
- // 内容应该是0x9AC6CDD7
- if (file.Read(&dwIsAldus, sizeof(DWORD)) != sizeof(DWORD))
- {
- pInfo->result = ER_FILERWERR; // 读文件时出错
- file.Close();
- return;
- }
- if (dwIsAldus == ALDUSKEY)
- {
- // 表明该文件是一个可放置元文件
- if (dwFileSize < (ALDUSMFHEADERSIZE+sizeof(METAHEADER)))
- {
- pInfo->result = ER_SUCCESS; // 这可能是一个受损的WMF文件
- pInfo->annexdata.iAnnData = 0;
- file.Close();
- return;
- }
- // 读去文件头部的结构。
- file.Seek(0, CFile::begin);
- if (file.Read(&aldusMFHeader, ALDUSMFHEADERSIZE) != ALDUSMFHEADERSIZE)
- {
- pInfo->result = ER_FILERWERR;
- file.Close();
- return;
- }
- dwSeekPos = ALDUSMFHEADERSIZE;
- }
- else // 老式的Windows元文件
- dwSeekPos = 0;
- file.Seek(dwSeekPos, CFile::begin);
- // 读windows元文件头
- if (file.Read(&mfHeader, sizeof(METAHEADER)) != sizeof(METAHEADER))
- {
- pInfo->result = ER_FILERWERR;
- file.Close();
- return;
- }
- // 检查头部标志(0表示是内存元文件,1表示磁盘元文件)
- if ((mfHeader.mtType != 0)&&(mfHeader.mtType != 1))
- {
- pInfo->result = ER_SUCCESS;
- pInfo->annexdata.iAnnData = 0; // 这可能是一个受损的WMF文件
- file.Close();
- return;
- }
- // 到此,表明该文件是一个有效的WMF文件,iAnnData变量设为1
- pInfo->annexdata.iAnnData = 1;
- pInfo->state = PKST_PASSVER;
- pInfo->result = ER_SUCCESS;
- file.Close();
- }
- }
- // 操作命令解释函数---解释:CMD_GET_FILE_INFO命令
- // 获取指定文件的信息
- void _fnCMD_GET_FILE_INFO(INFOSTR *pInfo)
- {
- CFile file;
- DWORD dwIsAldus;
- ALDUSMFHEADER aldusMFHeader;
- // 检验入口参数是否符合接口定义
- ASSERT(pInfo->result == ER_EMPTY);
- ASSERT(::strlen(pInfo->filename));
- // 此时,该文件必需是一个已存在的、并且是有效的WMF文件
- 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;
- }
- file.Seek(0, CFile::begin);
- // 读取文件头的四个字节。(如果是可放置元文件,该DWORD的
- // 内容应该是0x9AC6CDD7
- if (file.Read(&dwIsAldus, sizeof(DWORD)) != sizeof(DWORD))
- {
- file.Close();
- pInfo->result = ER_FILERWERR;
- return;
- }
- if (dwIsAldus == ALDUSKEY)
- {
- // 表明该文件是一个可放置元文件,读文件头部的结构。
- file.Seek(0, CFile::begin);
- if (file.Read(&aldusMFHeader, ALDUSMFHEADERSIZE) != ALDUSMFHEADERSIZE)
- {
- file.Close();
- pInfo->result = ER_FILERWERR;
- return;
- }
- }
- HWND hWnd = ::GetDesktopWindow();
- HDC dc = ::GetDC(hWnd);
- LPIMAGEINFOSTR lpImgInfoStr = &pInfo->imginfo;
- // 获取文件的长度、图像的宽度、高度等信息
- lpImgInfoStr->imgtype = IMT_VECTORSTATIC;
- lpImgInfoStr->imgformat = IMF_WMF;
- lpImgInfoStr->filesize = file.GetLength();
- // 计算WMF图像的原始尺寸。其中aldusMFHeader.bbox中存放的是文件单位的
- // 图像尺寸,而aldusMFHeader.inch中则是一英寸等于多少文件单位的数值。
- // 我们先计算出该图像的以英寸为单位的尺寸,然后再除以当前显示器的每
- // 英寸多少像素的值(可用GetDeviceCaps()函数取得),就可以得到图像以
- // 像素为单位的尺寸了。(挺麻烦的:-)
- float fx, fy;
- if (dwIsAldus == ALDUSKEY)
- {
- fx = (float)(aldusMFHeader.bbox.right-aldusMFHeader.bbox.left);
- fy = (float)(aldusMFHeader.bbox.bottom-aldusMFHeader.bbox.top);
- fx = (fx/(float)aldusMFHeader.inch)*::GetDeviceCaps(dc, LOGPIXELSX)+(float)0.5; // 此处的加上0.5是四舍五入.
- fy = (fy/(float)aldusMFHeader.inch)*::GetDeviceCaps(dc, LOGPIXELSY)+(float)0.5;
- }
- if (dwIsAldus == ALDUSKEY)
- lpImgInfoStr->width = (int)fx;
- // 如果是可放置的元文件,则宽度等于指定的宽度.
- else
- lpImgInfoStr->width = ::GetDeviceCaps(dc, HORZRES);
- // 如果是老式的Windows元文件,就默认它的宽度为屏幕宽度.因为这种
- // 元文件中没有保存图像尺寸的数据.
- if (dwIsAldus == ALDUSKEY)
- lpImgInfoStr->height = (int)fy;
- else
- lpImgInfoStr->height = ::GetDeviceCaps(dc, VERTRES);
- ::ReleaseDC(hWnd, dc);
- // 这是个虚值,没有意义.因为元文件中没有保存颜色数据(不针对增强型元文件).
- lpImgInfoStr->bitcount = 24;
- lpImgInfoStr->compression = ICS_GDIRECORD;
- // 以下这个0值没有意义,该参数只对BMP图像文件有意义.
- lpImgInfoStr->linesize = 0;
- // 静态WMF文件只有一个图像,所以设为1.
- lpImgInfoStr->imgnumbers = 1;
- // 可以被编辑,因为它是静态图像。
- lpImgInfoStr->imgchang = 0;
- // 获取文件最后的修改日期(月在高字节,日在低字节)
- CFileStatus status;
- 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;
- // 关闭文件
- file.Close();
- // 设置出口数据
- pInfo->state = PKST_PASSINFO;
- pInfo->result = ER_SUCCESS;
- }
- // 操作命令解释函数---解释:CMD_LOAD_FROM_FILE命令
- // 从指定图像文件中读取数据
- void _fnCMD_LOAD_FROM_FILE(INFOSTR *pInfo)
- {
- // 检验入口参数是否符合接口定义
- ASSERT(pInfo->result == ER_EMPTY);
- ASSERT(::strlen(pInfo->filename));
- // 此时,该文件必需是一个已存在的、有效的WMF文件,并且数据包中
- // 含有该文件的信息(imginfo结构中)
- ASSERT(pInfo->state == PKST_PASSINFO);
- ASSERT(pInfo->imginfo.imgformat == IMF_WMF);
- ASSERT(pInfo->pImgInfo == NULL);
- // 必需设置标准图像格式信息
- ASSERT(pInfo->sDIBInfo.bmi.biSize == sizeof(BITMAPINFOHEADER));
- ASSERT(pInfo->pLineAddr != NULL);
- ASSERT(pInfo->_pbdata != NULL);
- HENHMETAFILE hEnhMeta;
- BYTE *pby;
- HBITMAP bmp, oldbmp;
- HWND hWnd = ::GetDesktopWindow();
- HDC hDC = ::GetDC(hWnd);
- HDC hComDC;
- int sizeline;
- ASSERT(hWnd);
- if (pInfo->fpProgress)
- {
- if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 6))
- { // 如果进度函数返回1,则说明用户想中断操作,返回。
- ::ReleaseDC(hWnd, hDC);
- pInfo->result = ER_USERBREAK;
- return;
- }
- }
- if (Read(pInfo, &hEnhMeta))
- {
- ASSERT(hEnhMeta);
- ASSERT(pInfo->sDIBInfo.bmi.biPlanes == 1);
- // 可接收三中格式的图像位数据请求:16,24,32。并且要求数据包位
- // 数据缓冲区是DIB格式(扫描行以4字节对齐)
- ASSERT((pInfo->sDIBInfo.bmi.biBitCount==16)||(pInfo->sDIBInfo.bmi.biBitCount==24)||(pInfo->sDIBInfo.bmi.biBitCount==32));
- // 创建用于存放图像位数据的临时缓冲区
- bmp = ::CreateDIBSection(hDC, (CONST BITMAPINFO*)&pInfo->sDIBInfo,
- DIB_RGB_COLORS, (VOID**)&pby, NULL, 0);
- hComDC = ::CreateCompatibleDC(hDC);
- if ((bmp == NULL)||(hComDC == NULL)) // 错误检查
- {
- ASSERT(pInfo->pImgInfo);
- ::GlobalFree(pInfo->pImgInfo);
- pInfo->pImgInfo = NULL;
- ::DeleteEnhMetaFile(hEnhMeta);
- ::ReleaseDC(hWnd, hDC);
- if (bmp) ::DeleteObject(bmp);
- if (hComDC) ::DeleteDC(hComDC);
- pInfo->result = ER_SYSERR;
- return;
- }
- ASSERT(pby); // 此时pby中必然存在bmp位数据缓冲区的地址
- oldbmp = (HBITMAP)::SelectObject(hComDC, bmp);
- // 设置背景色为缺省窗口色
- ::FillRect(hComDC, &CRect(0,0,pInfo->sDIBInfo.bmi.biWidth, pInfo->sDIBInfo.bmi.biHeight), (HBRUSH)(COLOR_WINDOW+1));
- // 绘制WMF图像(由Windows元文件格式转为的EMF格式)
- ::PlayEnhMetaFile(hComDC, hEnhMeta, CRect(0,0,pInfo->sDIBInfo.bmi.biWidth, pInfo->sDIBInfo.bmi.biHeight));
- ::SelectObject(hComDC, oldbmp);
- ::DeleteDC(hComDC);
- int height = pInfo->sDIBInfo.bmi.biHeight;
- ASSERT(height != 0);
- // DIB缓冲区中每一扫描行都是4字节对齐的,所以使用了DIBSCANLINE_WIDTHBYTES宏
- sizeline = DIBSCANLINE_WIDTHBYTES(pInfo->sDIBInfo.bmi.biWidth*pInfo->sDIBInfo.bmi.biBitCount);
- // 复制图像到数据包中
- PBYTE lpsou = pby;
- ASSERT(pInfo->pLineAddr[0] != NULL); // 如果数据包中的行地址没有填写,就会引发此断言
- if (height < 0) // 正向DIB缓冲区(top-down)
- {
- for (int i=0;i<height;i++)
- {
- ::CopyMemory((PVOID)pInfo->pLineAddr[i], (CONST VOID *)lpsou, sizeline);
- lpsou += sizeline;
- }
- }
- else // 倒向
- {
- for (int i=0;i<height;i++)
- {
- ::CopyMemory((PVOID)pInfo->pLineAddr[height-i-1], (CONST VOID *)lpsou, sizeline);
- lpsou += sizeline;
- }
- }
- ::DeleteObject(bmp);
- ::DeleteEnhMetaFile(hEnhMeta);
- // 成功
- pInfo->state = PKST_INFOANDBITS;
- pInfo->modify = 0;
- pInfo->result = ER_SUCCESS;
- }
- ::ReleaseDC(hWnd, hDC);
- if (pInfo->fpProgress) // 结束进度条,此调用不再支持用户中断
- (*pInfo->fpProgress)(RWPROGRESSSIZE, RWPROGRESSSIZE);
- }
- // 操作命令解释函数---解释:CMD_SAVE_TO_FILE命令
- // 将数据保存到指定文件中
- void _fnCMD_SAVE_TO_FILE(INFOSTR *pInfo)
- {
- // WMF模块无法支持保存命令。
- pInfo->result = ER_NOTSUPPORT;
- return;
- }
- // 操作命令解释函数---解释:CMD_RESIZE命令
- // 重新获取指定尺寸的图像位数据(只适用于矢量图像)
- void _fnCMD_RESIZE(INFOSTR *pInfo)
- {
- // 指定尺寸在pInfo->sDIBInfo.bmi中指定
- _fnCMD_LOAD_FROM_FILE(pInfo);
- }
- /*************************************************************************
- *
- * IsFileExist()
- *
- * 参数说明:
- *
- * char *lpFileName - 待判断的文件路径和名称(文件名)
- *
- * 返回值:
- *
- * BOOL - 如果指定的文件存在返回TRUE,否则返回FALSE。
- *
- * 描述:
- *
- * 判断指定的文件是否存在
- *
- * 该文件必需可以被读和写
- *
- ************************************************************************/
- BOOL IsFileExist(char *lpFileName)
- {
- CFile file;
- BOOL bExist = FALSE; // 文件存在是TRUE,不存在是FALSE
- // 确定指定的文件是否存在
- if (file.Open(lpFileName, CFile::modeReadWrite))
- {
- bExist = TRUE;
- file.Close();
- }
- return bExist;
- }
- /*************************************************************************
- *
- * Read()
- *
- * 参数说明:
- *
- * INFOSTR *pInfo - 图像读写数据包
- * HENHMETAFILE *pHEnhMeta - 返回的元文件句柄(如果成功的话)
- *
- * 返回值:
- *
- * BOOL - 如果读取成功返回TRUE,否则返回FALSE。
- *
- * 描述:
- * 如果调用成功,该函数将修改pHEnhMeta指向的值,而且申请一块内存
- * 挂接到pInfo中的pImgInfo上(此内存块由客户程序负责释放)。
- *
- * 读取指定元文件到数据包中
- *
- ************************************************************************/
- BOOL Read(INFOSTR *pInfo, HENHMETAFILE *pHEnhMeta)
- {
- CFile file;
- DWORD dwIsAldus;
- ALDUSMFHEADER m_aldusMFHeader;
- METAHEADER mfHeader;
- DWORD dwSize;
- DWORD seekpos;
- *pHEnhMeta = NULL;
- // 打开指定文件
- if (!file.Open(pInfo->filename, CFile::modeRead))
- {
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
- file.Seek(0, CFile::begin);
- if (file.Read(&dwIsAldus, sizeof(DWORD)) != sizeof(DWORD))
- {
- file.Close();
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
-
- if (dwIsAldus != ALDUSKEY) // 旧的Windows元文件.
- {
- ::ZeroMemory(&m_aldusMFHeader, sizeof(m_aldusMFHeader));
- seekpos = 0;
- }
- else // 可放置型元文件.
- {
- file.Seek(0, CFile::begin);
- // 读去头部的附加结构
- if (file.Read(&m_aldusMFHeader, ALDUSMFHEADERSIZE) != ALDUSMFHEADERSIZE)
- {
- file.Close();
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
- seekpos = ALDUSMFHEADERSIZE;
- }
- file.Seek(seekpos, CFile::begin);
- // 读Windows元文件头.
- if (file.Read(&mfHeader, sizeof(mfHeader)) != sizeof(mfHeader))
- {
- file.Close();
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
- // 为元文件数据分配内存.(mtSize的尺寸值单位是WORD型,所以乘2)
- dwSize = mfHeader.mtSize*2;
- BYTE* lpMFBits = (BYTE*)::GlobalAlloc(GPTR, dwSize);
- if (lpMFBits == NULL)
- {
- file.Close();
- pInfo->result = ER_MEMORYERR; // 内存不足,返回.
- return FALSE;
- }
- // 定位元文件位数据偏移.
- file.Seek(seekpos, CFile::begin);
- int loop = dwSize/RWBLOCKSIZE; // 读的循环次数
- int leavings = dwSize-(loop*RWBLOCKSIZE); // 剩余尺寸
- BYTE *lpTmp = lpMFBits;
- // 将图像数据读入内存
- for (int i=0;i<loop;i++)
- {
- if (file.Read(lpTmp, RWBLOCKSIZE) != RWBLOCKSIZE)
- {
- file.Close();
- ::GlobalFree(lpMFBits);
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
- if (pInfo->fpProgress)
- {
- if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 10+60/loop*(i+1)))
- { // 如果进度函数返回1,则说明用户想中断操作,返回。
- file.Close();
- ::GlobalFree(lpMFBits);
- pInfo->result = ER_USERBREAK;
- return FALSE;
- }
- }
- lpTmp += RWBLOCKSIZE;
- }
- if (file.Read(lpTmp, leavings) != (unsigned int)leavings)
- {
- file.Close();
- ::GlobalFree(lpMFBits);
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
- /* 简化代码
- if (file.ReadHuge(lpMFBits, dwSize) != dwSize)
- {
- file.Close();
- delete [] lpMFBits;
- pInfo->result = ER_FILERWERR;
- return FALSE;
- }
- */
- // 获得元文件句柄
- *pHEnhMeta = ::SetWinMetaFileBits(dwSize, lpMFBits, NULL, NULL);
- // 此时lpMFBits中的数据已经无用,删除.
- ASSERT(lpMFBits);
- ::GlobalFree(lpMFBits);
- file.Close();
- if (!(*pHEnhMeta))
- {
- pInfo->result = ER_SYSERR;
- return FALSE;
- }
- if (pInfo->fpProgress)
- {
- if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 80))
- { // 如果进度函数返回1,则说明用户想中断操作,返回。
- ::DeleteEnhMetaFile(*pHEnhMeta);
- *pHEnhMeta = NULL;
- pInfo->result = ER_USERBREAK;
- return FALSE;
- }
- }
- // 分配原始图像信息块
- LPWMFADDINFO lpWmfAddInfo;
- lpWmfAddInfo = (LPWMFADDINFO)::GlobalAlloc(GPTR, sizeof(WMFADDINFO));
- if (!lpWmfAddInfo)
- {
- ::DeleteEnhMetaFile(*pHEnhMeta);
- *pHEnhMeta = NULL;
- pInfo->result = ER_MEMORYERR;
- return FALSE;
- }
- HWND hWnd = ::GetDesktopWindow();
- HDC dc = ::GetDC(hWnd);
- if (dwIsAldus == ALDUSKEY)
- {
- // 表明该文件是一个可放置元文件,读文件头部的结构。
- lpWmfAddInfo->format = 1; // 等于1表示它是可放置元文件
- lpWmfAddInfo->inchto = m_aldusMFHeader.inch; // 文件单位到英寸单位的转换因子
- lpWmfAddInfo->x1 = m_aldusMFHeader.bbox.left;
- lpWmfAddInfo->y1 = m_aldusMFHeader.bbox.top;
- lpWmfAddInfo->x2 = m_aldusMFHeader.bbox.right;
- lpWmfAddInfo->y2 = m_aldusMFHeader.bbox.bottom;
- lpWmfAddInfo->whgene = (float)(((float)lpWmfAddInfo->x2-lpWmfAddInfo->x1)/((float)lpWmfAddInfo->y2-lpWmfAddInfo->y1));
- }
- else
- {
- lpWmfAddInfo->format = 0; // 0表示老的Windows元文件
- lpWmfAddInfo->inchto = 0;
- lpWmfAddInfo->x1 = 0;
- lpWmfAddInfo->y1 = 0;
- // 此时x1,x2,y1,y2的单位就不是文件单位了,而是像素单位
- lpWmfAddInfo->x2 = ::GetDeviceCaps(dc, HORZRES);
- lpWmfAddInfo->y2 = ::GetDeviceCaps(dc, VERTRES);
- lpWmfAddInfo->whgene = (float)(((float)lpWmfAddInfo->x2-lpWmfAddInfo->x1)/((float)lpWmfAddInfo->y2-lpWmfAddInfo->y1));
- }
- // 置原始图像信息,此内存块由客户程序负责释放
- pInfo->pImgInfo = (void*)lpWmfAddInfo;
- ::ReleaseDC(hWnd, dc);
- if (pInfo->fpProgress)
- {
- if ((*pInfo->fpProgress)(RWPROGRESSSIZE, 90))
- { // 如果进度函数返回1,则说明用户想中断操作,返回。
- ::DeleteEnhMetaFile(*pHEnhMeta);
- *pHEnhMeta = NULL;
- ::GlobalFree(lpWmfAddInfo);
- pInfo->pImgInfo = NULL;
- pInfo->result = ER_USERBREAK;
- return FALSE;
- }
- }
- return TRUE;
- }