CDC类定义的是设备上下文对象的类。
CDC对象提供处理显示器或打印机等设备上下文的成员函数,以及处理与窗口客户区对应的显示上下文的成员。
通过CDC对象的成员函数进行所有的绘图。
类对设备上下文操作提供了成员函数,处理绘图工具。安全型图形设备接口(GDI)对象收集,以及处理颜色和调色板。
它还为获取和设置绘图属性、映射,处理视点、窗口扩展、转换坐标,处理区域、剪贴、绘制直线及绘制简单椭圆和多边形等形状提供了成员函数。
另外还为绘制文本、处理字体,使用打印机跳转,滚动和播放元文件提供成员函数。
使用CDC对象时要构造它,然后调用与它平等的、使用设备上下文的Windows函数的成员函数。
MFC中绘图分为三个区域:标准客户区、临时客户区、非客户窗口区。
在Window中,HDC是用于绘图的句柄,它和HWND一样。HDC是设备环境专用的绘图句柄。在MFC中封装于CDC类中。
HDC句柄绘图有三种方式,分别为标准客户区绘图、临时客户区绘图和非客户区绘图。因此CDC类绘图也分为三种。
标准客户区绘图是在WM_PAINT消息回调时执行,通过调用BeginPain函数获取标准的客户区绘图句柄进行绘图,最后调用EndPaint函数释放绘图句柄。在CDC类这两个函数封装于CPointDC 类中,这个类是派生于CDC类。在MFC中要是在标准客户区绘图的话在WM_PAINT消息映射函数中创建CPointDC对象进行绘图。
在任何消息回调函数中都可以执行,调用GetDC获取临时客户区绘图句柄进行绘图,最后调用ReleaseDC函数释放。在MFC中封装于CClientDC类中,此类继承于CDC类。
CClientDC中封装了GetDC和ReleaseDC中。因此MFC中需要进行临时绘图的话需要使用CClientDC类对象。
非客户区绘图(包括标题栏)必须是在WM_NCPAINT消息回调的时候执行,调用GetWindowDC函数获取非客户区的绘图句柄,最后通过ReleaseDC释放。在MFC中封装于CWindowDC中,此类也是继承于CDC类。要是想在整个屏幕区进行绘图据需要使用此类创建的对象。
绘图的三大坐标,根据不同的绘图区域有着不同的坐标系系统。在Windows程序开发中常用的三种坐标系是:屏幕坐标系、客户区坐标系、非可会窗口坐标系
1)屏幕坐标系:
坐标原点在屏幕法人左上角,自左向右x的坐标增大,自上而下y的坐标哦、 正大如果屏幕的分辨率设置为1024x1768,屏幕的左上角坐标是(0,0),屏幕左下角是1024x1768使用GetWindonRect获取屏幕的坐标
2)非客户、窗口坐标系
坐标原点在窗口(包括标题栏)左上角,xy坐标轴方向同上使用GetClientRect获取窗口的矩形区域。
3)客户区坐标系
坐标原点在标题栏一下的客户区左上角,xy方向同上例如:BeginPaint函数返回的设备环境是基于客户区坐标系,该函数一般只在WM_NCPAIN消息中使用GetDC函数返回的设备环境是基于客户区的坐标系,该函数一般在任何消息中都可已使用GetClientRect函数获取的是客户区坐标系,是依据该坐标系计算的,左上角坐标一定是(0,0)
绘图过程中使用的其他类:
MFC中标准绘图:
void C绘图Dlg::OnPaint()
{
CPaintDC dc(this); // 用于绘制的设备上下文
RECT rect;
GetClientRect(&rect); //获取客户区的位置
rect.bottom = 30;
dc.SetTextColor(RGB(0, 255, 255)); //设置字体
dc.FillSolidRect(&rect, RGB(255, 0, 0)); //将rect所选区域填充成自己想要的颜色
CString str;
str = "hiajdskjdsfol";
dc.DrawText(str, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); //向指定的区域写入字体。
dc.MoveTo(40, 40); //画线开始端
dc.LineTo(140, 40);//画线结束端
//CPen p1(PS_SOLID,4,RGB(255,0,0));//画笔,可以是空参数,也可以带入参数,第一个参数是线的种类(实线、虚线),线的宽度,线的颜色
CPen p1;//定义一个画笔,设置画线的属性
LOGPEN lp = { PS_SOLID, 4 };//设置画笔属性
lp.lopnColor = RGB(255, 0, 0);//设置画笔颜色
p1.CreatePenIndirect(&lp);//创建画笔
dc.SelectObject(&p1);//绘图设备选择画笔。
dc.MoveTo(40, 60); //画线开始端
dc.LineTo(140, 60);//画线结束端
CPen p2(PS_DASHDOT, 1, RGB(0, 255, 0));//注意使用PS_DASHDOT时,线的宽度只能选择为1
dc.SelectObject(&p2);
dc.Rectangle(10, 80, 50, 120);//注意,如果不结束画笔的选择,那么此画笔将一直沿用。
CPen p3;//定义一个空画笔
p3.CreatePen(PS_DASHDOTDOT, 1, RGB(0, 0, 255)); //空画笔需要使用。CreatePen创建画笔
dc.SelectObject(&p3);
CPoint ps[] = { CPoint(196, 92), CPoint(96, 92), CPoint(196, 192) };//使用Polygon时需要使用定
// 义一个指针数值,将多边形的定点包含在里面
dc.Polygon(ps, sizeof(ps) / sizeof(ps[0]));//Polygon是一个画多边形的函数,第一个参数是所画图形坐标指正,第二个是定点的个数、
CRect rect1(240, 50, 340, 160);//定义一个方形区域
dc.SelectObject(&p1);
CPoint point1(340, 50), point2(440, 160);
dc.MoveTo(point1);
dc.LineTo(rect1.CenterPoint());
dc.LineTo(point2);
dc.Chord(rect1, point1, point2);
CPen p4(PS_NULL, 54, RGB(202, 02, 51));
CBrush br(RGB(255, 0, 255));
dc.SelectObject(&br);
dc.SelectObject(&p4);
dc.Rectangle(140, 170, 240, 230);
}
运行结果:
MFC中客户区绘图:
客户区临时绘图,我们使用一个按钮触发绘图实现,当按下按钮之后,软件触发绘图事件。代码如下:
void C绘图Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
CClientDC dc(this);
RECT rect;
GetClientRect(&rect); //获取客户区的位置
rect.bottom = 30;
dc.SetTextColor(RGB(0, 255, 255)); //设置字体
dc.FillSolidRect(&rect, RGB(255, 0, 0)); //将rect所选区域填充成自己想要的颜色
CString str;
str = "hiajdskjdsfol";
dc.DrawText(str, &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); //向指定的区域写入字体。
dc.MoveTo(40, 40); //画线开始端
dc.LineTo(140, 40);//画线结束端
//CPen p1(PS_SOLID,4,RGB(255,0,0));//画笔,可以是空参数,也可以带入参数,第一个参数是线的种类(实线、虚线),线的宽度,线的颜色
CPen p1;//定义一个画笔,设置画线的属性
LOGPEN lp = { PS_SOLID, 4 };//设置画笔属性
lp.lopnColor = RGB(255, 0, 0);//设置画笔颜色
p1.CreatePenIndirect(&lp);//创建画笔
dc.SelectObject(&p1);//绘图设备选择画笔。
dc.MoveTo(40, 60); //画线开始端
dc.LineTo(140, 60);//画线结束端
CPen p4(PS_NULL, 54, RGB(202, 02, 51));
CBrush br(RGB(255, 0, 255));
dc.SelectObject(&br);
dc.SelectObject(&p4);
dc.Rectangle(140, 170, 240, 230);
}
运行结果:
MFC中非客户区绘图:
void C绘图Dlg::OnNcPaint()
{
// TODO: 在此处添加消息处理程序代码
// 不为绘图消息调用 CDialogEx::OnNcPaint()
CWindowDC dc(this);//定义一个非客户绘图设备
RECT rect;
GetClientRect(&rect);//获取非客户区大小
dc.FillSolidRect(&rect, RGB(255, 0, 0));//绘制一个背景区域,大小为客户区大小
dc.Ellipse(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);//绘制一个椭圆
}
运行结果:注意,标题栏被的左上角被当做初始原点进行绘图