基础语法篇_3——绘制线条 【SDK全局函数、CDC类、CClientDC类、CWindowDC类、在桌面窗口、绘制彩色线条】、画刷绘图【简单画刷、位图画刷、透明画刷】、绘制连续线条、绘制扇形效果线条

35 篇文章 40 订阅

🔳🔳 绘制线条 、画刷绘图、绘制连续线条、绘制扇形效果的线条


🔳🔳 插入符【文本插入符|图形插入符】、窗口重绘、路径、字符输入【设置字体|字幕变色】


🔳🔳 菜单命令响应函数、菜单命令的路由、基本菜单操作、动态菜单操作、电话本实例


🔳🔳 对话框的创建与显示、动态创建按钮、控件的访问【控件调整|静态文本控件|编辑框控件】、对话框伸缩功能、输入焦点的传递、默认按钮的说明


🔳🔳 MFC对话框:逃跑按钮、属性表单、向导创建


🔳🔳 在对话框程序中让对话框捕获WM_KEYDOWN消息


🔳🔳修改应用程序窗口的外观【窗口光标|图标|背景】、模拟动画图标、工具栏编程、状态栏编程、进度栏编程、在状态栏上显示鼠标当前位置、启动画面


🔳🔳设置对话框、颜色对话框、字体对话框、示例对话框、改变对话框和控件的背景及文本颜色、位图显示

一、绘制线条

在创建的单文档程序中实现绘画线条功能。

1)在view类中添加单击鼠标左键事件WM_LBUTTONDOWN
自动生成的类如下:

void CMFCTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CView::OnLButtonDown(nFlags, point);
}

生成的两个参数,其中第二个参数是CPoint类型,表示一个点。当鼠标按下后,鼠标单击处的坐标点由此参数传递给OnLButtonDown这个响应函数。

2)在消息响应函数中保存CPoint点的信息。
需要在类视图中添加一个成员变量:
①通过在类视图选项卡上用鼠标右键单击该类,并从弹出的快捷菜单中选择添加——>添加变量菜单命令。


②通过在类视图选项卡上用鼠标右键单击该类,并从弹出的快捷菜单中选择类向导——>成员变量——>添加自定义

在View的构造函数中初始化这个值。

CMFCTestView::CMFCTestView() noexcept
{
	// TODO: 在此处添加构造代码
	m_ptPoint.x = 0;
	m_ptPoint.y = 0;
}

在消息响应函数中保存鼠标按下点的信息。

void CMFCTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_ptPoint = point;
	CView::OnLButtonDown(nFlags, point);
}

3)绘制线段的终点。
终点是鼠标左键弹起来时获得。对WM_LBUTTONUP消息进行响应。

1.1 利用SDK全局函数实现画线功能

进行绘图操作,必须获得一个设备描述表(DC)。


1)通过GetDC()获得当前窗口的设备描述表。
CWnd类有一个成员变量(m_hWnd)用于保存窗口句柄。
2)调用MoveToEx()函数将当前位置移动到所需要绘制的线段起点处。

第一个参数:设备描述表的句柄;
第二个参数:新位置的X坐标;
第三个参数:新位置的Y坐标;
第四个参数:指向POINT结构体的指针,用于保存移动操作前鼠标的位置坐标。

3)调用LineTo()函数绘制一条到指定终点的线。

第一个参数:设备描述表的句柄;
第二个参数:终点X坐标;
第三个参数:终点Y坐标。

4)绘图结束后,释放设备描述表资源。调用ReleaseDC函数。


void CMFCTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//获得窗口设备描述表
	HDC hdc;
	//冒号说明是全局SDK函数
	hdc = ::GetDC(m_hWnd);
	//移动到线条的起点
	MoveToEx(hdc, m_ptPoint.x, m_ptPoint.y, NULL);
	//画线
	LineTo(hdc, point.x, point.y);
	//释放设备描述表
	//冒号说明是全局SDK函数
	::ReleaseDC(m_hWnd, hdc);

	CView::OnLButtonUp(nFlags, point);

}

1.2 利用MFC的CDC类实现画线功能

MFC为我们提供了一个设备描述表的封装类CDC,该类封装了所有与绘图相关的操作。该类提供了一个数据成员m_hDC,用于保存与CDC类相关的DC句柄。

void CMFCTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	//获取当前窗口的设备描述表对象的指针
	CDC* pDC= GetDC();
	//移动到线条的起点
	pDC->MoveTo(m_ptPoint);
	//画线
	pDC->LineTo(point);
	//释放设备描述表
	ReleaseDC(pDC);

	CView::OnLButtonUp(nFlags, point);
}
1.3 利用MFC的CClientDC类实现画线功能

利用MFC提供的CClientDC类实现画线功能。
CClientDC派生于CDC类,当CClientDC对象构造时,内部会调用GetDC函数,获得一个设备描述表对象;并且在析构时调用ReleaseDC函数。


void CMFCTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	//===============CClientDC===================
	CClientDC dc(this);
	dc.MoveTo(m_ptPoint);
	dc.LineTo(point);
	//===========================================
	
	CView::OnLButtonUp(nFlags, point);
}

1.4 利用MFC的CWindowDC类实现画线功能

CWindowDC派生于CDC类,并在构造时调用GetWindowDC函数获得相应的设备描述表对象,在析构时调用ReleaseDC函数释放资源。

CWindowDC对象可以访问整个窗口区域,包括框架窗口的客户区和非客户区。

void CMFCTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	 
    //===============CWindowDC===================
	CWindowDC dc(this);
	dc.MoveTo(m_ptPoint);
	dc.LineTo(point);
	//===========================================

	CView::OnLButtonUp(nFlags, point);
}

当把this指针换成指向视图类父窗口的指针:

CWindowDC  dc(GetParent());

发现此时线条可以画到工具栏和菜单栏上。

1.5 在桌面窗口中画线

若获得一个与桌面窗口相关的设备描述表,就可以在桌面窗口中绘图。CWnd类的GetDesktopWindow成员函数可以获得Windows桌面窗口的句柄。

void CMFCTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	 
   //===============窗口桌面画线===================
	CWindowDC dc(GetDesktopWindow());
	dc.MoveTo(m_ptPoint);
	dc.LineTo(point);
	//================================================
	
	CView::OnLButtonUp(nFlags, point);
}

1.6 绘制彩色线条

上面绘制的线条都是黑色,是因为设备描述表中有一个默认的黑色画笔。
若绘制其他颜色:需要创建一个特定颜色的画笔,然后将此画笔选入设备描述表中
1)MFC提供的类CPen创建画笔对象。
构造函数如下:

CPen(int nPenStyle,int nWidth,COLORREF crColor);

参数一:指定笔的线型(实线PS_SOLID,虚线PS_DASH,点线PS_DOT等),画笔宽度小于等于1时,虚线线型才有效
参数二:指定笔的线宽;
参数三:指定笔的颜色,这个参数是COLORREEF类型,利用RGB这个宏可以创建这种类型的值。

RGB声明如下:
COLORREF RGB(BYTE bRed, BYTE bGreen, BYTE bBlue);
RGB宏三个参数,分别代表红,绿,蓝三种颜色得值。取值范围0~255。其中(0,0,0)代表黑色;(255,255,255)代表白色。

2)构造一个GDI对象,该对象并不会立即生效,必须选入设备描述表。
通过SelectObject函数可以实现将GDI对象选入设备描述表,并返回指向先前被选对象的指针。目的:为了完成当前绘图操作后,还原设备描述表。当绘图结束后,恢复到原来的画笔颜色。
一般情况下,完成绘图操作之后,都要利用SelectObject函数将先前的GDI对象选入设备描述表,以便将其恢复到原先的状态。

void CMFCTestView::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//===============更改绘图的颜色===================
	//创建一个宽度为9的红色的实线型画笔
	CPen pen(PS_SOLID, 9, RGB(255, 0, 0));
	//获取当前窗口的设备描述表
	CClientDC dc(this);
	//将自己设置的画笔选入设备描述表
	CPen* pOldPen = dc.SelectObject(&pen);
	//画线
	dc.MoveTo(m_ptPoint);
	dc.LineTo(point);
	//设备表的原画笔恢复
	dc.SelectObject(pOldPen);
	//===========================================

	CView::OnLButtonUp(nFlags, point);

}

二、使用画刷绘图

MFC提供了一个CBrush类,可以用于创建画刷对象。画刷通常用于填充一块区域。

2.1 简单画刷

1)创建一个画刷。
2)创建设备描述表对象。
3)调用设备描述表的FillRect填充一块矩形区域,鼠标拖动的过程的起点和终点构造矩形。
CRect构造矩形区域。
CRect(POINT topLeft,POINT bottomRight);
CDC类的成员函数FillRect填充所有的矩形区域。包括左边和上边的边界,但不填充右边和底部边界。
void FillRect(LPCRECT lpRect, CBrush* pBrush);

lpRect: 指向一个RECT结构体或者CRect对象的指针,该结构体包含要填充的矩形的逻辑坐标。
pBrush: 指向用于填充矩形的画刷对象的指针。

//===============画刷绘制矩形===================
	//创建红色画刷
	CBrush brush(RGB(255, 0, 0));
	//获取当前窗口的设备描述表
	CClientDC dc(this);
	//利用红色画刷填充鼠标拖曳过程中的形成的矩形区域
	dc.FillRect(CRect(m_ptPoint, point), &brush);
	//===========================================

2.2 位图画刷

CBrush类有个构造函数:

CBrush (CBitmap*  pBitmap);

创建CBitmap对象时,需要调用一个初始化函数初始化位图对象。CBitmap类提供多个初始化函数:LoadBitmap、CreateBitmap、CreateBitmapIndirect等。

BOOL LoadBitmap(LPCTSTR lpszResourceName);
BOOL LoadBitmap(UINT nIDResource);

第一个声明需要一个资源的ID作为参数。首先需要给Draw程序增加一个位图资源。在资源视图的Bitmap下右键点击添加资源

//===============位图绘制===================
	//创建位图对象
	CBitmap bitmap;
	bitmap.LoadBitmap(IDB_BITMAP1);
	//创建位图画刷
	CBrush brush(&bitmap);
	//获取当前窗口的设备描述表
	CClientDC dc(this);
	//利用红色画刷填充鼠标拖曳过程中的形成的矩形区域
	dc.FillRect(CRect(m_ptPoint, point), &brush);
	//===========================================

2.3 透明画刷

利用CDC的Rectangle函数绘制一个矩形。

	//获取当前窗口的设备描述表
	CClientDC dc(this);
	//画刷填充鼠标拖曳过程中的形成的矩形区域
	//dc设备表默认有一个白色画刷
	dc.Rectangle(CRect(m_ptPoint,point));

白色画刷会覆盖底层的矩形


利用GetStockObject函数可以获得黑色或者白色的画刷句柄。参数取值NULL_BRUSH获取一个空画刷。GetStockObject函数获取的是一个画刷句柄,而我们需要将画刷句柄转化成一个画刷对象。CBrush类提供了一个FromHandle函数用来实现这样的转化功能。

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_ptPoint,point));
	//恢复原来的画刷
	dc.SelectObject(pOldBrush);

透明画刷,不遮挡底部绘制图形。

三、绘制连续线条

绘制连续的线条,首先需要得到线条的起点,然后需要捕获鼠标移动过程中的每一个点,可以通过捕获鼠标移动消息WM_MOUSEMOVE实现。
1)视图增加鼠标移动消息WM_MOUSEMOVE的响应函数OnMouseMove。只要鼠标在应用程序窗口中移动,都会进入这个消息响应函数中。

void CMFCTestView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CView::OnMouseMove(nFlags, point);
}

2)设置一个变量表示鼠标左键是否按下这一状态。
①为视图类添加一个BOOL型成员变量m_bDraw,当鼠标左键按下的时候,此变量为真;鼠标左键弹起时候,此变量为假。

②在视图的构造函数中,初始化此变量为false。
③当鼠标左键按下时,即在OnLButtonDown函数中将此变量变成TRUE;当鼠标左键弹起时,即在OnLButtonUp函数中将此变量变成FALSE。

④在OnMouseMove函数中首先对m_bDraw变量进行判断。若为真,开始画线操作,每绘制一条线段后,下次的线段起点为上一条线段的终点。所以当绘制一条线段后,应该修改线段的起点。

void CMFCTestView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CClientDC dc(this);
	if (m_bDraw == TRUE) {
		dc.MoveTo(m_ptPoint);
		dc.LineTo(point);
		//修改线段的起点
		m_ptPoint = point;

	}
	CView::OnMouseMove(nFlags, point);
}

改变画笔的颜色,使用CPen类实现。

void CMFCTestView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	//创建一个宽度为2的实线画笔
	CPen pen(PS_SOLID, 5, RGB(12, 100, 122));
	//获取当前窗口的设备描述表
	CClientDC dc(this);
	//将自己的画笔选入设备描述表
	CPen* pOldPen = dc.SelectObject(&pen);
	if (m_bDraw == TRUE) {
		dc.MoveTo(m_ptPoint);
		dc.LineTo(point);
		//修改线段的起点
		m_ptPoint = point;
	}
	//恢复原来画笔
	dc.SelectObject(pOldPen);


	CView::OnMouseMove(nFlags, point);
}

四、绘制扇形效果的线条

鼠标左键按下的点为起点保持不变,分别绘制到鼠标移动点的直线,这时就会出现扇形。绘制一个带边线的扇形。
1)视类添加一个成员函数,用来保存鼠标上一个移动点。从鼠标当前点到鼠标上个移动点的连线,绘制一条边线。
2)保存当前鼠标点,为下一条边线做准备。

void CMFCTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_bDraw = TRUE;

	//鼠标按下的起点
	m_ptPoint = point;
	//鼠标上一个移动点
	m_ptOld = point;

	CView::OnLButtonDown(nFlags, point);
}
void CMFCTestView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	
	//创建一个宽度为2的实线画笔
	CPen pen(PS_SOLID, 5, RGB(12, 100, 122));
	//获取当前窗口的设备描述表
	CClientDC dc(this);
	//将自己的画笔选入设备描述表
	CPen* pOldPen = dc.SelectObject(&pen);
	if (m_bDraw == TRUE) {
		dc.MoveTo(m_ptPoint);
		dc.LineTo(point);
		dc.LineTo(m_ptOld);
		m_ptOld=point;
	}
	//恢复原来画笔
	dc.SelectObject(pOldPen);


	CView::OnMouseMove(nFlags, point);
}

在这里插入图片描述

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值