5.4字符输入

打字时,一个字符一个字符输入。当输入一个新的字符时,实际上是重新输入了一个字符串,因为每个字符的宽度不定。因为人眼有视觉残留效应,所以感觉是一个字符一个字符地输入。

因此实现该功能:首先给CTestView类添加WM_CHAR消息响应函数OnChar。
接着给CTestView类添加CString类型的成员变量:m_strLine,用来存储输入的字符串,同时在CTestView类构造函数中初始化为空。

鼠标点击哪里,插入符就应该移动到哪里,字符就在插入符后输入。
因此给视类添加WM_LBUTTONDOWN的消息响应函数。
把插入符移动到鼠标左键单击处,利用CWnd类的SetCaretPos函数来实现。
鼠标左键单击,插入符移动到鼠标左键单击处时,m_strLine中之前保存的输入内容得清空,重新保存新的内容到m_strLine中,用到CString类的Empty函数。

OnChar函数中需要用到鼠标左键单击的坐标,为视类添加CPoint类型变量:m_ptOrigin,访问权限为私有。在视类构造函数中设置为0。

按下回车键,插入符换到下一行,之前保存的字符串清零,插入符位置横坐标不变,纵坐标加上当前字体你的高度,调用GetTextMetrics函数。

按下退格键删除一个字符,由于每个字符宽度不定,因此:
先将文本颜色设置为背景色,输出一次;将m_strLine中字符串末尾的字符删去,产生新的m_strLine,在将文本的颜色恢复为原来的颜色,再输出一次。
获取背景色:CDC类GetBKColor函数
设置文本颜色:CDC类SetTextColor函数
virtual COLORREF SetTextColor( COLORREF crColor );
返回的是先前文本的颜色。
从字符串中删除一个字符:CString类Left函数
CString Left( int nCount ) const;
返回一个CString对象,返回指定字符串左边指定数目(nCount)的字符。

若当前不是回车符和退格符,就把它添加到m_strLine变量中。
回车符ASCII码十六进制0x0d,退格符0x08。

void CTextView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
 // TODO: Add your message handler code here and/or call default
 CClientDC dc(this);
 TEXTMETRIC tm;
 dc.GetTextMetrics(&tm);
 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+=nChar;
 }
 dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
 CView::OnChar(nChar, nRepCnt, nFlags);
}

这个时候插入符是固定不动的,这个时候我们要让插入符随着字符的输入、删除和回车而移动。
在dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);之前加入以下代码:

CSize sz=dc.GetTextExtent(m_strLine);
CPoint pt;
pt.x=m_ptOrigin.x+sz.cx;
pt.y=m_ptOrigin.y;
SetCaretPos(pt);

在这里插入图片描述

5.4.1设置字体

MFC提供了一个CFont类来专门设置字体。
在构造了一个CFont对象后,利用该类提供的初始化函数对对象进行初始化,然后才能使用该对象。
本例使用CreatePointFont函数进行初始化。
BOOL CreatePointFont( int nPointSize, LPCTSTR lpszFaceName, CDC* pDC = NULL );
第一个参数设置字体的高度,单位是一个点的十分之一。
第二个参数是字体的名称
第三个参数CDC对象指针,将第一个参数指定高度转换为逻辑单位,若为NULL,就用屏幕设备描述表进行转换。

void CTextView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
 // TODO: Add your message handler code here and/or call default
 CClientDC dc(this);
 
 CFont font;
 font.CreatePointFont(300,"华文行楷",NULL);
 CFont *pOldFont=dc.SelectObject(&font);
 
 TEXTMETRIC tm;
 dc.GetTextMetrics(&tm);
 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+=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(pOldFont);

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

在这里插入图片描述

5.4.2字幕变色功能的实现

为了输出卡拉OK字幕的平滑变色效果,调用CDC类的DrawText函数。
int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );
第一个参数:指定要输出的字符串。
第二个参数:指定文字显示的矩形。
第三个参数:指定文本的输出格式。

初始时,将文本矩形的宽度设置为较小的值,然后不断增加矩形的宽度,然后达到文字平滑变色的效果。要实现这个功能,要用到定时器。
定时器消息响应函数中,不断地增加显示文字的矩形宽度。

CWnd类SetTimer成员函数可以设置定时器。
UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );
第一个参数:非零值的定时器标识,函数成功调用就返回它。
第二个参数:定时器的时间间隔,以毫秒为单位。
第三个参数:回调函数,若设置了回调函数,就用它来处理定时器消息。

我们在视类OnCreate函数中设置定时器。即窗口产生之前。

int CTextView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
 if (CView::OnCreate(lpCreateStruct) == -1)
  return -1;
 bitmap.LoadBitmap(IDB_BITMAP1);
 CreateCaret(&bitmap);
 ShowCaret();

 SetTimer(1,100,NULL);
 // TODO: Add your specialized creation code here
 return 0;
}

接着给视类定时器消息WM_TIMER消息添加消息响应函数。

void CTextView::OnTimer(UINT nIDEvent) 
{
 // TODO: Add your message handler code here and/or call default
 CView::OnTimer(nIDEvent);
}

参数是定时器标识,区别那个定时器发来的消息。

因为DrawText函数第二个参数,矩阵的宽度需要不断增加,所以需要为CTestView类添加int型成员变量:m_nWidth。在视类构造函数中初始化为0。

对字符串资源(IDS_STRING61446)进行平滑变色。通过GetTextMetrics函数来获取矩阵的高度。

void CTextView::OnTimer(UINT nIDEvent) 
{
 // TODO: Add your message handler code here and/or call default
 m_nWidth+=5;

 CClientDC dc(this);
 TEXTMETRIC tm;
 dc.GetTextMetrics(&tm);

 CRect rect;
 rect.left=0;
 rect.top=200;
 rect.right=m_nWidth;
 rect.bottom=rect.top+tm.tmHeight;

 dc.SetTextColor(RGB(255,0,0));
 CString str;
 str.LoadString(IDS_STRING61446);
 dc.DrawText(str,rect,DT_LEFT);

CView::OnTimer(nIDEvent);
}

DT_LEFT:格式左对齐。DT_GIGHT:右对齐。
在这里插入图片描述

唱卡拉OK时,字幕会随着音乐的播放而变成另一种颜色,同时还需要判断矩形的宽度是否超过了字符串的宽度。字符串宽度计算要用到GetTextExtent函数。
在最后添加以下代码:

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

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

身影王座

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值