画线示例:
1、创建基于单文档工程:Draw
2、在CDrawView类中添加成员变量:private CPoint m_ptOrigin;
3、在CDrawView构造函数中初始化:m_ptOrigin = 0;
4、添加WM_LBUTTONDOWM消息响应函数:OnLButtonDown
添加代码:
m_ptOrigin = point;
5、添加WM_LBUTTONUP消息响应函数:OnLButtonUp
使用SDK全局函数实现划线功能:
HDC hdc;
hdc = ::GetDC(m_hWnd);
MoveToEx(hdc,m_ptOrigin.x,m_ptOrign.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc);
注:
m_hWnd是窗口句柄,每个继承自CWnd的子类都有该成员变量。
CWnd类也提供了GetDC和ReleaseDC成员函数,::表明是全局SDK函数,而不是CWnd类得成员函数。
接下来使用MFC的CDC类实现画线功能
CDC* pDC = GetDC();
PDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);
注:
MFC提供设备描述符的封装类CDC,封装了所有与绘图有关的操作。
该类提供一数据成员m_hDC,用来保存与CDC类相关的DC句柄,道理与CWnd类提供m_hWnd成员变量保存与窗口相关的句柄是一样。
利用MFC的CClientDC类实现画线功能
CClientDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
注:
CClientDC继承自CDC,自动调用GetDC和ReleaseDC,不需显式调用。
构造CClientDC对象时,需要一CWnd类型的指针作为参数。该例中传递CDrawView对象的指针this。
若想在CMainFrame类窗口中绘图,代码改为:CClientDC dc(GetParent());
这时可以画的工具栏上。
视图类只有客户区(即视图窗口本身),框架窗口既有客户区(即菜单栏以下部分)又有非客户区(程序运行界面的标题栏和菜单栏)。
利用MFC的CWindowDC类画线
CWindowDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
注:
CWindowDC派生于CDC类,构造时自动调用GetWindowDC,析构时自动调用ReleaseDC。
使用它可访问整个窗口区域。
视图窗口的整个窗口区也就视图窗口本身,而框架窗口的整个窗口区域就不同了:
代码改为GetWindowDC(GetParent());可以画的标题栏、菜单栏、工具栏上。
在桌面窗口画线
CWindowDC dc(GetDesktopWindow());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
注:
CWnd类得GetDesktopWindow成员函数可以获得Windows桌面窗口的句柄。这样就可在整个屏幕窗口画线。
绘制彩色线条
1、设备描述表中有一默认的黑色画笔,所以默认画出都是黑的。
2、可用MFC的类CPen创建画笔对象:(有三个构造函数,其一如下:)
CPen(int nPenStyle, int nWidth, COLORREF crColor);
nPenStyle:笔的线形(实线PS_SOLID、点线PS_DOT、虚线PS_DASH等)
nWindth:线宽
crColor:颜色,COLORREF类型。
利用RGB宏可以构建这种类型的值:
COLORREF RGB(BYTE bRed, BYTE bGreen, BYTE bBlue);
3、程序中构造一GDI对象后不会立即生效,必须选入设备描述表,才会在以后的绘制中生效。利用SelectObject把GDI对象选入设备描述表,并且返回先前被选对象的指针。是为还原设备描述表用的。一般都有将其恢复到先前状态。
4、绘制彩色线条:
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);
注:
CPen pen(PS_DASH, 10, RGB(255,0,0));
PS_DASH指明画的是虚线,但绘图中不起作用,因为画笔宽度小于等于1时,虚线线形才有效。
使用画刷
画刷常用来填充一块区域
CBrush brush(RGB(255,0,0));
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
注:
1、CRect提供多个构造函数,该例使用:
CRect(POINT topLeft,POINT bottonRight);
2、FillRect函数
void FillRect(LPCRECT lpRect, CBrush* pBrush);
lpRect:指向一RECT结构体或CRect对象的指针,该结构体或对象包含要填充的矩形逻辑坐标。
pBrush:指向用于填充的画刷对象的指针
3、这里只是用指定画刷填充一块区域,不需要把画刷选入设备描述表。设备描述表中存在一默认白色画刷。
位图画刷
CBitmap bitmap;//创建位图对象
bitmap.LoadBitmap(IDB_BITMAP1);//加载位图资源
CBrush brush(&bitmap);//创建位图画刷
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
注:
1、CBrush有一构造函数:CBrush(CBitmap* pBitmap);
该构造函数要求一CBitmap类型指针,通过CBitmap类的构造函数就能获得,但创建CBitmap对象时,其构造函数并不能得到一个有用的位图对象,还需调用初始化函数初始化该位图对象。
2、初始化函数有多个:LoadBitmap、CreateBitmap、CreateBitmapInderect等。
BOOL LoadBitmap(LPCTSTR lpszResourceName);
BOOL LoadBitmap(UINT nIDResource);
第二种需要一资源ID做参数,需要先导入一位图资源,位图ID为IDC_BITMAP1
透明画刷
1、关于白色画刷
调用Rectangle函数绘制矩形时,矩形重叠时会相互覆盖,这是因为设备描述表中有一默认的白色画刷,绘图时会利用白色画刷填充矩形内部。
2、CBrush类没有创建透明画刷的方法,只能通过其他方法:
GetStockObject(NULL_BRUSH);获得一空画刷的画刷句柄(绘图时使用的是画刷对象)
FromHandle将画刷句柄转化为画刷对象。
static CDC* PASCAL FromHandle(HDC hDC);
代码:
CClientDC dc(this);
CBrush* pBrush =
CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush* pOldBrush = dc.SelectObject(pBrush);
dc.Rectangle(CRect(m_ptOrigin,point));
dc.SelectObject(pOldBrush);
注:
1、FromHandle直接使用类名调用,是调用静态成员函数的方法。
2、GetStockObject函数返回的是HGDIOBJECT,需要强制类型转化:(HBRUSH)
3、pBrush是指针类型,选入设备描述表时不用加&符
4、Rectangle和FillRect区别:
FillRect参数中提供了绘制使用的画刷,所以不需要把画刷选入设备描述表,Rectangle没有画刷参数,需要选入设备描述表。
5、关于静态成员函数:
静态成员函数中不能调用非静态的成员函数和变量。静态成员函数只能访问静态变量。
非静态成员函数可以调用静态的成员函数和变量。
析:静态变量在对象生成之前产生,此时非静态变量还未产生,自然不能调用。非静态的变量产生时,静态的变量已生成,自然可以调用。
绘制连续线条
定义一成员变量:private BOOL m_bDraw;
构造函数中初始化为FALSE:m_bDraw = FALSE;
左键按下时:m_bDraw = TRUE;
左键弹起:m_bDraw = FALSE;
添加WM_MOUSEMOVE消息响应函数:OnMouseMove
CClientDC dc(this);
CPen pen(PS_SOLID,1,RGB(255,0,0));
CPen* pOldPen = dc.SelectObject(&pen);
if(m_bDraw == TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
m_ptOrigin = point;
}
dc.SelectObject(pOldPen);
绘制扇形效果的线条(带边线)
添加成员变量:private CPoint m_ptPre;
构造函数中初始化:m_ptpre = 0;
OnLButtonDown 中:m_ptPre = point;
OnMouseMove中:
CClientDC dc(this);
if(m_bDraw == TRUE)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.LineTo(m_ptPre);
m_ptPre = point;
}