第五课 文本 一、与文本有关的知识点: 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的逐渐变色的效果。

评论