第五课 文本
一、与文本有关的知识点:
1. WM_CHAR消息:
用户按动一下某个键,系统将发出WM_KEYDOWN, WM_KEYUP,并且参数中提供该键的虚拟扫描码。但有时用户按下某个键, 只想得到一条表示用户输入了某个字符的消息,TranslateMessage将WM_KEYDOWN, WM_KEYUP消息对转换成一条WM_CHAR消息,并在消息补充参数中提供该字符的编码。
2. CString 类:
在MFC中将对字符串的操作都封装在Cstring类中,用它来操作字符串特别方便。这一课我们要用到的是:
Empty(): 将字符串的内容清空。
Left(): 取字符串的左面几个字符串。
Format(): 得到一个格式化字符串,它的功能象C语言中的sprintf();
如: CString str = "Some Data";
str.Format("%s%d", str, 123); //str
现在的值是
”SomData123”
二、
文字处理:
1.
在
Cview
类中加入
WM
_
CHAR
消息的处理函数
OnChar
,在其中加入代码:
CClientDC dc(this);
CString str;
dc.TextOut(0,0,str);
这时,只能打出一个字符,因为
str
是局部变量,将它改为成员变量:
CString m_strInput;
2.
加入自定义字体:
CFont fn;
fn.CreatePointFont(200,"
楷体
");
dc.SelectObject(&fn);
其中,
CreatePointFont
是产生字体最简单的方法,它的第二个参数是字体的名字,具体你的系统中装了哪些字体,可以打开记事本,在其中的“格式”――“字体”中查到。
3.
设置文字颜色:
dc.SetTextColor(RGB(0,0,255));//
设置文字颜色为红色
4.
加入光标:
a.
在
CView
类中加入
WM
_
CREATE
消息的处理函数
OnCreate,
当窗口产生之后,会发出
WM
_
CREATE
消息,如果想让窗口一产生,就拥有光标,就应在
OnCreate
中加入代码。
CreateSolidCaret(100,100);//
产生一个
100
象素
*100
象素大小的实心光标
ShowCaret();
//
显示光标
*
注意:
WM
_
CREATE
消息只是代表窗口刚刚产生,此时窗口还不可见,因此在
OnCreate
中不能调用那些依赖于窗口完全激活状态的
Windows
函数。如:
GetClientRect()
b.
调整光标的大小与字体相适应:
CClientDC dc(this);
CFont fn;
fn.CreatePointFont(200,"
楷体
");
dc.SetTextColor(RGB(0,0,255));
dc.SelectObject(&fn);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm); //
得到
DC
中当前的字体信息
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
//
根据当前的大小产生光标
ShowCaret();
//
显示光标
c.
产生位图光标:
bmp.LoadBitmap(IDB_BITMAP1);
//bmp
定义为成员变量,
//IDB_BITMAP1
为事先在资源面板中做好的位图的
ID
CreateCaret(&bmp);
//
产生位图光标
ShowCaret();
//
显示光标
d.
调整光标位置,在
OnChar
中加入:
CPoint pt(tm.tmAveCharWidth*m_strInput.GetLength(),0);
//
用平均字符宽度*字符个数来得到字符串长度
SetCaretPos(pt);
//
设置光标位置
这种方法对于有些字体可以,有些字体不可以,会发生光标不在字符末尾的现象,因为在有些字体中,字符宽度并不一样,如
W
很宽,
l
很窄。
上段代码改为:
CSize sz=dc.GetTextExtent(m_strInput);
//
得到字符串的大小
CPoint pt(sz.cx,0)
;
//
用得到的字符串的长度设置
SetCaretPos(pt);
//
光标位置
5.
处理回车键:
a.
定义成员变量,用于记录字符串的输出位置。
CPoint m_ptOrigin; //
一定要在构造函数中赋初值
b.
在
OnChar
中加入代码:
if('\15'==nChar)
//
如果输入的是回车键
{
m_ptOrigin.x =0;
m_ptOrigin.y += tm.tmHeight;
//
将输出字符串的位置加一行
m_strInput.Empty();
//
清空字符串
}
else
m_strInput += nChar;
CSize sz=dc.GetTextExtent(m_strInput);
CPoint pt(sz.cx,m_ptOrigin.y);
SetCaretPos(pt);
dc.TextOut(m_ptOrigin.x ,m_ptOrigin.y,m_strInput);
6.
处理退格键:
if(8==nChar)
{
COLORREF oldclr=dc.SetTextColor(dc.GetBkColor());
//
将文字颜色设置为背景色
dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strInput);
//
用背景色将字符串再输出一遍,相当于将字符串擦去
dc.SetTextColor(oldclr);
//
将文字颜色设置为正常颜色
m_strInput=m_strInput.Left(m_strInput.GetLength()-1);
//
将字符串最后的一个字符去掉
}
else if(
‘
15
‘
==nChar)
………………
………………
三、
模拟卡拉
OK
1.
OnDraw
函数:
OnDraw
是
CView
类中的一个虚成员函数,当用户改变了窗口尺寸,或者当窗口恢复了先前被遮盖的部分,应用程序框架都会自动调用
OnDraw
函数。所以如果在
OnDraw
函数中加入绘制代码,得到的效果将是绘制的图形在窗口发生改变时还在。
for (int i=0;i<=300;i+=10)
{
pDC->MoveTo(0,i);
pDC->LineTo(300,i);
pDC->MoveTo(i,0);
pDC->LineTo(i,300);
}
将上面的代码加入
OnDraw
中,它绘制了由横、竖三十根线组成的网格,而且在窗口改变时不会消失。
2.
在绘制网格之前输出字符:
CString str1;
str1.LoadString(IDS_MYSTRING);
pDC->TextOut(0,50,str);
其中
LoadString
的作用是装入一个在资源面板中的
String Table
中定义的字符串资源,
IDS_MYSTRING
是这个字符串资源的
ID
。使用字符串资源的好处是,可以不修改代码而改变字符的内容。
这时运行程序,会发现先输出的文字被后绘制的网格穿过。
3.
用剪切区保护文字不被网格穿过:
在
DC
中有一个剪切区的概念,在剪切区中的内容将被保护起来,不被后来的绘制操作破坏。产生剪切区有两种方法:
a.
由
CRgn
来产生剪切区:
CSize sz=pDC->GetTextExtent(str); //
得到字符串的大小信息
CRgn rn;
rn.CreateRectRgn(0,50,sz.cx,sz.cy); //
产生一个区域覆盖输出的字符串
pDC->SelectClipRgn(&rn,RGN_DIFF); //
根据区域产生剪切区
b.
由
Path
来产生剪切区:
在
DC
中还有一个路径的概念,在
BeginPath()
函数和
EndPath()
函数之间
DC
上的笔所经过的路线定义了一条路径,可以通过路径来产生剪切区。需要特别强调的是:路径和区域不同,一个
DC
只对应一条路径。
pDC->BeginPath();
//
开始记录一条路径
pDC->Rectangle(0,50,sz.cx,sz.cy); //DC
上笔所经过的路线写入路径
pDC->EndPath(); //
结束记录路径
pDC->SelectClipPath(RGN_DIFF); //
由路径产生剪切区
4.
模拟卡拉
OK
的文字输出效果:
a.
在
OnCreate
中,生成定时器。
SetTimer(1,100,NULL);
其中:
第一个参数是产生的定时器的标识号,一个窗口上可以安装多个定时器,我们可以用一个数字来标识产生的是几号定时器。
第二个参数是产生的定时器的时间间隔(毫秒),当规定的时间间隔到来时,系统会向消息队列里发送一个
WM_TIMER
消息。
第三个参数是一个指向定时器回调函数的指针。当应用程序取到
WM_TIMER
消息时就会执行这个函数。如果这个参数赋为
NULL
,取到
WM_TIMER
消息时就会定义在窗口中的函数。
b.
在
CView
中加入成员变量
int m_nIndex
,用于记录矩形的边界。
c.
在
CView
中加入
WM_TIMER
消息的处理函数
OnTimer
,在其中加入代码:
CString str;
str.LoadString(IDS_MYSTRING);
CClientDC dc(this);
dc.SetTextColor(RGB(0,0,255));
CRect rect;
rect.top=50;
rect.left=0;
CSize sz=dc.GetTextExtent(str);
rect.bottom=50+sz.cy;
rect.right=m_nIndex++;
dc.DrawText(str,&rect,DT_LEFT);
if(m_nIndex>sz.cx)
{
m_nIndex=0;
dc.SetTextColor(RGB(0,255,0));
dc.TextOut(0,90,str);
}
说明:
上面的代码利用
DrawText
函数来实现卡拉
OK
逐步变色的效果(用上面讲的剪切区也可以实现)。
DrawText
函数用于在一个矩形范围内输出文本,如果文本长度大于矩形宽度,超出的部分将被裁剪掉。
我们在
OnDraw
中输出了一次
IDS_MYSTRING
标识的字符串,在
OnTimer
中,将文字颜色设置为另一种颜色,然后用
DrawText
函数在原来的位置再输出一次字符串,开始在一个小矩形上输出,每调用一次
OnTimer,
矩形的宽度变大一点,所得到的效果就是文字在一点一点的变色,模拟了卡拉
OK
的逐渐变色的效果。
评论