?? bmpproc.cpp
字號:
break;
case IT_DISKFILE:
ASSERT(!m_cFileName.IsEmpty()); // 文件來源的位圖應(yīng)該有文件名
case IT_RESOURCE:
case IT_MEMORY:
case IT_CLIP:
case IT_CREATE:
m_cFileName.Empty();
ASSERT(m_pInfo);
::free((void*)m_pInfo);
m_pInfo = NULL;
m_addInfo = 0;
m_type = IT_NULL;
m_mark = FALSE;
break;
default:
ASSERT(FALSE);
break;
}
return hBmp;
}
/*************************************************************************
*
* Save()
*
* 參數(shù)說明:
*
* LPCTSTR lpszNewFileName - 指定的新文件名(可以是NULL)
* WORD nBitsPerPixel - 指定的新顏色格式(即每像素多少位,可以是0)
*
* 返回值:
*
* BOOL - 如果成功返回TRUE,否則返回FALSE
*
* 描述:
*
* 將本身類中的位圖以新的格式或新的名稱保存到文件中
*
* 注:
*
* # 如果沒有指定新的文件名(入口參數(shù)lpszNewFileName被指定為NULL),函數(shù)
* 就使用類中原來的文件名,如果類中原來沒有文件名則函數(shù)失敗,返回FALSE
* # 如果沒有指定新的位數(shù)(入口參數(shù)nBitsPerPixel被指定為0),函數(shù)就使用類
* 中原來的位數(shù)值。如果新指定的位數(shù)值非法則函數(shù)失敗,返回FALSE。合法的
* 位數(shù)值是1,4,8,16,24,32 其中之一
* # 如果本身類中原來沒有位圖(空類),函數(shù)返回FALSE
* # 如果文件沒有打開或是寫文件時出錯,函數(shù)返回FALSE
* # 函數(shù)執(zhí)行成功之后,本身類中的文件名或位數(shù)將改為新值
* # 無論函數(shù)成功與否,本身類中的位圖不會改變
*
************************************************************************/
BOOL CBmpProc::Save(LPCTSTR lpszNewFileName, WORD nBitsPerPixel)
{
// 如果本身類中原來沒有位圖,函數(shù)返回FALSE
if (!IsValid())
return FALSE;
ASSERT(m_pInfo);
ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
LPBITMAPINFO pInfo;
BOOL bRet;
CString cOldFN;
// 以原來的格式保存到原來的文件中
if ((lpszNewFileName==NULL)&&(nBitsPerPixel==0))
{
// 應(yīng)該有文件名
if (m_cFileName.IsEmpty())
return FALSE;
return SaveBaseSpecifyFileName((LPCTSTR)m_cFileName);
}
// 以原來的格式保存到新的文件中
if ((lpszNewFileName!=NULL)&&(nBitsPerPixel==0))
{
bRet = SaveBaseSpecifyFileName((LPCTSTR)lpszNewFileName);
if (bRet)
m_cFileName = lpszNewFileName;
return bRet;
}
// 以新的格式保存到原來的文件中
if ((lpszNewFileName==NULL)&&(nBitsPerPixel!=0))
{
// 檢測位數(shù)合法性
if (!IsValidDibFormat(nBitsPerPixel))
return FALSE;
// 應(yīng)該有文件名
if (m_cFileName.IsEmpty())
return FALSE;
bRet = SaveBaseSpecifyFormat(nBitsPerPixel);
if (bRet)
{
pInfo = GetSpecifyFormatInfo(nBitsPerPixel);
if (!pInfo)
return FALSE;
::free((void*)m_pInfo);
m_pInfo = pInfo;
}
return bRet;
}
// 以新的格式保存到新的文件中
if ((lpszNewFileName!=NULL)&&(nBitsPerPixel!=0))
{
// 檢測位數(shù)合法性
if (!IsValidDibFormat(nBitsPerPixel))
return FALSE;
cOldFN = m_cFileName;
m_cFileName = lpszNewFileName;
bRet = SaveBaseSpecifyFormat(nBitsPerPixel);
if (bRet)
{ // 獲取指定格式的信息塊
pInfo = GetSpecifyFormatInfo(nBitsPerPixel);
if (!pInfo)
{
m_cFileName = cOldFN;
return FALSE;
}
::free((void*)m_pInfo);
m_pInfo = pInfo;
}
else
m_cFileName = cOldFN;
return bRet;
}
return FALSE;
}
/*************************************************************************
*
* SaveToClipboard()
*
* 參數(shù)說明:無
*
*
* 返回值:
*
* BOOL - 如果成功返回TRUE,否則返回FALSE
*
* 描述:
*
* 保存本身類中的位圖到剪貼板
*
* 注:
*
* # 如果本身類中原來沒有位圖,函數(shù)返回FALSE
* # 如果在打開或?qū)懭爰糍N板時出錯,函數(shù)返回FALSE
* # 無論函數(shù)成功與否,本身類中的內(nèi)容都不會改變
*
************************************************************************/
BOOL CBmpProc::SaveToClipboard()
{
// 如果本身類中原來沒有位圖,函數(shù)返回FALSE
if (!IsValid())
return FALSE;
ASSERT(m_pInfo);
ASSERT(m_pInfo->bmiHeader.biSize == sizeof(BITMAPINFOHEADER));
// 打開剪貼板
if (::OpenClipboard(NULL))
{
// 清空剪貼板
if (::EmptyClipboard())
{
DWORD DibSize = CalculateDIBSize((LPBITMAPINFOHEADER)m_pInfo);
DWORD infosize =CalculateDIBInfoSize((LPBITMAPINFOHEADER)m_pInfo);
// 分配DIB內(nèi)部格式內(nèi)存塊
HANDLE hDib = ::GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, DibSize);
if (hDib)
{
LPSTR lpDib = (LPSTR)::GlobalLock(hDib);
if (lpDib)
{
::memcpy((void*)lpDib, (const void*)m_pInfo, infosize);
// 獲取DIB位數(shù)據(jù)
HWND hWnd = ::GetDesktopWindow();
ASSERT(hWnd);
HDC hDC = ::GetDC(hWnd);
if (!::GetDIBits(hDC,(HBITMAP)m_hObject,0,m_pInfo->bmiHeader.biHeight,\
(LPVOID)((DWORD)lpDib+infosize),(LPBITMAPINFO)lpDib,DIB_RGB_COLORS))
{
::GlobalUnlock(hDib);
::GlobalFree(hDib);
::CloseClipboard();
::ReleaseDC(hWnd, hDC);
return FALSE;
}
::ReleaseDC(hWnd, hDC);
::GlobalUnlock(hDib);
// 將DIB數(shù)據(jù)貼入剪貼板
if (::SetClipboardData(CF_DIB, hDib))
{
// 如果成功,DIB句柄不應(yīng)釋放
::CloseClipboard();
return TRUE; // 成功
}
else
{
::GlobalFree(hDib);
::CloseClipboard();
return FALSE; // 失敗
}
}
::GlobalFree(hDib);
}
}
::CloseClipboard();
}
return FALSE; // 失敗
}
/*************************************************************************
*
* SaveBaseSpecifyFileName()
*
* 參數(shù)說明:
*
* LPCTSTR fn - 指定的文件名稱
*
* 返回值:
*
* BOOL - 如果成功返回TRUE,否則返回FALSE
*
* 描述:
*
* 保存本身類中的位圖到指定的文件中
*
* 注:
*
* # 如果指定的文件已經(jīng)存在,則函數(shù)將覆蓋該文件
* # 如果本身類中原來沒有位圖,函數(shù)返回FALSE
* # 如果文件沒有打開或是寫文件時出錯,函數(shù)返回FALSE
* # 函數(shù)并不修改類中文件名
*
************************************************************************/
BOOL CBmpProc::SaveBaseSpecifyFileName(LPCTSTR fn)
{
// 如果本身類中原來沒有位圖,函數(shù)返回FALSE
if (!IsValid())
return FALSE;
ASSERT(m_pInfo);
// 如果沒有指定文件名,返回FALSE
if (!fn)
return FALSE;
FILE *file;
// 用創(chuàng)建方式打開文件(二進(jìn)制)
file = ::fopen(fn, "w+b");
if (!file)
return FALSE;
::fseek(file, 0, SEEK_SET);
BITMAPFILEHEADER bmf;
bmf.bfType = DIB_HEADER_MARKER; //((WORD) ('M' << 8) | 'B')
bmf.bfSize = CalculateDIBFileSize((LPBITMAPINFOHEADER)m_pInfo);
bmf.bfReserved1 = 0;
bmf.bfReserved2 = 0;
bmf.bfOffBits = CalculateDIBitsOff((LPBITMAPINFOHEADER)m_pInfo);
// 寫入文件頭信息
if (!::fwrite((const void *)&bmf, sizeof(BITMAPFILEHEADER), 1, file))
{
::fclose(file);
return FALSE;
}
// 復(fù)制信息塊內(nèi)容,之所以復(fù)制信息塊而不直接使用m_pInfo,是因為
// GetDIBits()函數(shù)有可能改變信息塊顏色表的內(nèi)容
int infosize = CalculateDIBInfoSize((LPBITMAPINFOHEADER)m_pInfo);
ASSERT(infosize == (int)::_msize((void*)m_pInfo));
LPBITMAPINFO pInfo = (LPBITMAPINFO)CreateMemoryBlockFromAddress(
(LPVOID)m_pInfo);
if (!pInfo)
{
::fclose(file);
return FALSE;
}
// 寫入信息塊內(nèi)容
if (!::fwrite((const void *)pInfo, infosize, 1, file))
{
::free((void*)pInfo);
::fclose(file);
return FALSE;
}
LPSTR pBits = (LPSTR)CreateMemoryBlockFromAddress((LPVOID)NULL,
CalculateDIBitsSize((LPBITMAPINFOHEADER)pInfo));
if (!pBits)
{
::free((void*)pInfo);
::fclose(file);
return FALSE;
}
// 獲取DIB位數(shù)據(jù)
HWND hWnd = ::GetDesktopWindow();
ASSERT(hWnd);
HDC hDC = ::GetDC(hWnd);
if (!::GetDIBits(hDC,(HBITMAP)m_hObject,0,pInfo->bmiHeader.biHeight,\
(LPVOID)pBits,pInfo,DIB_RGB_COLORS))
{
::free((void*)pInfo);
::free((void*)pBits);
::fclose(file);
::ReleaseDC(hWnd, hDC);
return FALSE;
}
::ReleaseDC(hWnd, hDC);
// 信息塊已無用,釋放
::free((void*)pInfo);
DWORD dwA, dwB, dwC;
LPSTR lp = pBits;
// 以分段方式寫入位數(shù)據(jù),每個段長度為32KB。
dwA = CalculateDIBitsSize((LPBITMAPINFOHEADER)m_pInfo); // 總長度
dwB = dwA/32768; // 段數(shù)(32768)
dwC = dwA - (dwB*32768); // 余數(shù)
for (;dwB!=0;dwB--)
{
if (!::fwrite((const void *)lp, 32768, 1, file))
{
::free((void*)pBits);
::fclose(file);
return FALSE;
}
lp = (LPSTR)((DWORD)lp+32768UL);
}
// 寫入剩余的位數(shù)據(jù)
if (!::fwrite((const void *)lp, dwC, 1, file))
{
::free((void*)pBits);
::fclose(file);
return FALSE;
}
// 位數(shù)據(jù)已無用,釋放
::free((void*)pBits);
// 關(guān)閉文件
::fclose(file);
return TRUE;
}
/*************************************************************************
*
* SaveBaseSpecifyFormat()
*
* 參數(shù)說明:
*
* WORD nBitsPerPixel - 指定的格式(即每像素占多少位)
*
* 返回值:
*
* BOOL - 如果成功返回TRUE,否則返回FALSE
*
* 描述:
*
* 以指定的顏色格式保存本身類中的位圖到原來的文件中
*
* 注:
*
* # 如果指定的文件已經(jīng)存在,則函數(shù)將覆蓋該文件
* # 如果本身類中原來沒有位圖,函數(shù)返回FALSE
* # 如果文件沒有打開或是寫文件時出錯,函數(shù)返回FALSE
* # 如果指定的位數(shù)是非法值(1,4,8,16,24,32是合法值),函數(shù)返回FALSE
* # 函數(shù)并不修改類中信息塊的內(nèi)容
*
************************************************************************/
BOOL CBmpProc::SaveBaseSpecifyFormat(WORD nBitsPerPixel)
{
// 如果本身類中原來沒有位圖,函數(shù)返回FALSE
if (!IsValid())
return FALSE;
ASSERT(m_pInfo);
// 應(yīng)該有文件名
if (m_cFileName.IsEmpty())
return FALSE;
// 檢測位數(shù)合法性
if (!IsValidDibFormat(nBitsPerPixel))
return FALSE;
LPBITMAPINFO pTempInfo;
BOOL bRet;
// 獲取指定格式DIB的信息塊
LPBITMAPINFO pInfo = GetSpecifyFormatInfo(nBitsPerPixel);
if (!pInfo)
return FALSE;
// 保存原始信息塊
pTempInfo = m_pInfo;
m_pInfo = pInfo; // 以原文件名存儲
bRet = SaveBaseSpecifyFileName((LPCTSTR)m_cFileName);
m_pInfo = pTempInfo;
::free((void*)pInfo);
return bRet;
}
/*************************************************************************
*
* Create()
*
* 參數(shù)說明:
*
* int width - 創(chuàng)建位圖的寬度
* int height - 創(chuàng)建位圖的高度
* WORD nBitCount - 創(chuàng)建位圖中每個像素所占的位數(shù)
* const void *lpBits - 新位圖的初始化位數(shù)據(jù)(可以是NULL)
*
* 返回值:
*
* BOOL - 如果成功返回TRUE,否則返回FALSE
*
* 描述:
*
* 根據(jù)指定的數(shù)據(jù)創(chuàng)建一個位圖,并貼入本身類中
*
* 注:
*
* # 入口參數(shù)width和height不能是0,如果指定了0,函數(shù)返回FALSE
* # 入口參數(shù)nBitCount的有效值可以是1,4,8,16,24,32,其它的值將視為非法
* # 如果本身類中原來存在圖像,則調(diào)用函數(shù)成功之后,原來的圖像將被刪除
* # 如果入口參數(shù)lpBits是NULL,則新創(chuàng)建的位不被初始化
*
************************************************************************/
BOOL CBmpProc::Create(CSize size,
WORD nBitCount,
const void *lpBits)
{
return Create(size.cx, size.cy, nBitCount, lpBits);
}
BOOL CBmpProc::Create(int width,
int height,
WORD nBitCount,
const void *lpBits)
{
// 檢測寬度和高度值
if ((width==0)||(height==0))
return FALSE;
// 檢測位數(shù)合法性
if (!IsValidDibFormat(nBitCount))
return FALSE;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -