更新日期:2010-12-15
代码下载:demo.zip (请不要直接使用迅雷下载)
测试环境:VC6.0+WinXP
图片预览:
━━━━━━━━━━━━━━━━━━━━━━━━
以下代码演示如何实现透明图片(或者一般图片)在背景图上移动效果。
一、原理简介:
1.我们把所以图画到一个内存DC里,然后在Blt到屏幕,就是所谓的双缓冲了。
2.在内存DC里画图时,先把背景图画到内存DC,再画上前景需要移动的图片就可以了
二、具体到我们下面的例子:
1.定义2个CDrawBitmap对象,分别加载背景位图和前景移动的小飞机。
CDrawBitmap g_bmp1("4244123431.bmp");
CDrawBitmap g_bmp2("plane.bmp");
2.鼠标按下移动,或者接收到时钟消息时就实现双缓冲。
虽然代码有点“繁琐”,但记得我们关心的
主要是下面代码中hMemDC。所有绘图代码都在这里进行。
你经常不是这样调用的吗:
//屏幕上打印字体,画矩形
HDC hdc=::GetDC(m_hWnd);
::TextOut(hdc.......);
::RectangleRect(hdc......);
::ReleaseDC(m_hWnd,hdc) ;
而在双缓冲里,只需把所有需要用到屏幕hdc的函数中的hdc替换成hMemDC,如:
//屏幕上打印字体,画矩形
::TextOut(hMemDC.......);
::RectangleRect(hMemDC......);
具体到我们这里的动画,就是:
g_bmp1.Draw(hMemDC,0,0,600,600); //画背景图片到内存DC
g_bmp2.DrawTransparent(hMemDC,point.x-50,point.y-100); //画移动的前进小图片
画好后再调用BitBlt把内存hMemDC所有画好的东西拷贝到屏幕hScrDC
BitBlt(hScrDC,0,60,600,600,hMemDC,0,0,SRCCOPY);
希望对你有所帮助,谢谢!愿一切吉祥,阿弥陀佛!
/**************************************************************************** CDrawBitmap封装了一些画图片的函数。 调用如下: CDrawBitmap g_bmp1("D://My Documents//My Pictures//风景图片//4244123431.bmp"); g_bmp1.Draw(m_hWnd); CDrawBitmap g_bmp2("D://My Documents//My Pictures//风景图片//plane.bmp"); g_bmp2.DrawTransparent(m_hWnd); CDrawBitmap g_bmp3("D://My Documents//My Pictures//风景图片//jzg2.bmp"); g_bmp3.DrawTransparent(m_hWnd); ****************************************************************************/ //使用TransparentBlt需要添加 #pragma comment(lib,"msimg32.lib") #pragma comment(lib,"msimg32.lib") class CDrawBitmap { private: HBITMAP m_bitmap; int m_bitmap_cx; int m_bitmap_cy; public: CDrawBitmap() {} CDrawBitmap(TCHAR * PicturePath) { LoadPicture(PicturePath); } CDrawBitmap(WORD ResourceID) { LoadResource(ResourceID); } ~CDrawBitmap() { ::DeleteObject(m_bitmap);} bool LoadPicture(TCHAR * PicturePath) { m_bitmap=(HBITMAP)LoadImage(NULL, //应用程序实例 PicturePath, //路径 IMAGE_BITMAP, 0, //如果不置0,则此参数指定m_bitmap的宽(位图被拉伸) 0, //如果不置0,则此参数指定m_bitmap的高(位图被拉伸) LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_DEFAULTSIZE); if (!m_bitmap) return false; BITMAP bmp; GetObject(m_bitmap,sizeof(BITMAP),(LPSTR)&bmp); m_bitmap_cx=bmp.bmWidth; m_bitmap_cy=bmp.bmHeight; return true; } bool LoadResource(WORD ResourceID) { m_bitmap=LoadBitmap(GetModuleHandle(NULL),MAKEINTRESOURCE (ResourceID) ); if (!m_bitmap) return false; BITMAP bmp; GetObject(m_bitmap,sizeof(BITMAP),(LPSTR)&bmp); m_bitmap_cx=bmp.bmWidth; m_bitmap_cy=bmp.bmHeight; return true; } void Draw(HWND hWnd=NULL,int x=0,int y=0,int width=100,int height=100) { HDC hScrDC=GetDC(hWnd); //创建屏幕DC Draw(hScrDC,x,y,width,height); ::ReleaseDC(hWnd,hScrDC) ; //释放屏幕DC } void Draw(HDC hScrDC,int x=0,int y=0,int width=100,int height=100) { HDC hMemDC=CreateCompatibleDC(hScrDC); //创建内存DC ::SelectObject(hMemDC,m_bitmap); //把位图选进内存DC BitBlt(hScrDC,x,y,width,height,hMemDC,0,0,SRCCOPY); //内存DC映射到屏幕DC ::DeleteDC(hMemDC) ; //删除内存DC } void DrawTransparent(HWND hWnd=NULL,int x=0,int y=0) { HDC hScrDC=GetDC(hWnd); //创建屏幕DC DrawTransparent(hScrDC,x,y); ::ReleaseDC(hWnd,hScrDC) ; //释放屏幕DC } //不进行拉伸处理,如需要,请自行修改代码TransparentBlt中的参数 //使用TransparentBlt需要添加 #pragma comment(lib,"msimg32.lib") void DrawTransparent(HDC hScrDC,int x=0,int y=0,UINT crTransparent=RGB(255,255,255)) { HDC hMemDC=CreateCompatibleDC(hScrDC); //创建内存DC ::SelectObject(hMemDC,m_bitmap); //把位图选进内存DC ::TransparentBlt(hScrDC,x,y,m_bitmap_cx,m_bitmap_cy,hMemDC,0,0,m_bitmap_cx,m_bitmap_cy,crTransparent); ::DeleteDC(hMemDC) ; //删除内存DC } void DrawStretch(HWND hWnd=NULL,int x=0,int y=0,int width=100,int height=100) { HDC hScrDC=GetDC(hWnd); //创建屏幕DC DrawStretch(hScrDC,x,y,width,height); ::ReleaseDC(hWnd,hScrDC) ; //释放屏幕DC } void DrawStretch(HDC hScrDC=NULL,int x=0,int y=0,int width=100,int height=100) { HDC hMemDC=CreateCompatibleDC(hScrDC); //创建内存DC ::SelectObject(hMemDC,m_bitmap); //把位图选进内存DC SetStretchBltMode(hScrDC,COLORONCOLOR); //一定要先调用这个 StretchBlt(hScrDC,x,y,width,height,hMemDC,0,0,m_bitmap_cx,m_bitmap_cy,SRCCOPY); //内存DC映射到屏幕DC ::DeleteDC(hMemDC) ; //删除内存DC } }; void DrawBitmap(HBITMAP m_bitmap,HDC hScrDC,int x=0,int y=0,int width=100,int height=100) { HDC hMemDC=CreateCompatibleDC(hScrDC); //创建内存DC ::SelectObject(hMemDC,m_bitmap); //把位图选进内存DC BitBlt(hScrDC,x,y,width,height,hMemDC,0,0,SRCCOPY); //内存DC映射到屏幕DC ::DeleteDC(hMemDC) ; //删除内存DC } void DrawBitmap(HBITMAP m_bitmap,HWND hWnd=NULL,int x=0,int y=0,int width=100,int height=100) { HDC hScrDC=GetDC(hWnd); //创建屏幕DC DrawBitmap(m_bitmap,hScrDC,x,y,width,height); ::ReleaseDC(hWnd,hScrDC) ; //释放屏幕DC } CDrawBitmap g_bmp1("4244123431.bmp"); CDrawBitmap g_bmp2("plane.bmp"); //stop timer void CDemoDlg::OnLButtonDown(UINT nFlags, CPoint point) { KillTimer(1); CDialog::OnLButtonDown(nFlags, point); } //begin timer; void CDemoDlg::OnLButtonUp(UINT nFlags, CPoint point) { SetTimer(1,10,NULL); CDialog::OnLButtonUp(nFlags, point); } void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point) { if (nFlags&MK_LBUTTON) { /*************************************************** 步骤一:创建。 1.主要关心的是CreateCompatibleBitmap的后两个参数, 你往内存hMemDC里画的东东就在这个这个范围内 2.如果你已经有一个屏幕dc了,就去掉 HDC hScrDC=::GetDC(m_hWnd)和::ReleaseDC(m_hWnd,hScrDC) 这两行代码, 直接使用已有的屏幕dc代替下面代码中的所有hScrDC **************************************************/ HDC hScrDC=::GetDC(m_hWnd); //创建屏幕DC HDC hMemDC=CreateCompatibleDC(hScrDC); //创建内存DC HBITMAP bitmap=::CreateCompatibleBitmap(hScrDC,600,600); //创建兼容位图 HBITMAP OldBitmap=(HBITMAP)::SelectObject(hMemDC,bitmap); //把位图选进内存DC /*************************************************** 步骤二:绘图。 使用hMemDC绘图,就像你平时绘图一样操作 绘图代码主要在这里完成 **************************************************/ g_bmp1.Draw(hMemDC,0,0,600,600); //画背景图片到内存DC g_bmp2.DrawTransparent(hMemDC,point.x-50,point.y-100); //画移动的前进小图片 /*************************************************** 步骤三:将内存DC图拷贝到屏幕DC上进行显示。 1.BitBlt前4个参数nXDest,nYDest,nWidth,nHeight.确定屏幕DC上的一个矩形区域。 将来要显示在屏幕上的图形范围就在这4个参数所决定的矩形区域内。 2.BitBlt后面2个坐标参数x,y指定从内存hMemDC的哪个位置开始拷贝到屏幕DC上 **************************************************/ BitBlt(hScrDC,0,60,600,600,hMemDC,0,0,SRCCOPY); /*************************************************** 步骤四:最后的收尾工作(删除或释放资源) **************************************************/ ::SelectObject(hMemDC,OldBitmap); ::DeleteObject(bitmap); //释放位图所占Memory,不释放也可以(The system automatically deletes these resources when the process that created them terminates) ::DeleteDC(hMemDC) ; //删除内存DC ::ReleaseDC(m_hWnd,hScrDC) ; //释放屏幕DC } CDialog::OnMouseMove(nFlags, point); } void CDemoDlg::OnTimer(UINT nIDEvent) { /*************************************************** 步骤一:创建。 1.主要关心的是CreateCompatibleBitmap的后两个参数, 你往内存hMemDC里画的东东就在这个这个范围内 2.如果你已经有一个屏幕dc了,就去掉 HDC hScrDC=::GetDC(m_hWnd)和::ReleaseDC(m_hWnd,hScrDC) 这两行代码, 直接使用已有的屏幕dc代替下面代码中的所有hScrDC **************************************************/ HDC hScrDC=::GetDC(m_hWnd); //创建屏幕DC HDC hMemDC=CreateCompatibleDC(hScrDC); //创建内存DC HBITMAP bitmap=::CreateCompatibleBitmap(hScrDC,600,600); //创建兼容位图 HBITMAP OldBitmap=(HBITMAP)::SelectObject(hMemDC,bitmap); //把位图选进内存DC /*************************************************** 步骤二:绘图。 使用hMemDC绘图,就像你平时绘图一样操作 绘图代码主要在这里完成 **************************************************/ static int x=0; x+=1; if (x>400) x=0; g_bmp1.Draw(hMemDC,0,0,600,600); //画背景图片到内存DC g_bmp2.DrawTransparent(hMemDC,x,100); //画移动的前进小图片 /*************************************************** 步骤三:将内存DC图拷贝到屏幕DC上进行显示。 1.BitBlt前4个参数nXDest,nYDest,nWidth,nHeight.确定屏幕DC上的一个矩形区域。 将来要显示在屏幕上的图形范围就在这4个参数所决定的矩形区域内。 2.BitBlt后面2个坐标参数x,y指定从内存hMemDC的哪个位置开始拷贝到屏幕DC上 **************************************************/ BitBlt(hScrDC,0,60,600,600,hMemDC,0,0,SRCCOPY); /*************************************************** 步骤四:最后的收尾工作(删除或释放资源) **************************************************/ ::SelectObject(hMemDC,OldBitmap); ::DeleteObject(bitmap); //释放位图所占Memory,不释放也可以(The system automatically deletes these resources when the process that created them terminates) ::DeleteDC(hMemDC) ; //删除内存DC ::ReleaseDC(m_hWnd,hScrDC) ; //释放屏幕DC CDialog::OnTimer(nIDEvent); } |
推荐:
谈老师的BLOG (佛教大德)
狮姐的博客(狮子窝,学佛与灵魂之探究)
大方广(学习传统文化)
慈善点击(轻松一点,行善积德,何乐不为)
电影《地球公民》(揭示不为人知的一面)
心向光明 远离邪淫(现世警钟,不可不看)
戒淫(上篇)(正淫节欲,戒除邪淫)
戒淫(中篇)(纵欲之乐,忧患随之)
公民教育——命由我造