BOOL CDib::AttachMapFile(const TCHAR* strPathname, BOOL bShare) // para lectura { // si abrimos el mismo archivo dos veces, Windows lo trata como si fueran // 2 archivos distintos. No funciona con archivos BMP extraños en los // que # entradas de paleta > biClrUsed HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, bShare ? FILE_SHARE_READ : 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); DWORD dwFileSize = ::GetFileSize(hFile, NULL); HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); DWORD dwErr = ::GetLastError(); if(hMap == NULL) { AfxMessageBox(_T("Archivo de mapa de bits vacío")); return FALSE; } LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // proyectar archivo completo ASSERT(lpvFile != NULL); if(((LPBITMAPFILEHEADER) lpvFile)->bfType != 0x4d42) { AfxMessageBox(_T("Archivo de mapa de bits inválido")); DetachMapFile(); return FALSE; } AttachMemory((LPBYTE) lpvFile + sizeof(BITMAPFILEHEADER)); m_lpvFile = lpvFile; m_hFile = hFile; m_hMap = hMap; return TRUE; }
/************************************************************************* * * \函数名称: * AttachMapFile() * * \输入参数: * const char* strPathname - 映射文件的路径名 * BOOL bShare - 如果文件以共享形式打开,设置为TRUE * - 默认值为FALSE * * \返回值: * BOOL - 如果成功,则为TRUE * * \说明: * 以读模式打开内存映射文件,并将其与CDib对象进行关联。因为在文件使用之前并没有读入内存, * 所以它立即返回。不过,当访问这个DIB的时候,可能会有一些延迟,因为文件是分页的。 * DetachMapFile函数可以释放现有的已分配的内存,并关闭以前关联的任何内存映射文件。 * 用内存中的DIB与已有的CDib对象关联。此内存可能是程序的资源,或者是可能是剪贴板 * 或者OLE数据对象内存。内存可能已经由CRT堆栈用new运算符分配了,或者可能已经由 * Windows堆栈用GlobalAlloc分配了。 * 如果打开相同的文件两次,则Windows以另一个文件来对待 * ************************************************************************ */ BOOL CDib::AttachMapFile(const char* strPathname, BOOL bShare) // for reading { // 获取文件句柄,并设置打开模式为共享 HANDLE hFile = ::CreateFile(strPathname, GENERIC_WRITE | GENERIC_READ, bShare ? FILE_SHARE_READ : 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); ASSERT(hFile != INVALID_HANDLE_VALUE); // 获取文件的尺寸 DWORD dwFileSize = ::GetFileSize(hFile, NULL); // 创建文件映射对象,并设置文件映射的模式为读写 HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); DWORD dwErr = ::GetLastError(); if(hMap == NULL) { AfxMessageBox("Empty bitmap file"); return FALSE; } // 映射整个文件,注意FILE_MAP_WRITE为读写模式 LPVOID lpvFile = ::MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); // map whole file ASSERT(lpvFile != NULL); // 确认为bmp格式文件 if(((LPBITMAPFILEHEADER) lpvFile)->bfType != 0x4d42) { AfxMessageBox("Invalid bitmap file"); DetachMapFile(); return FALSE; } // 将内存中的DIB与已有的CDib对象关联 AttachMemory((LPBYTE) lpvFile + sizeof(BITMAPFILEHEADER)); // 将这些有用的句柄设置为类数据成员 m_lpvFile = lpvFile; m_hFile = hFile; m_hMap = hMap; // 返回 return TRUE; }