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; }
void CDib::Empty() { // se supone que esto libera lo que está en el DIB DetachMapFile(); if(m_nBmihAlloc == crtAlloc) { delete [] m_lpBMIH; } else if(m_nBmihAlloc == heapAlloc) { ::GlobalUnlock(m_hGlobal); ::GlobalFree(m_hGlobal); } if(m_nImageAlloc == crtAlloc) delete [] m_lpImage; if(m_hPalette != NULL) ::DeleteObject(m_hPalette); if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap); m_nBmihAlloc = m_nImageAlloc = noAlloc; m_hGlobal = NULL; m_lpBMIH = NULL; m_lpImage = NULL; m_lpvColorTable = NULL; m_nColorTableEntries = 0; m_dwSizeImage = 0; m_lpvFile = NULL; m_hMap = NULL; m_hFile = NULL; m_hBitmap = NULL; m_hPalette = NULL; }
/************************************************************************* * * \函数名称: * 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; }
/************************************************************************* * * \函数名称: * Empty() * * \输入参数: * 无 * * \返回值: * 无 * * \说明: * 该函数清空DIB,释放已分配的内存,并且必要的时候关闭映射文件 * ************************************************************************ */ void CDib::Empty() { // 关闭内存映射文件的连接 DetachMapFile(); // 根据内存分配的状态,调用相应的函数释放信息头 if(m_nBmihAlloc == crtAlloc) { delete [] m_lpBMIH; } else if(m_nBmihAlloc == heapAlloc) { ::GlobalUnlock(m_hGlobal); ::GlobalFree(m_hGlobal); } // 释放图象数据内存 if(m_nImageAlloc == crtAlloc) delete [] m_lpImage; // 释放调色板句柄 if(m_hPalette != NULL) ::DeleteObject(m_hPalette); // 如果创建了BITMAP,则进行释放 if(m_hBitmap != NULL) ::DeleteObject(m_hBitmap); // 重新设置内存分配状态 m_nBmihAlloc = m_nImageAlloc = noAlloc; // 释放内存后,还需要将指针设置为NULL并将相应的数据设置为0 m_hGlobal = NULL; m_lpBMIH = NULL; m_lpImage = NULL; m_lpvColorTable = NULL; m_nColorTableEntries = 0; m_dwSizeImage = 0; m_lpvFile = NULL; m_hMap = NULL; m_hFile = NULL; m_hBitmap = NULL; m_hPalette = NULL; }