GDI C++(2) 位图的绘制
在GDI有一个特点: 就是所有的图片绘制,都是通过DC来完成的。DC之间是可以相互传递的。
两个DC之中的图形 通过DC--->DC 来相互传递信息。
无论
位图--->屏幕
位图--->位图
屏幕---->位图
屏幕----->屏幕
他们所使用的都是DC-->DC之间的传递。
其关键点便是:
如何获得各自的DC
对于屏幕:
直接使用GetDC() ReleaseDC() 便可
::GetDC() 返回的是CDC*
对于图片:
CBitmap 不支持DC
CImage 获得DC
- CImage img;
- img.Load(imageFilePath);
- CDC *pDC;
- pDC=CDC::FromHandle(img.GetDC());
- // use pDC here
- img.ReleaseDC();
注意:
::GetDC() 返回的是CDC*
而CImage::GetDC() 返回的HDC
对图像进行操作
::GetDC() 所获得的是屏幕的DC, 使用此DC ,可以对屏幕进行绘图。
如果我们想在某一个位图的基础上,再次绘图的话,便不能简单的使用::GetDC()了,因为它只是负责在屏幕上绘图。
那怎么办呢?
既然所有的绘图都是在DC上进行绘图,所以我们必须把这个位图选择进DC,这样对DC操作,就相当直接对位图进行操作
pDC->SelectObject(&bmp):
// use pDC to draw orthers in the bmp
构造内存DC
一般我们为了避免闪烁等现象,需要构造内存DC ,然后再DC上进行绘制,绘制完毕后,通过DC之间的传递,将图像再绘制到屏幕中去。
CDC memDC; 只是创建了一个CDC对象,还没有创建DC资源
memDC.CreateCompatibleDC(pDC); 才是真正创建DC资源。
创建兼容DC是关键,其关键之处在于要创建的DC与哪个现有的DC兼容。
因为内存DC只是个中介,它必须要将其DC中的图像传递到其它DC中(目的DC),才会体现其价值。
而DC 与 DC之间可以传递信息的前提是:两DC是兼容的。
据此可知: 内存DC要兼容目的DC
如下例:
- CBitmap bmp;
- bmp.LoadBitmap(IDI_BITMAP);
- CDC memDC;
- memDC.CreateCompatibleDC(pDC);
- memDC.SelectObject(&bmp);
- pDC->BitBlt(0,0,nWidth,nHeight,&memDC,0,0,SRCCOPY);
DC--->DC的传递
下面针对各种情况一一给出示例:
1 位图--->屏幕
- // 位图到屏幕
- CBitmap bmp;
- BITMAP bm;
- CDC memDC;
- CDC *pDC=GetDC();
- //加载图片 获得图片信息
- bmp.LoadBitmap(IDB_BITMAP);
- bmp.GetBitmap(&bm);
- // 创建与屏幕兼容的DC,并选入位图
- memDC.CreateCompatibleDC(pDC);
- CBitmap* pOldBmp=(CBitmap *)memDC.SelectObject(&bmp);
- // 将位图绘制在屏幕中 位图--->屏幕
- pDC->SetStretchBltMode(COLORONCOLOR);
- pDC->StretchBlt(0,0,100,100,&memDC,bm.bmWidth,bm.bmHeight,SRCCOPY);
- memDC.SelectObject(pOldBmp);
- //释放资源
- ReleaseDC(pDC);
2
位图到位图1-----二者都是CBitmap类对象
- // 位图到位图
- // 因为目的地是位图,所以先创建一个空白位图
- // 因为是位图与位图之间的传递,所以可以使用两个内存DC来完成
- // 两个DC如何兼容? 只要每一个DC都与屏幕DC兼容,则这两个DC也就互相兼容了
- CBitmap destBmp;
- CBitmap sourceBmp;
- BITMAP bm;
- // 定义源DC 与目的DC对象
- CDC sourceDC;
- CDC destDC;
- // 获得兼容的屏幕DC
- CDC *pDC=GetDC();
- //加载源图片
- sourceBmp.LoadBitmap(IDB_BITMAP);
- sourceBmp.GetBitmap(&bm);
- // 创建源DC资源
- sourceDC.CreateCompatibleDC(pDC);
- sourceDC.SelectObject(&sourceBmp);
- // 创建Dest位图资源
- destBmp.CreateCompatibleBitmap(pDC,bm.bmWidth,bm.bmHeight);
- // 创建DestDC资源
- destDC.CreateCompatibleDC(pDC);
- destDC.SelectObject(&destBmp);
- //位图到位图传递
- destDC.SetStretchBltMode(HALFTONE);
- destDC.StretchBlt(0,0,bm.bmWidth,bm.bmHeight,&sourceDC,0,0,100,100,SRCCOPY);
- ReleaseDC(pDC);
位图到位图2---源位图为CImage类
- // 位图到位图 2
- // 源位图为CImage对象,直接使用CImage对象的成员函数进行传递
- CImage sourceImage;
- CBitmap destBmp;
- CDC destDC;
- sourceImage.Load(imageFile);
- // 获得CImage对象的DC
- CDC *pDC=CDC::FromHandle(sourceImage.GetDC());
- // 创建Dest位图资源 DestDC
- destDC.CreateCompatibleDC(pDC);
- destDC.SelectObject(&destBmp);
- ::SetStretchBltMode(destDC.m_hDC,HALFTONE);
- ::SetBrushOrgEx(destDC.m_hDC,0,0,NULL);
- // 直接使用CImage成员函数进行传递 其实是:CImage封装了DC之间的传递工作
- sourceImage.StretchBlt(&destDC,CRect(0,0,100,100),CRect(0,0,100,100),SRCCOPY);
- // 释放DC资源
- sourceImage.ReleaseDC();
3 屏幕到位图
- //屏幕到位图
- CBitmap destBmp;
- CDC destDC;
- // 获得兼容的屏幕DC
- CDC *pDC=GetDC();
- // 创建Dest位图资源
- destBmp.CreateCompatibleBitmap(pDC,100,100);
- // 创建DestDC资源
- destDC.CreateCompatibleDC(pDC);
- destDC.SelectObject(&destBmp);
- //屏幕到位图传递
- destDC.SetStretchBltMode(HALFTONE);
- destDC.StretchBlt(0,0,100,100,pDC,0,0,100,100,SRCCOPY);
- ReleaseDC(pDC);