现在的位置: 首页 > 综合 > 正文

MFC学习日记五:Mfc文本编程

2018年02月03日 ⁄ 综合 ⁄ 共 4630字 ⁄ 字号 评论关闭

5:

文本编程首先需要创建一个插入符,创建插入符用CreateSolidCaret( int nWidth, int nHeight );参数分别是Caret(插入符)的宽度和高度,如果设置为0则会认为是系统窗口边界的高度与宽度。创建插入符需要在窗口创建完成之后创建,就需要在响应WM_CREATE消息的函数里去创建,响应WM_CREATE消息的函数是OnCreate;接下来就是在这个函数里用查到的创建插入符的函数CreateSolidCaret,在msdn下边解释Once created, the caret is initially hidden. To show the caret, the ShowCaret member function must be called. 

(这个插入符一旦创建了是被隐藏的,显示需要用ShowCaret函数:

CClientDC dc(this);                 

TEXTMETRIC tm; //构造一个文本输入标准的结构体

dc.GetTextMetrics(&tm); //获取当前字体的度量信息,把上面结构体地址传递进来,把获取到的字体信息填充这个结构体

CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight); //字体的平均宽度除8(是比较合理的宽度)

ShowCaret(); //显示插入符

2、创建图形的插入符,首先要构造一个CBitmap的对象,这个对象需要声明为CTestView类的成员变量,不然当OnCreate函数执行完的时候程序会销毁这个对象;

3、在窗口中输出文字,在CTestView类中有一个OnDraw函数,它是当窗口发生重绘的时候调用这个函数,为了让输出的文字在窗口中始终能够看到,就需在这个函数中进行处理

CString str("王东");           //也可以创建对象后用等号给str赋值

pDC->TextOut(50,50,str);

也可以在vc6.0左下边的ResourceView里的String Table里创建一个带ID的字符串,这样需要这个字符串的时候,只需要调用对应的ID就可以了,加载这个字符串用LoadString:

str.LoadString(IDS_WANGDONG);

pDC->TextOut(0,200,str);

Mfc当中路径层:路径层主要用于画图当中,其概念就像当年军阀割据时圈地一样,在地域划定了界线,界线之内是各自的地盘,别人不能侵犯。VC++中利用CDC提供的BeginPathEndPath这两个函数来实现路径层。BeginPath()其作用实在设备描述表中打开一个路径层,然后利用图形设备接口提供的函数进行绘图操作,例如绘制一些点、椭圆等;最后,绘图操作完成之后,应用程序调用EndPath()这个函数关闭这个路径层,这样范围就圈定好了。后面可以通过SelectClipPath这个函数进行各种操作(有或操作含有与操作等)来画图:

CString str("王东");
pDC->TextOut(50,50,str);
CSize sz=pDC->GetTextExtent(str); //这个函数用来获取特定一个字符串的显示长度与高度,需在字符串未显示之前调用
str.LoadString(IDS_WANGDONG);
pDC->TextOut(0,200,str);
pDC->BeginPath(); //打开路径层,圈定范围
pDC->Rectangle(50,50,50+sz.cx,50+sz.cy); //设置范围为str字符串显示区域
pDC->EndPath(); //范围圈定好,关闭路径层
pDC->SelectClipPath(RGN_DIFF); //把路径层范围关闭,不对其区域做操作
for(int i=0;i<300;i+=10)
{ //画出一大片网格,但须绕过路径层
pDC->MoveTo(0,i);
pDC->LineTo(300,i); //画横线
pDC->MoveTo(i,0);
pDC->LineTo(i,300); //画竖线
}

字符输入在屏幕显示功能:首先需要捕获键盘按下的消息,就需要响应WM_CHAR消息的函数OnChar,还需要把插入符移动到我们想要的位置(鼠标左键点击的位置),这里就需要响应WM_LBUTTONDOW消息,在Msdn中查到这样一个函数CWnd::SetCaretPos 它的定义是这样的:static void PASCAL SetCaretPos( POINT point );只需要在OnLButtonDown这个响应函数里调用这个函数就可以实现我们想要的;

字符输入记在一个字符串里,每当我们输入一个字符,就把整个字符串给这个字符串变量重新赋值,然后从起始点重新输出,给人感觉只是输出了最后一个字符,遵照这个原理,在CTestView的头文件中,需要声明一个m_strLineCString对象和记录起始点的m_ptOriginCPoint对象,对这两个都在构造函数中赋予初值空和0

当鼠标点击的时候我们需要插入符转移到鼠标点击的位置,在ONLButtonDown中用SetCaretPos这个函数可以将插入符设置到我们想要的位置,并且此时我们需要把起始点和字符串重新赋初值。

SetCaretPos(point);

m_strLine.Empty();

m_ptOrigin=point;

下面是字符输入输出时做的一些判断:

CClientDC dc(this);
TEXTMETRIC tm;	 //构造一个文本标准结构体
dc.GetTextMetrics(&tm);	 //获取当前文本标准赋值给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); 	//最后输出保存好的字符串

修改输出字体:这里需要用在Msdn中查到的CFont类中的函数:BOOL CreatePointFont( intnPointSize, LPCTSTRlpszFaceName, CDC*pDC = NULL );参数分别是字体的大小(12012点大小的字体)、字体的名字、转换字体的高度为一个逻辑单元,如果为空,整个屏幕设备上下文被用来做为转换。

CFont font;

font.CreatePointFont(300,"华文行楷",NULL); //创建一种字体

CFont *pOldFont=dc.SelectObject(font);    //把设计好的字体选择到设备描述表中,并且返回旧的字体

.....

.....

..... //输出我们想要的文字

dc.SelectObject(pOldFont); //把之前的字体重新选择到设备描述表中去

卡拉ok字幕变色效果,在此我在msdn中查到一个函数int DrawText( const CString&str, LPRECTlpRect, UINTnFormat );它的作用是把一个字符串放在一个区域里,按照设定的格式或者样式输出,参数分别是:要输出的字符串、矩形区域、输出样式/格式,这样就可以用这个函数的在特定大小的矩形区域输出字符串这个特性,来控制这个矩形区域的大小实现想要的效果;在此我们需要用到定时器,是UINT SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT* lpfnTimer)(HWND, UINT, UINT, DWORD) );参数分别是定时器的编号(定时器成功时则返回这个编号)、定时器的设定间隔(以毫秒为单位)、回调函数(可以为空)。在OnCreate函数中定义我们的定时器,要调用定时器还要响应WM_TIMER这个消息,那就需要增加消息处理,在这个消息处理函数中做我们想要做的事情:

首先在CTestView中增加一个成员变量,用来记录矩形区域的宽度(在初始化函数中对这个变量赋初值0):

void CTestView::OnTimer(UINT nIDEvent) 
{
// TODO: Add your message handler code here and/or call default
m_nWidth+=5;	 //没响应一次定时器,宽度+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_WANGDONG);
dc.DrawText(str,rect,DT_LEFT);	 //文本左对齐随着矩形区域变大输出
rect.top=150;
rect.bottom=rect.top+tm.tmHeight;
dc.DrawText(str,rect,DT_RIGHT);     //文本右对齐随着矩形区域变大输出
CSize sz=dc.GetTextExtent(str);
if(m_nWidth>sz.cx)
{
m_nWidth=0;	 //文本显示完全,重新初始化
dc.SetTextColor(RGB(0,255,0));	//显示完后改变文本颜色为绿色
dc.TextOut(0,200,str);
}
CView::OnTimer(nIDEvent);
}

总结:

dc.GetTextMetrics(&tm); //获取当前字体的度量信息,把上面结构体地址传递进来,把获取到的字体信息填充这个结构体

CSize sz=pDC->GetTextExtent(str); //这个函数用来获取特定一个字符串的显示长度与高度,需在字符串未显示之前调用

抱歉!评论已关闭.