1. 画线
方法I:使用HDC (SDK模式)
HDC hDC;
hDC = ::GetDC(m_hWnd); //此处要用全局的::GetDC,否则默认用CDC的。
MoveToEx(hDC, point1.x, point1.y, NULL); //MoveToEx,先移到初始点,然后再画线
LineTo(hDC, point2.x, point2.y);
::ReleaseDC(m_hWnd, hDC); //释放也要用全局::ReleaseDC
方法II:使用CDC(MFC模式)
CDC *pdc=GetDC();
pdc->MoveTo(point1);
pdc->LineTo(point2);
ReleaseDC(pdc);
方法III:使用CClientDC(CClientDC继承自CDC,不需要手动GetDC和ReleaseDC,传递this或GetParent())
CClientDC dc(GetParent()); //可以在Frame下画线
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
方法IV:使用CWindowDC(CWindowDC继承自CDC,包含客户区和非客户区,可以在整个屏幕下画线 ,不需要手动GetDC和ReleaseDC)
CWindowDC dc(GetDesktopWindow());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
2. 包含画笔(颜色,样式,宽度)
方法1:
CDC *pDC = GetDC();
CPen pen(PS_SOLID, 2, RGB(200,200,200)); //定义一个画笔,样式为实线,颜色为灰色,宽度为2像素
CPen *pOldPen = pDC->SelectObject(&pen); //将新画笔选入设备描述表,并返回之前的画笔
pDC->MoveTo(m_ptOrign);
pDC->LineTo(point);
pDC->SelectObject(pOldPen); //还原旧画笔
ReleaseDC(pDC);
方法2:
CClientDC dc(this); //不需要ReleaseDC
CPen pen(PS_DASH,1,RGB(255,0,0)); //定义一个画笔,样式为破折号,颜色为红色,宽度为1像素
CPen *cOldPen=dc.SelectObject(&pen); //将新画笔选到dc中,并保存之前的画笔
dc.MoveTo(point1);
dc.LineTo(point2);
dc.SelectObject(cOldPen); //还原旧画笔
方法3:
CWindowDC dc(GetDesktopWindow()); //CWindowDC继承自CDC,包含客户区和非客户区,GetDesktopWindow()获取桌面
CPen pen(PS_SOLID, 5, RGB(255,0,0));
CPen *pOldPen = dc.SelectObject(&pen);
dc.MoveTo(point1);
dc.LineTo(point2);
dc.SelectObject(pOldPen);
3. 画刷
CBrush brush(RGB(255,0,0));
CClientDC dc(this); //CClientDC传递this
dc.FillRect(CRect(point1, point2), &brush); //FillRect填充
透明画刷:
CClientDC dc(this);
CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)); //创建透明画刷
CBrush *pOld = dc.SelectObject(pBrush);
dc.Rectangle(CRect(point1, point2)); //画矩形
dc.SelectObject(pOld); //最后返还画刷
4. 画圆角矩形
//圆角大小
POINT pt;
pt.x = 5;
pt.y = 5;
//窗口尺寸
CRect rc;
GetClientRect(&rc);
//画圆角矩形,然后还原旧画笔
CDC *pDC = GetDC();
pDC->RoundRect(&rect, pt);
pDC->SelectObject(hOldPen);
//新画笔:实线,线宽5,红色
CPen pen(PS_SOLID, 5, RGB(255, 0, 0));
CPen* hOldPen = pDC->SelectObject(&pen);
//通过朝CRect的中心移动边以缩小CRect,SM_CXEDGE表示缩小一个边框大小,相反函数nflateRect
rect.DeflateRect(CSize(GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE)));
//填充颜色
CBrush brush(RGB(200,200,200));
pDC->FillRect(rect, &brush);
brush.DeleteObject();
例如:给窗体加上圆角矩形的窗体
需要重载消息 WM_ERASEBKGND,在函数OnEraseBkgnd(CDC* pDC)中实现,才能保证在窗体被遮盖重现后,窗体上画的线条及加载的图片被正常显示
//绘图
BOOL CDelTaskDlg::OnEraseBkgnd(CDC* pDC)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
CDialogEx::OnEraseBkgnd(pDC);
CRect rc;
GetClientRect(&rc);
rc.right -= 1;
rc.bottom -= 1;
//画圆角矩形
POINT pt;
pt.x = 5;
pt.y = 5;
CPen hNewPen(PS_SOLID, 1, RGB(170, 170, 170));
CPen* hOldPen = pDC->SelectObject(&hNewPen);
pDC->RoundRect(&rc, pt);
pDC->SelectObject(hOldPen);
return TRUE;
}
5. 创建任意线条
(1)创建基于单文档工程:Draw
CDrawView类中添加成员变量:
CPoint m_ptOrigin;
BOOL m_bDraw;
(2)CDrawView()中初始化:
m_ptOrigin = point;
m_bDraw = false;
(3)添加消息响应函数:
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_MOUSEMOVE
(4)左键按下时:
m_ptOrigin = point;
m_bDraw = true;
(5)左键抬起:
m_bDraw = false;
(6)鼠标移动时:
//画连续线条
CClientDC dc(this);
if(m_bDraw)
{
dc.MoveTo(point1);
dc.LineTo(point2);
m_ptOrigin = point2; //必须的
}
//画扇形线条
CClientDC dc(this);
if(m_bDraw)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
}
//画带外包线的扇形线条
析:画带外包线的扇形线条,不光记录初始位置,还要记录鼠标移动上一位置。
添加成员变量:
CPoint m_ptOld;
在鼠标左键按下时初始化:
m_ptOld = point;
在鼠标移动时进行改变:
CClientDC dc(this);
if(m_bDraw)
{
dc.MoveTo(m_ptOrigin);
dc.LineTo(m_ptOld);
dc.MoveTo(m_ptOld);
dc.LineTo(point);
m_ptOld = point;
}
6. 画矩形
画无边框的矩形:
方法说明:利用FillRect函数填充矩形。填充内容为画刷的内容,即画刷对象的指针
CBrush brush(RGB(5,255,255));
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
以位图作为画刷的资源:
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bitmap); //定义画刷的同时初始化
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
bitmap.DeleteObject(); //可以调用DeleteObject删除由LoadBitmap加载的位图,否则CBitmap的析构函数将删除该位图对象
或者:
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush; //先声明
brush.CreatePatternBrush(&bitmap); //再初始化
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
bitmap.DeleteObject(); //可以调用DeleteObject删除由LoadBitmap加载的位图,否则CBitmap的析构函数将删除该位图对象
画有边框的矩形:
方法说明:利用Rectangle方法来画矩形。其中CBrush与CPen类分别负责矩形内部和矩形边框的属性
(1) 画中心为白色的矩形
CClientDC dc(this);
dc.Rectangle(CRect(point1,point2));
(2)画中心为透明的矩形(空笔刷)
CClientDC dc(this);
CBrush *pBrush=CBrush::FromHandle((HBRUSH)
GetStockObject(NULL_BRUSH));
CBrush *pOldBrush=dc.SelectObject(pBrush);
dc.Rectangle(CRect(m_ptOrigin,point));
pOldBrush=pBrush;
(3)画中心为透明边为任意颜色的矩形
CClientDC dc(this);
CPen pen(PS_SOLID,1,RGB(234,23,53));
CPen *pOldPen=dc.SelectObject(&pen);
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH))
CBrush *pOldBrush=dc.SelectObject(pBrush);
dc.Rectangle(CRect(m_ptOrigin,point));
dc.SelectObject(pOldPen);
dc.SelectObject(pOldBrush);
总结:
使用画笔:
CClientDC dc(this);
CPen pen(PS_SOLID,1,RGB(234,23,53));
CPen *pOldPen=dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen);
使用画刷填充:
CBrush brush(RGB(0,255,0));
CClientDC dc(this);
CRect rect(point1,point2);
dc.FillRect(&rect,&brush);
使用位图创建画刷进行填充:
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bitmap);
CClientDC dc(this);
CRect rect(point1,point2);
dc.FillRect(&rect,&brush);
使用空笔刷画透明矩形:
CBrush *brush;
brush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CClientDC dc(this);
CBrush *pOldBrush =dc.SelectObject(brush) ;
dc.Rectangle(CRect(point1,point2));
dc.SelectObject(pOldBrush) ;