📄 cdib.cpp
字号:
*/
BOOL CDib::SetSystemPalette(CDC* pDC)
{
//如果DIB不具备调色板,则需要利用系统的调色板
if(m_nColorTableEntries != 0) return FALSE;
//为设备上下文创建中间调色板,并将其与CPalette对象连接
m_hPalette = ::CreateHalftonePalette(pDC->GetSafeHdc());
//返回
return TRUE;
}
/***********************************************************
* \函数名称:
* UsePalette()
* \输入参数:
* CDC* pDC -要实现调色板的设备上下文指针
* BOOL bBackground -标记为FALSE(默认值),并且应用程序正在前台运行
* -则Windows将把该调色板作为前台调色板来实现。
* -标记为TRUE,则Windows将把该调色板作为后台调色板来实现
* \返回值:
* UINT -如果成功,则返回映射到系统调色板的逻辑调色板的表项数
* -否则返回GDI_ERROR
* \说明:
* 该函数将CDib对象的逻辑调色板选入设备上下文,然后实现该调色板
* Draw成员函数在绘制DIB之前调用UsePalette
************************************************************
*/
UINT CDib::UsePalette(CDC* pDC,BOOL bBackground/* = FALSE*/)
{
//判断是否存在调色板
if(m_hPalette == NULL) return 0;
//得到设备上下文句柄
HDC hdc = pDC->GetSafeHdc();
//选择调色板到设备上下文
::SelectPalette(hdc,m_hPalette,bBackground);
//实现该调色板
return ::RealizePalette(hdc);
}
/***********************************************************
* \函数名称:
* CopyPalette()
* \输入参数:
* HPALETTE hPalSrc -需要拷贝的源调色板句柄
* \返回值:
* HPALETTE -如果成功,则返回拷贝的调色板句柄
* \说明:
* 该函数将创建一个新的调色板,并从指定的调色板拷贝调色板内容
************************************************************
*/
HPALETTE CDib::CopyPalette(HPALETTE hPalSrc)
{
//调色板指针,临时变量
PLOGPALETTE plogPal;
//声明一个调色板句柄和一个临时句柄
HPALETTE hPalette;
HANDLE hTemp;
//调色板表项数
int iNumEntries = 0;
//获取调色板中的表项数
iNumEntries = GetPaletteEntries(hPalSrc,0,iNumEntries,NULL);
if(iNumEntries == 0)
return (HPALETTE)NULL;
//分配调色板内存,得到句柄
hTemp = GlobalAlloc(GHND,sizeof(DWORD) + sizeof(PALETTEENTRY) * iNumEntries);
if(!hTemp)
return (HPALETTE)NULL;
//得到调色板的指针
plogPal = (PLOGPALETTE)GlobalLock(hTemp);
if(!plogPal)
return (HPALETTE)NULL;
//设置调色板的信息
plogPal->palVersion = 0x300;
plogPal->palNumEntries = (WORD)iNumEntries;
//获取逻辑调色板中指定范围的调色板表项
GetPaletteEntries(hPalSrc,0,iNumEntries,plogPal->palPalEntry);
//创建一个Windows调色板
hPalette = CreatePalette(plogPal);
//释放已分配的内存
GlobalUnlock(hTemp);
GlobalFree(hTemp);
//返回调色板句柄
return hPalette;
}
/***********************************************************
* \函数名称:
* GetSystemPalette()
* \输入参数:
* 无
* \返回值:
* HPALETTE -系统调色板句柄
* \说明:
* 该函数获得当前正使用的系统调色板的句柄
************************************************************
*/
HPALETTE CDib::GetSystemPalette()
{
//设备上下文
HDC hDC;
//声明调色板句柄、指针等临时变量
static HPALETTE hPal = NULL;
HANDLE hLogPal;
LPLOGPALETTE lpLogPal;
//当前系统调色板的颜色数
int nColors;
//获得当前系统设备上下文
hDC = GetDC(NULL);
if(!hDC)
return NULL;
//获得当前系统调色板的颜色数目
nColors = (1<<(GetDeviceCaps(hDC,BITSPIXEL) * GetDeviceCaps(hDC,PLANES)));
//给调色板分配内存
hLogPal = GlobalAlloc(GHND,sizeof(LOGPALETTE) + nColors * sizeof(PALETTEENTRY));
if(!hLogPal)
return NULL;
//得到调色板内存指针
lpLogPal = (LPLOGPALETTE)GlobalLock(hLogPal);
//设置调色板信息
lpLogPal->palVersion = 0x300;
lpLogPal->palNumEntries = nColors;
//将系统的调色板拷贝到当前的逻辑调色板中
GetSystemPaletteEntries(hDC,0,nColors,
(LPPALETTEENTRY)(lpLogPal->palPalEntry));
//创建Windows调色板
hPal = CreatePalette(lpLogPal);
//释放已分配内存并删除临时对象
GlobalUnlock(hLogPal);
GlobalFree(hLogPal);
ReleaseDC(NULL,hDC);
//返回
return hPal;
}
/***********************************************************
* \函数名称:
* CreateBitmap()
* \输入参数:
* CDC* pDC -设备上下文指针
* \返回值:
* HBITMAP -到GDI位图的句柄,如果不成功,则为 NULL
* -该句柄不是作为公共数据成员存储的
* \说明:
* 从已有的DIB中创建DDB位图
* 不要与CreateSection混淆了,后者的作用是生成DIB并保存句柄
************************************************************
*/
HBITMAP CDib::CreateBitmap(CDC* pDC)
{
//如果不存在图像数据,则返回NULL
if(m_dwSizeImage == 0) return NULL;
//用指定的DIB来创建DDB,并用DIB信息初始化位图的图像位
HBITMAP hBitmap = ::CreateDIBitmap(pDC->GetSafeHdc(),m_lpBMIH,
CBM_INIT,m_lpImage,(LPBITMAPINFO)m_lpBMIH,DIB_RGB_COLORS);
ASSERT(hBitmap != NULL);
//返回DDB位图句柄
return hBitmap;
}
/***********************************************************
* \函数名称:
* CreateSection()
* \输入参数:
* CDC* pDC -设备上下文指针
* \返回值:
* HBITMAP -到GDI位图的句柄,如果不成功,则为 NULL
* -该句柄也是作为公共数据成员存储的
* \说明:
* 通过调用Win32 SDK的CreateDIBSection函数创建一个DIB段
* 图像内存将不被初始化
************************************************************
*/
HBITMAP CDib::CreateSection(CDC* pDC/*=NULL*/)
{
//如果信息头为空,不作任何处理
if(m_lpBMIH == NULL) return NULL;
//如果图像数据不存在,不作任何处理
if(m_lpImage != NULL) return NULL;
//创建一个DIB段
m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),(LPBITMAPINFO)m_lpBMIH,
DIB_RGB_COLORS,(LPVOID*)&m_lpImage,NULL,0);
ASSERT(m_lpImage != NULL);
//返回HBITMAP句柄
return m_hBitmap;
}
/***********************************************************
* \函数名称:
* ComputePaletteSize()
* \输入参数:
* int nBitCount -像素位数
* \返回值:
* 无
* \说明:
* 根据像素位数计算调色板的尺寸
************************************************************
*/
void CDib::ComputePaletteSize(int nBitCount)
{
if((m_lpBMIH == NULL) || (m_lpBMIH->biClrUsed == 0))
{
switch(nBitCount)
{
case 1:
m_nColorTableEntries = 2;
break;
case 4:
m_nColorTableEntries = 16;
break;
case 8:
m_nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
m_nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
}
else
{
m_nColorTableEntries = m_lpBMIH->biClrUsed;
}
ASSERT((m_nColorTableEntries >= 0) && (m_nColorTableEntries <= 256));
}
/***********************************************************
* \函数名称:
* ComputeMetrics()
* \输入参数:
* 无 -
* \返回值:
* 无
* \说明:
* 计算调色板和位图的尺寸
************************************************************
*/
void CDib::ComputeMetrics()
{
if(m_lpBMIH->biSize != sizeof(BITMAPINFOHEADER))
{
TRACE("Not a valid Windows bitmap -- probably an OS/2 bitmap\n");
throw new CException;
}
m_dwSizeImage = m_lpBMIH->biSizeImage;
if(m_dwSizeImage == 0)
{
DWORD dwBytes = ((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) / 32;
if(((DWORD) m_lpBMIH->biWidth * m_lpBMIH->biBitCount) % 32)
{
dwBytes++;
}
dwBytes *= 4;
m_dwSizeImage = dwBytes * m_lpBMIH->biHeight; // no compression
}
m_lpvColorTable = (LPBYTE) m_lpBMIH + sizeof(BITMAPINFOHEADER);
}
/***********************************************************
* \函数名称:
* 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;
}
/***********************************************************
* \函数名称:
* ConvertDDBToDIB()
* \输入参数:
* HBITMAP hBitmap -指向源数据的BITMAP句柄
* CDib* pDibDst -指向转换目标的CDib对象指针
* \返回值:
* BOOL -如果成功,则返回TRUE
* \说明:
* 该函数将源BITMAP类pDibSrc中的数据拷贝到pDibDst中,并对相应的数据成员赋值
************************************************************
*/
BOOL CDib::ConvertDDBToDIB(HBITMAP hBitmap, HPALETTE hPal)
{
//声明一个BITMAP结构
BITMAP bm;
//设备上下文
HDC hDC;
//像素位数
WORD biBitCount;
//调色板表项数
int nColorTableEntries;
//如果hBitmap句柄无效,则返回
if(!hBitmap)
{
return FALSE;
}
//释放已分配的内存
Empty();
//填充图像数据到bm中,其中最后一个参数表示接收这个指定的对象的指针
if(!GetObject(hBitmap,sizeof(BITMAP),(LPBYTE)&bm))
{
return FALSE;
}
//计算像素位数
biBitCount = bm.bmPlanes * bm.bmBitsPixel;
if(biBitCount <= 1)
biBitCount = 1;
else if(biBitCount <= 4)
biBitCount = 4;
else if(biBitCount <= 8)
biBitCount = 8;
else
biBitCount = 24;
//计算调色板的尺寸
//如果biClrUsed为零,则用到的颜色数为2的biBitCount次方
switch(biBitCount)
{
case 1:
nColorTableEntries = 2;
break;
case 4:
nColorTableEntries = 16;
break;
case 8:
nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
nColorTableEntries = 0;
break;
default:
ASSERT(FALSE);
}
ASSERT((nColorTableEntries >= 0) && (nColorTableEntries <= 256));
m_nColorTableEntries = nColorTableEntries;
//分配DIB信息头和调色板的内存
m_lpBMIH = (LPBITMAPINFOHEADER) new char
[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries];
m_nBmihAlloc = m_nImageAlloc = crtAlloc;
m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
m_lpBMIH->biWidth = bm.bmWidth;
m_lpBMIH->biHeight = bm.bmHeight;
m_lpBMIH->biPlanes = 1;
m_lpBMIH->biBitCount = biBitCount;
m_lpBMIH->biCompression = BI_RGB;
m_lpBMIH->biSizeImage = 0;
m_lpBMIH->biXPelsPerMeter = 0;
m_lpBMIH->biYPelsPerMeter = 0;
m_lpBMIH->biClrUsed = nColorTableEntries;
m_lpBMIH->biClrImportant = nColorTableEntries;
//获得设备上下文句柄
hDC = GetDC(NULL);
//如果没有指定调色板,则从系统中获得当前的系统调色板
if(hPal == NULL)
{
hPal = GetSystemPalette();
}
hPal = SelectPalette(hDC,hPal,FALSE);
RealizePalette(hDC);
//调用GetDIBits填充信息头,并获得图像数据的尺寸
GetDIBits(hDC,hBitmap,0,(UINT)m_lpBMIH->biHeight,NULL,
(LPBITMAPINFO)m_lpBMIH,DIB_RGB_COLORS);
//如果没正确的获得图像数据尺寸,则重新计算
if(m_lpBMIH->biSizeImage == 0)
{
m_lpBMIH->biSizeImage = (((bm.bmWidth * biBitCount) + 31)/32*4) * bm.bmHeight;
}
//分配存放图像数据的内存
m_lpImage = (LPBYTE) new char[m_lpBMIH->biSizeImage];
//调用GetDIBits加载图像数据,给出图像数据指针
//如果加载不成功,释放内存,返回FALSE
if(GetDIBits(hDC,hBitmap,0,(UINT)m_lpBMIH->biHeight,(LPBYTE)m_lpImage,
(LPBITMAPINFO)m_lpBMIH,DIB_RGB_COLORS) == 0)
{
Empty();
SelectPalette(hDC,hPal,TRUE);
RealizePalette(hDC);
ReleaseDC(NULL,hDC);
return FALSE;
}
//删除临时变量
SelectPalette(hDC,hPal,TRUE);
RealizePalette(hDC);
ReleaseDC(NULL,hDC);
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -