總結一下關于位圖的幾種用法。
說到這還是開頭給大家介紹一下,有關位圖的知識吧,以及對于我們比較有用的幾個關于位圖的結構體。
一.位圖結構如下:
---- 一、BMP文件結構
---- 1. BMP文件組成
---- BMP文件由文件頭、位圖信息頭、顏色信息和圖形數據四部分組成。
---- 2. BMP文件頭
---- BMP文件頭數據結構含有BMP文件的類型、文件大小和位圖起始位置等信息。
---- 其結構定義如下:
typedef struct tagBITMAPFILEHEADER
{
WORDbfType; // 位圖文件的類型,必須為BM
DWORD bfSize; // 位圖文件的大小,以字節為單位
WORDbfReserved1; // 位圖文件保留字,必須為0
WORDbfReserved2; // 位圖文件保留字,必須為0
DWORD bfOffBits; // 位圖數據的起始位置,以相對于位圖
// 文件頭的偏移量表示,以字節為單位
} BITMAPFILEHEADER;
---- 3. 位圖信息頭
BMP位圖信息頭數據用于說明位圖的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本結構所占用字節數
LONGbiWidth; // 位圖的寬度,以像素為單位
LONGbiHeight; // 位圖的高度,以像素為單位
WORD biPlanes; // 目標設備的級別,必須為1
WORD biBitCount// 每個像素所需的位數,必須是1(雙色),
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位圖壓縮類型,必須是 0(不壓縮),
// 1(BI_RLE8壓縮類型)或2(BI_RLE4壓縮類型)之一
DWORD biSizeImage; // 位圖的大小,以字節為單位
LONGbiXPelsPerMeter; // 位圖水平分辨率,每米像素數
LONGbiYPelsPerMeter; // 位圖垂直分辨率,每米像素數
DWORD biClrUsed;// 位圖實際使用的顏色表中的顏色數
DWORD biClrImportant;// 位圖顯示過程中重要的顏色數
} BITMAPINFOHEADER;
---- 4. 顏色表
顏色表用于說明位圖中的顏色,它有若干個表項,每一個表項是一個RGBQUAD類型的結構,定義一種顏色。RGBQUAD結構的定義如下:
typedef struct tagRGBQUAD {
BYTErgbBlue;// 藍色的亮度(值范圍為0-255)
BYTErgbGreen; // 綠色的亮度(值范圍為0-255)
BYTErgbRed; // 紅色的亮度(值范圍為0-255)
BYTErgbReserved;// 保留,必須為0
} RGBQUAD;
顏色表中RGBQUAD結構數據的個數有biBitCount來確定:
當biBitCount=1,4,8時,分別有2,16,256個表項;
當biBitCount=24時,沒有顏色表項。
位圖信息頭和顏色表組成位圖信息,BITMAPINFO結構定義如下:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader; // 位圖信息頭
RGBQUAD bmiColors[1]; // 顏色表
} BITMAPINFO;
下面我們介紹第一種辦法:
//第一種方法,使用WM__CTRLCOLOR來實現
/*******************OnCtlColor中添加的代碼*****************/
HBRUSH CDemoBitmapDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
// TODO: Change any attributes of the DC here
//第一種實現方法
if(nCtlColor=CTLCOLOR_DLG)
{
return brush;
}
// TODO: Return a different brush if the default is not desired
return hbr;
}
BOOL CDemoBitmapDlg::OnInitDialog()
{
//第一種方法,使用wm_ctlcolor來實現
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
brush.CreatePatternBrush(&bitmap);//brush定義在頭文件中CBrush burush
bitmap.deleteobject();
}
第二種方法使用資源文件中導入的IDB_BITMAP來實現
第一步先在資源中導入一個位圖:IDB_BITMAP1
void CDemoBitmapDlg::OnBtnBitmap()
{
// TODO: Add your control notification handler code here
/***************顯示BITMAP的第二種方法**********************/
HBITMAP hBitmap;
CBitmap bitmap;
CClientDC *pDC;
pDC=new CClientDC(this);
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
bitmap.Attach(hBitmap);
CDC CDCompatible;
CDCompatible.CreateCompatibleDC(pDC);//創建兼容DC
CDCompatible.Selectobject(&bitmap);
/*********其它幾種顯示方式********/
/* pDC->BitBlt(0,0,200,200,&CDCompatible,0,0,SRCCOPY);
CDCompatible.SetBkMode(TRANSPARENT);
pDC->StretchBlt(0,0,352,288,&CDCompatible,0,0,352,288,SRCCOPY);
CDCompatible.CreateCompatibleDC(this->GetDC());
CDCompatible.Selectobject(&bitmap); */ //選擇繪圖對象
BITMAP bmp;
bitmap.GetBitmap(&bmp);
pDC->StretchBlt(0,0,bmp.bmWidth,bmp.bmHeight,&CDCompatible,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
CDCompatible.deleteDC();
::deleteobject(&bitmap);
}
第三種方法是通過讀取指定目錄中的位圖文件來顯示(這里分別把它們顯示在Picture控件和Static上面這也是大家通常要用到的):
void CDemoBitmapDlg::OnBtnPic()
{
// TODO: Add your control notification handler code here
/****************向PICTURE控件中動態添加位圖****************************/
HBITMAP hBitmap;
CBitmap bitmap;
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
bitmap.Attach(hBitmap);
m_Pic.SetBitmap(hBitmap);
}
/****************在STATIC中顯示位圖*********************/
void CDemoBitmapDlg::OnBtnStatic()
{
// TODO: Add your control notification handler code here
CBitmap hbmp;
HBITMAP hbitmap;
//將pStatic指向要顯示的地方
CStatic *pStaic;
pStaic=(CStatic*)GetDlgItem(IDC_IMAGE);
// pStaic=(CStatic*)GetDlgItem(IDC_BUTTON1);
//裝載資源 MM.bmp是我的一個文件名,用你的替換
hbitmap=(HBITMAP)::LoadImage (::AfxGetInstanceHandle(),"NetFriend.bmp",
IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
hbmp.Attach(hbitmap);
//獲取圖片格式
BITMAP bm;
hbmp.GetBitmap(&bm);
CDC dcMem;
dcMem.CreateCompatibleDC(GetDC());
CBitmap *poldBitmap=(CBitmap*)dcMem.Selectobject(hbmp);
CRect lRect;
pStaic->GetClientRect(&lRect);
//顯示位圖
pStaic->GetDC()->StretchBlt(lRect.left ,lRect.top ,lRect.Width(),lRect.Height(), &dcMem,0 ,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
dcMem.Selectobject(&poldBitmap);
}
/*****************向BUTTON中添加ICON*****************************/
//方法和導入其它位圖類似,在這里就只做一個說明一下就是了。
HICON hIco;
hIco=AfxGetApp()->LoadIcon(IDI_ICON1);
m_BtnBitmap.SetIcon(hIco);
第四種讀取位圖文件來顯示位圖:
void CDemoBitmapDlg::OnBtnBtmfile()
{
// TODO: Add your control notification handler code here
/*******************通過讀取位圖文件來顯示位圖**********************/
CString strFileName;
strFileName.Format("%s","NetFriend.bmp");
//成位圖信息BITMAPINFO
BITMAPINFO *bitmapinfo=NULL;
BYTE *BmpData=NULL;
CFile file;//讀取位圖信息
//設置文件的打開方式
if(!file.Open(strFileName,Cfile::modeRead|Cfile::typeBinary))
{
return;
}
//BITMAP文件頭結構體
BITMAPFILEHEADER BitmapHead;
//讀取位圖文件頭
if(file.Read(&BitmapHead,sizeof(BITMAPFILEHEADER))!=sizeof(BITMAPFILEHEADER))
{
MessageBox("讀取文件頭失敗!");
return;
}
if(BitmapHead.bfType!=0x4d42)
{
MessageBox("對不起,您讀取的不是位圖文件!");
return;
}
//位圖信息
BITMAPINFOHEADER BitmapInfo;
if(file.Read(&BitmapInfo,sizeof(BITMAPINFOHEADER))!=sizeof(BITMAPINFOHEADER))
{
MessageBox("讀取位圖信息失敗!");
return;
}
if(BitmapInfo.biBitCount!=24)
{
MessageBox("對不起,當前程序只支持24位位圖信息!");
return;
}
bitmapinfo=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)];
if(!bitmapinfo)
{
MessageBox("內存分配失敗!");
return;
}
/*把BMP位圖信息頭中的數據讀取到位圖信息結構中去.*/
memcpy(bitmapinfo,&BitmapInfo,sizeof(BITMAPINFOHEADER));
/*用來得到位圖文件的大小*/
DWORD dataByte=BitmapHead.bfSize-BitmapHead.bfOffBits;
BmpData=(BYTE*)new char[dataByte];
if(!BmpData)
{
MessageBox("內存分配失敗!");
delete bitmapinfo;
delete BmpData;
return;
}
if(file.Read(BmpData,dataByte)!=dataByte)
{
MessageBox("讀取位圖數據失敗!");
return;
}
file.Close();
CClientDC *pDC=new CClientDC(this);
pDC->SetStretchBltMode(COLORONCOLOR);
StretchDIBits(pDC->GetSafeHdc(),200,0,BitmapInfo.biWidth,BitmapInfo.biHeight, 0,0,BitmapInfo.biWidth,BitmapInfo.biHeight,BmpData,bitmapinfo,DIB_RGB_COLORS,SRCCOPY);
}
最后給大家介紹兩個顯示位圖的特效的例子更多的特效顯示(http://www.pconline.com.cn/pcedu/empolder/gj/vc/0504/608259.html):
1> 水平交錯顯示位圖
void CListBmap::OnButton1()
{
// TODO: Add your control notification handler code here
HBITMAP hBitmap;
CBitmap cBitmap;
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp", IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
cBitmap.Attach(hBitmap);
cBitmap.GetBitmap(&bitmap);
int i=0,j=0;
CClientDC *pDC=new CClientDC(this);
CDC memDC;
memDC.CreateCompatibleDC(GetDC());
memDC.Selectobject(&cBitmap);
for(i=0;i<bitmap.bmHeight;i+=2)
{
j=i;
while(j>0)
{
pDC->StretchBlt(0,j-1,bitmap.bmWidth,1,&memDC,0,bitmap.bmHeight-(i-j+1), bitmap.bmWidth,1,SRCCOPY);
pDC->StretchBlt(0,bitmap.bmHeight-j,bitmap.bmWidth,1,&memDC,0,i-j, bitmap.bmWidth,1,SRCCOPY);
j-=2;
}
Sleep(50);
}
}
2>雨點顯示:
void CListBmap::OnButton2()
{
// TODO: Add your control notification handler code here
HBITMAP hBitmap;
CBitmap cBitmap;
hBitmap=(HBITMAP)::LoadImage(::AfxGetInstanceHandle(),"NetFriend.bmp", IMAGE_BITMAP,0,0,LR_LOADFROMFILE|LR_CREATEDIBSECTION);
cBitmap.Attach(hBitmap);
cBitmap.GetBitmap(&bitmap);
int i=0,j=0;
CClientDC *pDC=new CClientDC(this);
CDC memDC;
memDC.CreateCompatibleDC(GetDC());
memDC.Selectobject(&cBitmap);
for ( i=0; i<=bitmap.bmHeight; i++ )
{
for ( j=0; j<=bitmap.bmHeight-i; j++ )
pDC->StretchBlt(
0,j,
//目標設備邏輯橫、縱坐標
bitmap.bmWidth,1,
//顯示位圖的像素寬、高度
&memDC,
//源位圖設備情境對象
0,bitmap.bmHeight-i,
//源位圖的起始橫、縱坐標
bitmap.bmWidth,1,
//源位圖的像素寬、高度
SRCCOPY);
Sleep(20);
}
}
轉自:http://blog.csdn.net/xyshu/archive/2008/08/20/2802162.aspx