📄 mypicture.cpp
字号:
// MyPicture.cpp: implementation of the CMyPicture class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MyPicture.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CMyPicture::CMyPicture()
{
}
CMyPicture::~CMyPicture()
{
FreeData();
}
BOOL CMyPicture::LoadData(CString Path)
{
//释放以前的数据
FreeData();
//文件句柄
HFILE hf;
//Bitmap文件信息头
BITMAPINFOHEADER bi;
//指向BITMAPINFOHEADER结构的指针
LPBITMAPINFOHEADER lpImgData;
//Bitmap文件头
BITMAPFILEHEADER bf;
//指向逻辑调色板结构的指针
LOGPALETTE *pPal;
//指向RGBQUAD结构的指针
LPRGBQUAD lpRGB;
//用来保存设备中原来的调色板
HPALETTE hPrevPalette;
//设备句柄
HDC hDc;
//存储调色板的局部内存句柄
HLOCAL hPal;
//每一行的字节数
DWORD LineBytes;
//实际的图象数据占用的字节数
DWORD ImgSize;
//调色板数组中的颜色个数
DWORD NumColors;
DWORD i;
HGLOBAL hImgData;
//打开文件
if((hf =_lopen(Path,OF_READ))==HFILE_ERROR)
{
//MessageBox(NULL,"打开文件失败!","加载失败", MB_OK|MB_ICONEXCLAMATION);
return FALSE;
}
//将BITMAPFILEHEADER结构从文件中读出,填写到bf中
_lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER));
//将BITMAPINFOHEADER结构从文件中读出,填写到bi中
_lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER));
//得到每行的字节数,注意必须为4的倍数
LineBytes=(DWORD)((bi.biWidth*bi.biBitCount + 31)/32 * 4);
//得到实际的图象数据占用的字节数
ImgSize=(DWORD)LineBytes*bi.biHeight;
//如果bi.biClrUsed不为零,即为实际用到的颜色数
if(bi.biClrUsed!=0)
NumColors=(DWORD)bi.biClrUsed;
//否则,用到的颜色数为2biBitCount
else
{
switch(bi.biBitCount){
case 1:
NumColors=2;
break;
case 4:
NumColors=16;
break;
case 8:
NumColors=256;
break;
case 24:
NumColors=0; //对于真彩色图,没用到调色板
break;
default: //其它的颜色数,不做处理。
//MessageBox(NULL,"不支持的文件格式!","加载失败", MB_OK|MB_ICONEXCLAMATION);
//关闭文件
_lclose(hf);
return FALSE;
}
}
//计算出的偏移量不等于实际偏移量,说明文件有错误
if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD) + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)))
{
//MessageBox(NULL,"文件错误!","加载失败",MB_OK|MB_ICONEXCLAMATION);
//关闭文件
_lclose(hf);
return FALSE;
}
bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + NumColors*sizeof(RGBQUAD)+ImgSize;
//分配内存,大小为BITMAPINFOHEADER结构长度加调色板+实际位图
if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
{
//分配内存错误
//MessageBox(NULL,"分配内存失败!","加载失败",MB_OK|MB_ICONEXCLAMATION);
//关闭文件
_lclose(hf);
return FALSE;
}
//指针lpImgData指向该内存区
lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
//文件指针重新定位到BITMAPINFOHEADER开始处
_llseek(hf,sizeof(BITMAPFILEHEADER),SEEK_SET);
//将文件内容读入lpImgData
_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)+(long)NumColors*sizeof(RGBQUAD)+ImgSize);
//关闭文件
_lclose(hf);
//NumColors不为零,说明用到了调色板
if(NumColors!=0)
{
//为逻辑调色板分配局部内存
//大小为逻辑调色板结构长度 + NumColors * sizeof(PALETTENTRY)
hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+NumColors* sizeof(PALETTEENTRY));
//指针pPal指向该内存区
pPal =(LOGPALETTE *)LocalLock(hPal);
//填写逻辑调色板结构的头
pPal->palNumEntries = (WORD)NumColors;
pPal->palVersion = 0x300;
//lpRGB指向的是调色板开始的位置
lpRGB = (LPRGBQUAD)((LPSTR)lpImgData+(DWORD)sizeof(BITMAPINFOHEADER));
//填写每一项
for (i = 0; i < NumColors; i++)
{
pPal->palPalEntry[i].peRed=lpRGB->rgbRed;
pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;
pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;
pPal->palPalEntry[i].peFlags=(BYTE)0;
lpRGB++; //指针移到下一项
}
//产生逻辑调色板
hPalette=CreatePalette(pPal);
//释放内存
LocalUnlock(hPal);
LocalFree(hPal);
}
//获得设备上下文句柄
hDc=GetDC(NULL);
//如果刚才产生了逻辑调色板
if(hPalette)
{
//将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在hPrevPalette
hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
RealizePalette(hDc);
}
//产生位图句柄
hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData,
(LONG)CBM_INIT,
(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),
(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
//将原来的调色板(如果有的话)选入设备上下文句柄
if(hPalette && hPrevPalette)
{
SelectPalette(hDc,hPrevPalette,FALSE);
RealizePalette(hDc);
}
//释放设备上下文
ReleaseDC(NULL,hDc);
//解锁内存区
GlobalUnlock(hImgData);
//装载成功
return TRUE;
}
void CMyPicture::Display(CDC *pDC)
{
//hBitmap不为NULL,表示已经装载了图片
if (hBitmap)
{
//建立一个内存设备上下文
HDC hMemDC;
hMemDC = CreateCompatibleDC(pDC->m_hDC);
//有调色板
if (hPalette)
{
//将调色板选入屏幕设备上下文
SelectPalette (pDC->m_hDC, hPalette, FALSE);
//将调色板选入内存设备上下文
SelectPalette (hMemDC, hPalette, FALSE);
RealizePalette (pDC->m_hDC);
}
//将位图选入内存设备上下文
SelectObject(hMemDC, hBitmap);
//显示位图
BitBlt(pDC->m_hDC, m_Left, m_Top, m_Width, m_Height, hMemDC, 0, 0, SRCCOPY);
//释放内存设备上下文
DeleteDC(hMemDC);
}
}
void CMyPicture::FreeData()
{
//释放图片对象
if (hBitmap)
DeleteObject(hBitmap);
//释放调色板对象
if (hPalette)
DeleteObject(hPalette);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -