目录
利用MFC的CWindowDC类实现画线功能
在桌面窗口中画线
绘制彩色线条
CPen
nPenStyle
nWidth
crColor
接上:VC++ 绘制线条 OnLButtonDown函数(DrawView.cpp) 利用SDK全局函数实现画线功能 利用MFC的CDC类实现画线功能 利用MFC的CClientDC类实现画线功能
接下:VC++使用画刷绘图 简单画刷 FillRect函数 位图画刷 透明画刷
先介绍一个MFC类:CWindowDC,这个类也派生于CDC类,并且在构造时调用GetWindowDC函数获得相应的设备描述表对象,在析构时调用ReleaseDC函数释放该设备描述对象所占用的资源。也就是说,当我们利用CWindowDC对象绘图时,也不需要显式地调用GetDC和ReleaseDC函数,该对象会自动获取和释放设备描述表资源。使用CWindowDC对象有哪些好处呢?该对象可以访问整个窗口区域,包括框架窗口的非客户区和客户区。该对象的构造与CClientDC对象相同,如果要构造一个与视类窗口相关的设备描述表,则可以利用视类对象的指针来构造这个CWindowDC对象。如下所示是利用CWindowDC对象实现画线功能的代码。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
CWindowDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
编译并运行Draw程序,将会发现这段代码实现的功能与利用CClientDC类画线时没什么区别,也只能在视类窗口中画线,因为这时创建的设备描述表与视类窗口相关。
接着,把上面代码中构造设备描述表对象时使用的参数this指针换为指向视类父窗口的指针。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
CWindowDC dc(GetParent());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
编译并运行Draw程序,将会发现此时线条可以画到工具栏和菜单栏上,程序运行结果下如图所示。
知识点:通常都是在客户区中绘图。但是如果利用 CWindowDC 类,就可以实现在工具栏和菜单上绘图。
如果获得了一个与桌面窗口相关的设备描述表,就可以在桌面窗口中绘图。CWnd类的 GetDesktopWindow 成员函数可以获得 Windows 桌面窗口的句柄。修改构造设备描述表的代码,结果如下所示。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
CWindowDC dc(GetDesktopWindow());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
CView::OnLButtonUp(nFlags, point);
}
再次 Build 并运行 Draw 程序,并拖动鼠标画线,发现这时可以在整个屏幕窗口上画线。(但是截图后不显示)
上述各种方法实现的画线功能所绘制的都是黑色线条。这是因为在设备描述表中有一个默认的黑色画笔,因此绘制的线条都是黑色的。如果想要绘制其他颜色的线条,首先需要创建一个特定颜色的画笔,然后将此画笔选入设备描述表中,接下来绘制的线条的颜色就由这个新画笔的颜色决定了。可以利用MFC提供的类CPen来创建画笔对象。该类封装了与画笔相关的操作,它有三个构造函数。
CPen( );
CPen(
int nPenStyle,
int nWidth,
COLORREF crColor
);
CPen(
int nPenStyle,
int nWidth,
const LOGBRUSH* pLogBrush,
int nStyleCount = 0,
const DWORD* lpStyle = NULL
);
其中一个构造函数的原型声明如下所示:
CPen(
int nPenStyle,
int nWidth,
COLORREF crColor
);
指定钢笔的样式。 在构造函数的第一个版本的此参数可以是下列值之一:
PS_SOLID 创建实心钢笔。
PS_DASH 创建一个虚线钢笔。 有效,仅当钢笔的宽度为1或更小,在组件度量单位。
PS_DOT 创建一个虚线钢笔的。 有效,仅当钢笔的宽度为1或更小,在组件度量单位。
PS_DASHDOT 使用交替短划线和点创建一个钢笔。 有效,仅当钢笔的宽度为1或更小,在组件度量单位。
PS_DASHDOTDOT 使用交替短划线和double点创建一个钢笔。 有效,仅当钢笔的宽度为1或更小,在组件度量单位。
PS_NULL 创建一个空钢笔。
PS_INSIDEFRAME 创建例如绘制在Windows GDI输出功能生成的闭合的形状内部帧的一行指定一个边框的一个笔(, Ellipse、 Rectangle、 RoundRect、 Pie和 Chord 成员函数)。 在此样式使用Windows GDI未指定一个边框的输出功能(例如, LineTo 成员函数),钢笔的绘图区未由帧限制。
CPen 构造函数的第二个版本指定类型,样式,终止线帽的组合,并连接属性。 应按位组合可以使用或运算符,从每个类别的值(|)。 钢笔类型可为下列值之一:
PS_GEOMETRIC 创建一个几何图形钢笔。
PS_COSMETIC 创建一个装饰性的钢笔。
CPen 构造函数的第二个版本添加 nPenStyle的以下钢笔样式:
PS_ALTERNATE 创建设置其他像素的一个钢笔。 (此样式为装饰性的笔只适用)。
PS_USERSTYLE 创建使用用户提供的一个样式数组的一个钢笔。
终止线帽可为下列值之一:
PS_ENDCAP_ROUND 终止线是圆形的。
PS_ENDCAP_SQUARE 终止线是正方形。
PS_ENDCAP_FLAT 终止线保持不变。
连接可为下列值之一:
PS_JOIN_BEVEL Joins为、。
并在 SetMiterLimit 函数时,设置的当前限制内 PS_JOIN_MITER Joins是斜接。 如果连接超出此限制,其转换为、。
PS_JOIN_ROUND Joins是圆形的。
指定钢笔的宽度。
对于构造函数的第一个版本,因此,如果该值为0,无论该映射模式,如组件单位的宽度始终为1像素。
对于构造函数的第二个版本,因此,如果 nPenStyle 是 PS_GEOMETRIC,该宽度(以逻辑单位给定。 如果 nPenStyle 是 PS_COSMETIC,必须将宽度为1。
包含钢笔的一个RGB颜色。
其中,第一个参数(nPenStyle)指定笔的线型(实线、点线、虚线等);第二个参数(nWidth)指定笔的线宽;第三个参数(crColor)指定笔的颜色,这个参数是COLORREF类型,利用RGB宏可以构建这种类型的值。RGB宏的声明如下所示。
public:
static int RGB(
int Red,
int Green,
int Blue
)
COLORREF RGB(BYTE bRed, BYTE bGreen, BYTE bBlue color);
可以看到,RGB宏有三个参数,分别代表红、绿、蓝三种颜色的值。这三个参数都是BYTE类型,取值范围为0~255。如果将RGB宏的三个分量全部设置为0,则得到黑色;如果全部设置为255,则得到白色;……可以将这三个分量设置成0~255之间的任意值,从而得到各种不同的颜色。
另外,在程序中,当构造一个 GDI 对象后,该对象并不会立即生效,必须选入设备描述表,它才会在以后的绘制操作中生效。利用SelectObject函数可以实现把GDI对象选入设备描述表中,并且该函数会返回指向先前被选对象的指针。这主要是为了在完成当前绘制操作后,还原设备描述表。例如,当我们在某个局部范围内绘图时,可能需要改变画笔的颜色,并把新画笔选入设备描述表。当这部分绘图操作完成之后,需要恢复到原来的画笔颜色,然后完成其他部分的绘图操作。在一般情况下,在完成绘图操作之后,都要利用SelectObject函数把先前的GDI对象选入设备描述表,以便使其恢复到先前的状态。
如下代码所示是在Draw程序中绘制彩色线条的程序代码。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
CPen pen(PS_SOLID,1, RGB(255, 0, 0));
CClientDC dc(this);
CPen* pOldPen = dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen);
CView::OnLButtonUp(nFlags, point);
}
在面所示代码中,首先创建一个实线画笔,其宽度为1,颜色为红色。接着利用SelectObject函数将新画笔对象选入设备描述表。然后利用画线函数绘制线条。最后,再次调用SelectObject函数恢复设备描述表中的画笔对象。编译并运行Draw程序,并拖动鼠标画线,这时可以看到这次绘制的是红色的线条。可以试着修改画笔的颜色,将会绘制出其他各种颜色的线条。也可以改变画笔的宽度,例如改为10,此时程序运行结果如下图所示。也可以改变画笔的线型,例如选择虚线线型,即用下面这行代码替上面构造画笔对象的那行代码。
CPen pen(PS_DASH,10, RGB(255, 0, 0));
编译并运行Draw程序,并拖动鼠标左键进行画线操作,将会发现绘制的还是一条实线,并不是想像中的虚线。这是因为当画笔的宽度小于等于1时,虚线线型才有效。因此,可以修改构造画笔对象的代码,将其宽度设置为1,再次编译并运行 Draw 程序,并拖动鼠标左键绘制线条,这时可以看到绘制的是虚线,如下图所示。
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
CPen pen(PS_DASH,1, RGB(255, 0, 0));
CClientDC dc(this);
CPen* pOldPen = dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen);
CView::OnLButtonUp(nFlags, point);
}
另外,还可以绘制点线(将画笔的线型改为 PS_DOT),程序运行结果如下图所示。