窗口程序学习笔记No.3

文本窗口程序编程

      • 创建基本插入符
      • 创建图形插入符
      • 输出一串文字
      • 键盘输入字符
      • 改变字体
      • 让字体颜色渐变

创建基本插入符

我们平时所用的文本编辑器如记事本,VS等,都有一个一闪一闪的竖线,我们称之为插入符
通常我们输入的信息都是显示在插入符之后的,而我们建立的基本MFC程序,里面是没有插入符的
所以我们首先先创建一个插入符

  1. 建立一个MFC单文档程序;
  2. 在 VIEW 类中添加消息响应函数:
    右键 VIEW 类,选择类向导,选择消息,选择 WM_CREATE,添加,编辑
    利用 CreateSolidCaret() 函数添加:
    窗口程序学习笔记No.3_第1张图片
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	// TODO:  在此添加您专用的创建代码
	CreateSolidCaret(20,100);
	ShowCaret();
	return 0;
}

这个时候我们发现插入符大小,即高度和宽度不对,而我们常用的编辑器中插入符应该是随我们使用的字体变化的,所以我们又没有办法获取到当前窗口的字体尺寸呢?
GetTextMetrics()函数:窗口程序学习笔记No.3_第2张图片
GetTextMetrics函数需要一个
TEXTMETRIC
的指针,我们看下这个结构体:
窗口程序学习笔记No.3_第3张图片
我们只需要使用高度和宽度就可以了,这里简单介绍下升序(Ascent)高度和降序(Descent)高度:
窗口程序学习笔记No.3_第4张图片
我们使用平均高度/8(除以8是因为8比较合适,大家也可以尝试下别的):

int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	// TODO:  在此添加您专用的创建代码
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
	ShowCaret();
	return 0;
}

窗口程序学习笔记No.3_第5张图片

创建图形插入符

下面我们利用 CreateCaret() 函数和位图来创建一个图形插入符
窗口程序学习笔记No.3_第6张图片
首先还是:解决方案资源管理器 - > 资源文件右键单击 - > 添加 - > 资源 - > 位图 - > 新建
窗口程序学习笔记No.3_第7张图片
然后利用 CBitmap 创建一个对象,放在 view 类的头文件里:

private:
	CBitmap bitmap;

完成函数:

int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	//CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
	
	bitmap.LoadBitmap(IDB_BITMAP1);
	CreateCaret(&bitmap);
	ShowCaret();
	return 0;
}

窗口程序学习笔记No.3_第8张图片
这样我们就有了一个图形插入符

输出一串文字

由于窗口尺寸发生变化的时候,窗口会进行重绘,所以我们直接输出会被覆盖掉
可以利用 view 类中提供的 OnPaint() 函数输出;利用 CString类创建一个字符对象

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // 用于绘制的设备上下文
	// TODO: 在此处添加消息处理程序代码
	CString str("琛小獭");
	dc.TextOutW(50,50,str);
	// 不要为绘制消息而调用 CWnd::OnPaint()
}

窗口程序学习笔记No.3_第9张图片
我们还可以利用 LoadStringW() 函数,在资源视图中找到 StringTable,双击在最下面的空格添加一个:
窗口程序学习笔记No.3_第10张图片
窗口程序学习笔记No.3_第11张图片

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // 用于绘制的设备上下文
	// TODO: 在此处添加消息处理程序代码
	CString str("琛小獭");
	dc.TextOutW(50,50,str);
	str.LoadStringW(IDS_CHEN);//填101也可
	dc.TextOutW(0,200,str);
	// 不要为绘制消息而调用 CWnd::OnPaint()
}

窗口程序学习笔记No.3_第12张图片
路径城:我们可以利用他让窗口的某些区域变得不一样

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // 用于绘制的设备上下文
	// TODO: 在此处添加消息处理程序代码
	CString str("琛小獭");
	dc.TextOutW(50,50,str);
	str.LoadStringW(IDS_CHEN);//填101也可
	dc.TextOutW(0,200,str);
	// 不要为绘制消息而调用 CWnd::OnPaint()
	dc.BeginPath();
	dc.Rectangle(50,50,50+sz.cx,50+sz.cy);
	dc.EndPath();
	//dc.SelectClipPath(RGN_DIFF);
	for (int i = 0; i < 300; i += 10)//网格
	{
		dc.MoveTo(0, i);
		dc.LineTo(300,i);
		dc.MoveTo(i,0);
		dc.LineTo(i, 300);
	}
}

窗口程序学习笔记No.3_第13张图片

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // 用于绘制的设备上下文
	// TODO: 在此处添加消息处理程序代码
	CString str("琛小獭");
	dc.TextOutW(50,50,str);
	str.LoadStringW(IDS_CHEN);//填101也可
	dc.TextOutW(0,200,str);
	// 不要为绘制消息而调用 CWnd::OnPaint()
	dc.BeginPath();
	dc.Rectangle(50,50,50+sz.cx,50+sz.cy);
	dc.EndPath();
	dc.SelectClipPath(RGN_DIFF);
	for (int i = 0; i < 300; i += 10)//网格
	{
		dc.MoveTo(0, i);
		dc.LineTo(300,i);
		dc.MoveTo(i,0);
		dc.LineTo(i, 300);
	}
}

窗口程序学习笔记No.3_第14张图片

键盘输入字符

首先我们添加一个消息响应函数 WM_CHAR,让我们输入的字符能被获取,所以需要添加一个字符串m_srtLine 用来存储输入的字符,字符输出需要一个点作为起点;当我们鼠标点击,插入符会随着点击移动,所以添加一个消息响应WM_LButtonDown,此时改变输出起点:

private:
	CPoint m_ptOrigin;
private:
	CString m_strLine;

SetCaretPos函数改变插入符位置,鼠标点击后字符应该清零,改变输出起点

void CChildView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	SetCaretPos(point);
	m_strLine.Empty();
	m_ptOrigin = point;
	CWnd::OnLButtonDown(nFlags, point);
}

如果我们输入 回车,表示换行;输入 退格,表示删除一个字符;
插入符也要随之移动

void CChildView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);

	//判断是否回车,回车清空str,并且改变插入符位置******************
	if (0x0d == nChar)
	{
		m_strLine.Empty();
		m_ptOrigin.y += tm.tmHeight;
	}
	//**************************************************************

	//判断是否是退格,退格则先将字符颜色设置为背景色****************
	//然后删除字符串中的最后一个字符,再将颜色改回来*******************
	else if (0x08 == nChar)
	{					   
		COLORREF clr = dc.SetTextColor(dc.GetBkColor());
		dc.TextOut(m_ptOrigin.x, m_ptOrigin.y,m_strLine);
		m_strLine = m_strLine.Left(m_strLine.GetLength() - 1);
		dc.SetTextColor(clr);
	}
	//*************************************************************

	//都不是则作为字符输出
	else
	{
		m_strLine += (char)nChar;
	}

	//移动插入符***************************************************
	CSize sz = dc.GetTextExtent(m_strLine);
	CPoint pt;
	pt.x = m_ptOrigin.x+sz.cx;
	pt.y = m_ptOrigin.y;
	SetCaretPos(pt);
	//*************************************************************
	
	//输出
	dc.TextOut(m_ptOrigin.x, m_ptOrigin.y, m_strLine);

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

窗口程序学习笔记No.3_第15张图片

改变字体

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

	CFont ft;//改变字体
	ft.CreatePointFont(300,"楷体",NULL);//关联字体
	CFont *pft = dc.SelectObject(&ft);//选择字体

	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);

	//判断是否回车,回车清空str,并且改变插入符位置******************
	if (0x0d == nChar)
	{
		m_strLine.Empty();
		m_ptOrigin.y += tm.tmHeight;
	}
	//**************************************************************

	//判断是否是退格,退格则先将字符颜色设置为背景色****************
	//再删除字符串中的最后一个字符,再将颜色改回来*******************
	else if (0x08 == nChar)
	{					   
		COLORREF clr = dc.SetTextColor(dc.GetBkColor());
		dc.TextOut(m_ptOrigin.x, m_ptOrigin.y,m_strLine);
		m_strLine = m_strLine.Left(m_strLine.GetLength() - 1);
		dc.SetTextColor(clr);
	}
	//*************************************************************

	//都不是则输出
	else
	{
		m_strLine += (char)nChar;
	}


	//移动插入符***************************************************
	CSize sz = dc.GetTextExtent(m_strLine);
	CPoint pt;
	pt.x = m_ptOrigin.x+sz.cx;
	pt.y = m_ptOrigin.y;
	SetCaretPos(pt);
	//*************************************************************

	dc.TextOut(m_ptOrigin.x, m_ptOrigin.y, m_strLine);

	dc.SelectObject(pft);//选择回来

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

让字体颜色渐变

添加消息响应函数 WM_TIMER,每间隔一段时间让颜色渐变的范围变大
利用DrawText函数改变颜色
首先在 OnCreate中加入Timer:

SetTimer(1, 100, NULL);

然后完成:

void CChildView::OnTimer(UINT_PTR nIDEvent)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_nWidth += 5;
	CClientDC dc(this);
	TEXTMETRIC tm;
	dc.GetTextMetrics(&tm);
	CRect rt;
	rt.left = 0;
	rt.top = 200;
	rt.right = m_nWidth;
	rt.bottom = rt.top + tm.tmHeight;
	dc.SetTextColor(RGB(255,0,0));
	CString str;
	str.LoadString(IDS_CHEN);
	dc.DrawText(str,rt,DT_LEFT);

	CSize sz = dc.GetTextExtent(str);
	if (m_nWidth > sz.cx)
	{
		m_nWidth = 0;
		dc.SetTextColor(RGB(0,255,0));
		dc.TextOut(0,200,str);
	}

	CWnd::OnTimer(nIDEvent);
}

窗口程序学习笔记No.3_第16张图片

你可能感兴趣的:(MFC学习笔记)