第一个C是Class,D是Device,第二个C是Context,即“设备上下文”,是MFC中应用程序的图形设备接口,封装了绘图所需的成员函数。
任何时候,最多只能获得5个CDC同时使用。
函数原型:
CDC* CWnd::GetDC();
调用成功则返回当前窗口客户区设备上下文标识符,否则返回NULL。
函数原型:
int CWnd::ReleaseDC(CDC* pDC);
pDC是要释放设备上下文的标识符,调用成功则返回非0,否则返回0。
CGdiObject | 提供各种Windows GDI绘图工具的基类 |
CBitmap | 封装GDI位图,提供位图操作的接口 |
CBrush | 封装GDI画刷,可以选作设备上下文的当前画刷 |
CFont | 封装GDI字体,可以选作设备上下文的当前字体 |
CPalette | 封装GDI调色板,提供应用程序和显示器之间的颜色接口 |
CPen | 封装GDI画笔,可以选作设备上下文的当前画笔 |
(1)绘图开始前,创建一个新的GDI对象,并选入当前设备上下文中,同时保存指向原GDI对象的指针。
(2)使用新的GDI对象画图。
(3)绘图结束后,使用保存的原GDI对象的指针将设备上下文恢复原状。
函数原型:
COLORREF CDC::SetPixel(POINT point,COLORREF crColor);
COLORREF CDC::SetPixel(int x,int y,COLORREF crColor);
参数顺序为像素点位置,像素点颜色。调用成功则返回像素点的RGB值,否则返回-1。
函数原型:
BOOL CDC::SetPixelV(POINT point,COLORREF crColor);
BOOL CDC::SetPixelV(int x,int y,COLORREF crColor);
参数含义同上,调用成功则返回非0,否则返回0。
因为SetPixel要返回RGB值,而SetPixelV不需要,故SetPixelV执行速度稍快。
原型:
COLORREF RGB(BYTE byRed,BYTE byGreen,BYTE byBlue);
三个参数都是字节型变量,返回值COLORREF类型,是用DWORD表示的整型数。
#define RGB(r,g,b) ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|
(((DWORD)(BYTE)(b)<<16)))
内存原理图:
以红色为例:
(1)RGB(255,0,0):顺序为red,green,blue
(2)0x0000FF:顺序为blue,green,red,与内存原理图对应
函数原型:
COLORREF CDC::GetPixel(int x,int y)const;
COLORREF CDC::GetPixel(POINT point)const;
调用成功返回指定位置的RGB值,否则返回-1。
void CExample1View::OnDraw(CDC* pDC)
{
CExample1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
CPoint p0(100, 100);//声明点
CPoint p1(p0.x + 100, p0.y);
pDC->SetPixelV(p0, RGB(255, 0, 0));//绘制像素点
COLORREF crColor = pDC->GetPixel(p0);//获取像素点颜色
pDC->SetPixelV(p1,crColor);
}
因为绘图范围不止第一象限,所以需要在客户区自建坐标系,采用之前的代码在客户区中心建立x正向右、y正向上的坐标系。因为x坐标和y坐标是相互独立的,所以嵌套循环中x和y的顺序可以交换,结合循环变量的设置,可以实现不同的动画效果。
void CExample1View::OnDraw(CDC* pDC)
{
CExample1Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
CRect rect;
GetClientRect(rect);
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(rect.Width(), rect.Height());
pDC->SetViewportExt(rect.Width(), -rect.Height());
pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);
rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);
srand((unsigned)time(NULL));//防止获得的随机数重复,time返回系统时间的秒数
COLORREF crColor;
for (int x = 50; x < 150; ++x)//从左往右
for (int y = -50; y < 50; ++y)//一列一列画,从下往上
pDC->SetPixelV(x, y, RGB(rand() % 256,
rand() % 256, rand() % 256));
for(int x = 50; x < 150; ++x)//对应x'从-50到-150,从右往左
for (int y = -50; y < 50; ++y) {
crColor = pDC->GetPixel(x, y);
pDC->SetPixelV(-x, y, crColor);
}
}