MFC 画线,画刷,文本

CPaintDC dc(this);//只能在OnPaint函数中使用
CClientDC dc(this);//在哪里使用都可以

画直线

获得设备描述表—>MoveTo -->LineTo

CClientDC dc(this);
	dc.MoveTo(m_myPoint);
	dc.LineTo(point);

画连续直线

思路: 鼠标按下时,变量flag为true,记初始点坐标;在鼠标移动消息处理函数下,当flag为true,获得设备描述表 MoveTo LineTo
最重要的是: 鼠标移动时,消息终点为下一个的起始点
鼠标左键按下:

m_myPoint = point;
m_bDrawFlag = true;

在鼠标移动时:OnMouseMove()

if(true == m_bDrawFlag)//画连续的线,前一段的终点是此段的起点
	{
		CClientDC dc(this);
		dc.MoveTo(m_myPoint);
		dc.LineTo(point);
		m_myPoint = point;//如果没有这个,则画的线起点是一个,终点不同而已,
	}

画刷

  • 简单画刷 :主要做填充
    获得设备描述表–> 定义画刷对象—>填充
   CBrush brush(RGB(255,0,0));
	CClientDC dc(this);
	dc.FillRect(CRect(m_myPoint,point),&brush);
  • 位图画刷
    思路:获得设备描述表—>定义位图对象–>加载位图–>定义画刷对象–>填充
   CClientDC dc(this);
	CBitmap bitmap;
	bitmap.LoadBitmap(IDB_BITMAP1);//不想有虚线 可以添加头文件 resource.h
	CBrush brush(&bitmap);
	dc.FillRect(CRect(m_myPoint,point),&brush);

字体 CFont::CreatePointFont

如果在OnDraw中就不需要获取设备描述表
思路: 创建对象 -> 选入设备描述表中 -> 输出TextOut即可 -> 恢复原来的字体

   CFont::CFont font;
	font.CreatePointFont(500,_T("楷体"));
	CFont *pOldFont = pDC->SelectObject(&font);//将新的font对象选入设备描述表,该函数返回的 被替代的对象的指针
	pDC->TextOutW(200,50,_T("hello"));
	pDC->SelectObject(pOldFont);//恢复原来的环境

	pDC->TextOutW(200,150,_T("hello"));//为了测试,是不是恢复了默认的字体

输出:
第一行: 一个很大字体的 hello
第二行 : 一个很小字体的 hello

任意位置的 插入符 CWnd::CreateSolidCaret

创建–》显示–》移动–》必须要时要隐藏
函数:CWnd::CreateSolidCaret实体
函数:CreateCaret 需要CBitmap
在视图中,OnCreate中创建,是因为: 在窗口创建之前创建插入符是没有任何意义的,所以在窗口创建完后在创建插入符,故在OnCreate中

  1. 一般插入符:
CreateSolidCaret(100,100);//太大啦,不和谐,获取字体信息
ShowCaret();

发现创建的插入符太太太大了。。。怎么办呢?获取环境的插入符信息,然后给新的插入符,按照一定比例来创建。
2. 根据上下文环境设置插入符

   //创建窗口后再创建插入符,就可以,没有窗口,创建插入符也没啥作用
	//获取字体信息
	CClientDC dc(this);
    TEXTMETRIC text;//字体信息结构体
	dc.GetTextMetrics(&text);//之前给text定义的LPTEXTMETRIC  显示 参数不兼容
	CreateSolidCaret(text.tmAveCharWidth/8,text.tmHeight);//太大啦,不和谐,获取字体信息
	ShowCaret();

3. 任意位置插入插入符 SetCaretPos(point);
SetCaretPos(point);//移动插入符
鼠标左键:任意位置 设置光标位置

任意位置点击键盘输入字符

在上面任意 位置 点击 就显示插入符的基础上,写字体:

a. 定义全局变量 CString m_strCon; CPoint m_point;//TextOut中需要
b. 鼠标左键按下时,
清空m_strCon.Text("");或者 m_strCon.Empty();
m_point = point;//点击位置写入
作用: 写入时不会把上一次的内容也显示上
c. 键盘消息在WM_CHAR中处理:
在文档中显示输入字符TextOut

//键盘中输入内容
	m_strCon += (TCHAR)nChar;

	//写字体  在CDC中
	CClientDC dc(this);
	dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);

发现上面光标并没有跟着走:而且原来写的前面还有一个光标:
【解决方法】获取字符串的尺寸信息,在起点坐标的基础上,加上这个尺寸信息就可以啦

//键盘中输入内容
	m_strCon += (TCHAR)nChar;

	//写字体  在CDC中
	CClientDC dc(this);

	//光标随着输入走
	CSize size = dc.GetTextExtent(m_strCon);/获取字符串的尺寸信息
	int x = m_myPoint.x + size.cx;//不能是 m_strCon.GetLength();
	int y = m_myPoint.y;
	SetCaretPos(CPoint(x,y));

	//输出字体//起点坐标不能改
	dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);//这个必须是原来的位置,就是在按下的时候的位置  

任意位置的字符的换行、退格

void CDrawLineView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	//键盘中输入内容

	//写字体  在CDC中
	CClientDC dc(this);
	
	if(nChar == VK_RETURN)//换行
	{
		m_strCon.Empty();
		TEXTMETRIC text;//字体信息结构体
	    dc.GetTextMetrics(&text);
		m_myPoint.y += text.tmHeight;
	}
	else if(nChar == VK_BACK)//重新写
	{
	//先用白色背景重新写一个全的,然后在写一个去掉的
		COLORREF col = dc.GetBkColor();
		COLORREF Old = dc.SetTextColor(col);
		dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);
		m_strCon = m_strCon.Left(m_strCon.GetLength() - 1);
		dc.SetTextColor(Old);
	}
	else
	{
		m_strCon += (TCHAR)nChar;;
	}

	//光标随着输入走
	CSize size = dc.GetTextExtent(m_strCon);
	int x = m_myPoint.x + size.cx;
	int y = m_myPoint.y;
	SetCaretPos(CPoint(x,y));

	//输出字体
	dc.TextOutW(m_myPoint.x,m_myPoint.y,m_strCon);

	CView::OnChar(nChar, nRepCnt, nFlags);
}

字体颜色随时间变化,像歌词

m_nWidth为全局 int

if(nIDEvent == 12)
	{
		m_nWidth += 5;//+= 50时 显示不全
		CString str = _T("hello,hello,show up if you  want to have something ,you must do your best !");
		CClientDC dc(this);
		
		CSize size = dc.GetTextExtent(str);
		if(m_nWidth > size.cx)
		{
			m_nWidth = 0;
			Invalidate(false);//界面刷新
		}
		//先获得原来的颜色
		dc.TextOutW(200,50,str);
		COLORREF col = dc.GetTextColor();
		dc.SetTextColor(RGB(255,0,0));//设置新的颜色
		dc.DrawText(str,CRect(200,50,200 + m_nWidth,50 + size.cy),DT_BOTTOM);
		dc.SetTextColor(col);//恢复原来颜色
	}

函数InValidate()

原型:void Invalidate( BOOL bErase = TRUE );
功能: 该函数的作用是使整个窗口客户区无效。窗口的客户区无效意味着需要重绘。
bErase 决定了在发送WM_PAINT之前是否发送WM_ERASEBKGND.

Invalidate: 函数: 是刷新窗口,调用这个函数会产生消息WM_PAINT 程序会相应ONDraw或者OnPaint函数
bErase = false 时 不擦除背景色,直接绘图;
bErase = true 时 需要擦除背景色,会出现 刷屏的现象

InvalidateRect():

该函数的功能与Invalidate基本一样,不同的是,它是使指定的某个区域无效,需要输入一个区域,如果参数为NULL,则设置整个窗口为无效区。

函数UpdateWindow( )

原型:BOOL UpdateWindow(HWND hWnd );// hWnd 要更新的窗口的句柄
UpdateWindow函数就发送一个WM_PAINT消息来更新指定窗口的客户区。

UpdateWindow( )的作用是使窗口立即重绘。调用Invalidate等函数后窗口不会立即重绘,这是由于WM_PAINT消息的优先级很低,它需要等消息队列中的其它消息发送完后才能被处理。调用UpdateWindow函数可使WM_PAINT被直接发送到目标窗口,从而导致窗口立即重绘。
关于这几个函数的具体用法,见链接
【总结】
1.添加变量方式:选中所属类,添加变量 变量类型CPoint 可以自己输入,这样子的话可以,添加的变量会有初始化
2.在VS2010中资源时会有曲线,可以添加头文件 resource.h 就没有曲线啦,这个VS2010就是有点问题哦
3. 有多个LineTo时:
pDC->MoveTo(20,20);
pDC->LineTo(40,40);//
pDC->LineTo(50,87);//这个LineTo的起点 (MoveTo)就是上一个 LineTo的点,所以是一个折线:
线段一 点(20,20)到(40,40)
线段二 点(40,40)到(50,87)
4. 多个MoveTo时:
pDC->MoveTo(20,20);
pDC->MoveTo(40,40);//
pDC->LineTo(50,87);
最后只有一条线段: 点 (40,40)到点(50,87) ,第一个MoveTo的点就被忽略了。
5. SelectObject 函数
功能: 将新的font对象选入设备描述表,
返回值:该函数返回的 被替代的对象的指针
CFont *pOldFont = pDC->SelectObject(&font);//该函数返回的 被替代的对象的指针
再次使用的时候:pDC->SelectObject(pOldFont); 恢复成原来的,如果在输出时,字体就变成默认的字体了,而不是自己设置的字体。
所以,在使用CPen CBrush CFont BitMap 时 一定要对SelectObject成对使用
6. 函数CDC::GetTextMetrics 获得设备的字体信息,使用时,必须的CClientDC dc(this); 必须获得设备描述表
7. CSize CDC::GetTextExtent(const CString& str) const; //获取字符串的尺寸信息
8. CDC::GetTextMetrics()//获取字符的信息,高度与7中cy大小是一样子的
9. GetTextColor
COLORREF GetTextColor() const; 获得当前字体的颜色
virtual COLORREF SetTextColor(COLORREF crColor );设置当前字体颜色

猜你喜欢

转载自blog.csdn.net/u012719076/article/details/84038083
MFC
今日推荐