第5课文本编程之一创建光标【参考资料:孙鑫VC++教学视频】
我们仍旧开始直接实践:
★相关的知识是文本编程的知识
第5课文本编程之一创建光标【参考资料:孙鑫VC++教学视频】
我们仍旧开始直接实践:
★相关的知识是文本编程的知识
现在用VC6直接实践一下MFC编程:
1、程序类型MFC AppWizard(exe)类型;
2、选择Single Document单文档应用程序
3、完成
第一项功能:创建光标(插入符);
可以在视类里面捕获消息CREATE消息:
首先在View类是覆盖在框架类之上的增加捕获wm_create消息:
第一步:增加create消息响应;
对类名右键:New Window Message and Event handlers for class CMainFrame.
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CreateSolidCaret(20,100);
ShowCaret();
return 0;
}
运行即看到插入符,也就是光标;
但是,问题是目前这个插入符的高度是固定的,怎么办?
★提醒:文本的信息在MFC里面有一个TEXTMETRIC结构体来组织的;
★注意:两个高度,升序高度和降序高度,例如g这个字母,圆圈的下边缘是base line,这个base line之上是升序高度,之下是降序高度;字体的高度是两个高度之和;
修改后的代码为:
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//获得当前文本度量/字体信息
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
//为什么要除于8.就是符合现实的高度。
ShowCaret();
return 0;
}
创建图形插入符
注意:CBitmap bitmap;如果是局部变量,那么函数结束时,该资源要被销毁的,还是看不见这个图形插入符;所以这里要增加一个view类的成员变量,私有变量;
当然:首先我们要用insert菜单,增加一个位图bitmap资源,写上一个文字,这个文字你随便写;
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//获得当前文本度量/字体信息
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
bitmap.LoadBitmap(IDB_BITMAP1);
CreateCaret(&bitmap);
ShowCaret();
return 0;
}
第5课文本编程之二输出文字【参考资料:孙鑫VC++教学视频】
算法:
第一步:准备文字;
第二步:输出文字;
程序实例:
第一步:是在View类里面已经有的ondraw函数:
CString str; CString是没有基类的。可变长度。
str="维新科学技术培训中心";
第二步:
pDC->TextOut(50,50,str); pDc是参数传递进来的一个指针。这句的含义是输出。
第二项功能:输出文字
可以在视类里面捕获消息DRAW消息:
View类里面已经有ondraw响应函数:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
增加一些代码,简单的输出文字:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
CString str;
str="维新科学技术培训中心";
pDC->TextOut(50,50,str);
}
在左边的菜单里的底下里有resource,看到一个String Table ,双击下,就能看到一些ID号。
在下面空白地方,双击,添加一个新的。
★提醒:字符串在MFC里面也是一个资源,我们同样可以通过insert菜单,插入一个字符串资源,然后我们使用这个资源;
在这里:我们insert一个字符串资源,它的ID是IDS_WEIXIN;
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
//第一步:
CString str;
str.LoadString(IDS_WEIXIN);
//第二步:
pDC->TextOut(0,200,str);
}
第5课文本编程之三路径层【参考资料:孙鑫VC++教学视频】
路径层:可以特殊显示某个部分;就相当于军阀割据,在划线里面。都是我的。
当作图的时候,如果想要在整幅图形其中的某个部分和其它部分有所区别,我们可以把这部分图形放到路径层当中,然后指定调用指定互操作模式调用SelectClipPath( int nMode )函数来使路径层和覆盖在其上新绘图剪切区域进行互操作,达到特殊效果。
步骤:
1、打开路径层;CDC::BeginPath();
2、画图,或者输出文字等等;
3、关闭路径层;CDC::EndPath();
第三项功能:路径层
可以在视类里面捕获消息DRAW消息:
View类里面已经有ondraw响应函数:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
CString str;
str="维新科学技术培训中心";
pDC->TextOut(50,50,str);
CSize sz=pDC->GetTextExtent(str);
//返回一个CSize对象。和Size的结构体类似。分别表示宽度和高度。每一个字符串都是不一样的。两个ww和两个ii的长度大小是不一样的。
这个函数是特定的,获取当前在屏幕上的字符串的信息。
放的位子也要注意的。有特定的。
str.LoadString(IDS_WEIXIN);
pDC->TextOut(0,200,str);
pDC->BeginPath();
pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);
pDC->EndPath();
}
画了一个矩形,放在路径层里面;如果这个矩形不放在路径层里面,会和文字形成叠加,覆盖了文字;
并且由于这个矩形是用白色填充的,所以就看不到文字;
下面,我们要画上网格线,横线和竖线,这些网格线不放在路径层里面:
for(int i=0;i<300;i+=10)
{
pDC->MoveTo(0,i);
pDC->LineTo(300,i); //画横线
pDC->MoveTo(i,0);
pDC->LineTo(i,300); //画竖线
}
路径层最精华的部分出现在下面:
在for循环之前增加一句话:
pDC->SelectClipPath(RGN_DIFF);
函数原型为:
BOOL SelectClipPath( int nMode );
这个函数就是路径层的精华了,它的意思是:把当前的路径层作为特殊的一个剪切区域(绘图区域限定在这个区域内)==绘图的区域 显示出来,显示出来的效果由这个函数的参数决定;
这里的参数有:
RGN_AND The new clipping region includes the intersection (overlapping areas) of the current clipping region and the current path.
此模式只保留显示路径层所有的内容,其余区域消失;
RGN_COPY The new clipping region is the current path.
RGN_DIFF The new clipping region includes the areas of the current clipping region, and those of the current path are excluded.
此模式只显示路径层部分的内容,其余区域不变,类似于“脱颖而出”;
RGN_OR The new clipping region includes the union (combined areas) of the current clipping region and the current path.
RGN_XOR The new clipping region includes the union of the current clipping region and the current path, but without the overlapping areas.
完整的代码如下:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
CString str;
str="维新科学技术培训中心";
pDC->TextOut(50,50,str);
CSize sz=pDC->GetTextExtent(str);
str.LoadString(IDS_WEIXIN);
pDC->TextOut(0,200,str);
pDC->BeginPath();
pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);
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);
}
}
第5课文本编程之四字符输入【参考资料:孙鑫VC++教学视频】
主要内容是:移动光标、字符输入、删除字符;
算法思想就是:
1.输入abc ,按照原来,是先输出a后,在a后面输出b,在b后,以b的后面为原点开始输出c。
但是这种算法不好。
2.输入a的时候,按照道理,a当做一个char。输入b的时候,把ab整体当做一个整体的char字符串,当输入c的时候,把abc整体当做一个整体的char字符串。然后刷新,然后客户的肉眼就觉得吧,后一次比前一次多了一个字母,会让人觉得,这个字母是后来弹出来的,后来加上去的。从而达到我们的目的。
So 第二种算法好。
算法:
第一步:在view类里面增加两个变量;
新点了一个点,就要把旧的那个点的字符串清空。
就出来了一个m_ptOrigin
CString m_strLine;CPoint m_ptOrigin;
第二步:初始化这两个变量,在view类的构造函数里面:
m_strLine="";
m_ptOrigin=0;
第三步:让光标跟随鼠标,在左键响应函数里面:
SetCaretPos(point);//静态的函数,point就是一个点。
第四步:编写onchar响应函数,键盘响应函数;
S1:设定字体;
CFont font; //创建一个字体
font.CreatePointFont(300,"华文行楷",NULL); //用font对象自己的初始化函数
CFont *pOldFont=dc.SelectObject(&font);
S2:获取字体尺寸信息;
CClientDC dc(this); 定义一个DC
TEXTMETRIC tm;
dc.GetTextMetrics(&tm); 获取字体的高度
S3:是回车吗?是,转到S4;否则,转到S5;
S4:清空字符串,并设定下一行的位置;
if(0x0d==nChar) //如果是回车0x0d
{
m_strLine.Empty();
m_ptOrigin.y+=tm.tmHeight;
}
S5:是退格键吗?是转到S6;否则,转到S7;
S6:消除一个字符;
退格键的算法:
S6.1:把整个字符串颜色设置成背景色,相当于消除;
S6.2:把这个字符串左边(Len-1)个字符再输出一遍;
S6.3:设定原来的颜色;
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);
//减少一个字符。m_strLine.Left比如输入5,就是把字符串的前五个输出来。
dc.SetTextColor(clr); //要把文本设置成原来的颜色。
}
S7:加入新的字符:m_strLine+=nChar;
S8:将插入符随着字符而移动;
S8.1、将光标原位置+字符宽度=光标新位置;
CSize sz=dc.GetTextExtent(m_strLine);
CPoint pt;
pt.x=m_ptOrigin.x+sz.cx;
pt.y=m_ptOrigin.y;
SetCaretPos(pt); //移动到这个点。
S9、输出文字
dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
dc.SelectObject(pOldFont);
S10、设置原来的字体:
dc.SelectObject(pOldFont);
S11、结束;
第四项功能:字符输入
给View增加两个成员变量:
CString m_strLine用于存储当前输入行的内容;
CPoint m_ptOrigin用于保存鼠标移动引起插入符改变时的新行开始位置;
CTestView::CTestView()
{
// TODO: add construction code here
m_strLine="";
m_ptOrigin=0;
}
可以在视类里面捕获消息WM_CHAR消息:
并增加消息响应函数onchar函数:
void CTestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
CView::OnChar(nChar, nRepCnt, nFlags);
}
还增加了一个左键响应函数:
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetCaretPos(point);
CView::OnLButtonDown(nFlags, point);
}
是为了光标和左键跟随着自由移动;
Onchar响应函数完整的功能:
void CTestView::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课文本编程之五卡拉ok文字变色【参考资料:孙鑫VC++教学视频】
主要内容是:卡拉ok中歌词平滑变色,这里我们是想在绿色的文字上覆盖红色的文字;
★★★★★算法:
1:33:05
第一步:设置定时器,在view中oncreate响应函数中;
SetTimer(1,100,NULL); //每隔多少时间,发送一个消息。
第一个参数是,返回值。第二个参数是每隔多少时间。是毫秒单位。第三个是回调函数。
第二步:给View类添加WM_TIMER消息响应函数;
第三步:给View添加成员变量int m_nWidth用于保存颜色随时间流逝变化的起点;
第四步:在OnTimer中添加如下代码
S1:获取字体尺寸信息;
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);//获取字体属性
S2:设置变化的矩形;
m_nWidth+=5;//每次位置增加
CRect rect(0,200, m_nWidth,200+ tm.tmHeight);
S3:设置文字颜色
dc.SetTextColor(RGB(255,0,0)); 这里是红色
S4:准备文字
CString str;
str.LoadString(IDS_WEIXIN);
S5:输出文字
dc.DrawText(str,rect,DT_LEFT);
S6:如果矩形的宽度>文字的宽度,则转到S7;否则转到S8;
S7:从头开始变色:
S7.1:设置矩形宽度为0;
S7.2:设置颜色为绿色,以示区别;
S7.3:直接输出绿色的文字;
CSize sz=dc.GetTextExtent(str);
if(m_nWidth>sz.cx)
{
m_nWidth=0;
dc.SetTextColor(RGB(0,255,0)); // 颜色设为绿色
dc.TextOut(0,200,str);
}
S8:结束
第五项功能:平滑变色
主要使用函数DrawText
函数原型:
int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );
//lpRect局限在一个矩形范围内。超出这个范围的,都截断不显示。
说明:
CDC::TextOut()是一个字母一个字母的输出,达不到平滑效果。
CDC::DrawText():将文字的输出局限于一个矩形区域,超出矩形区域的文字都被截断。利用这一特点,可每隔些时间增加矩形大小,从而可实现人眼中的平滑效果。
在OnTimer响应函数中完整代码:
void CTestView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//S1:获取字体尺寸信息;
CClientDC dc(this);
TEXTMETRIC tm;
//为了调用tm.tmHeight所以,才用TEXTMETRIC tm; 就可以获取文字的高度。
dc.GetTextMetrics(&tm);//获取字体属性
//S2:设置变化的矩形;
m_nWidth+=5;//每次位置增加
CRect rect(0,200, m_nWidth,200+ tm.tmHeight);
//S3:设置文字颜色
dc.SetTextColor(RGB(255,0,0));
//S4:准备文字
CString str;
str.LoadString(IDS_WEIXIN);
//S5:输出文字
dc.DrawText(str,rect,DT_LEFT);
//这个步骤是y方向150的位置,还有另外的一行文字;
// rect.top=150;
// rect.bottom=rect.top+tm.tmHeight;
// dc.DrawText(str,rect,DT_RIGHT);
// DT_RIGHT从字符串的最右边的字符开始输出,视觉就是浮动的,漂移的字符串,从左边飘出。。。。
//S6:如果矩形的宽度超过文字的宽度,则从头再来;
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);
}
现在用VC6直接实践一下MFC编程:
1、程序类型MFC AppWizard(exe)类型;
2、选择Single Document单文档应用程序
3、完成
第一项功能:创建光标(插入符);
可以在视类里面捕获消息CREATE消息:
首先在View类是覆盖在框架类之上的增加捕获wm_create消息:
第一步:增加create消息响应;
对类名右键:New Window Message and Event handlers for class CMainFrame.
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
CreateSolidCaret(20,100);
ShowCaret();
return 0;
}
运行即看到插入符,也就是光标;
但是,问题是目前这个插入符的高度是固定的,怎么办?
★提醒:文本的信息在MFC里面有一个TEXTMETRIC结构体来组织的;
★注意:两个高度,升序高度和降序高度,例如g这个字母,圆圈的下边缘是base line,这个base line之上是升序高度,之下是降序高度;字体的高度是两个高度之和;
修改后的代码为:
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//获得当前文本度量/字体信息
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
CreateSolidCaret(tm.tmAveCharWidth/8,tm.tmHeight);
//为什么要除于8.就是符合现实的高度。
ShowCaret();
return 0;
}
创建图形插入符
注意:CBitmap bitmap;如果是局部变量,那么函数结束时,该资源要被销毁的,还是看不见这个图形插入符;所以这里要增加一个view类的成员变量,私有变量;
当然:首先我们要用insert菜单,增加一个位图bitmap资源,写上一个文字,这个文字你随便写;
int CTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
//获得当前文本度量/字体信息
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);
bitmap.LoadBitmap(IDB_BITMAP1);
CreateCaret(&bitmap);
ShowCaret();
return 0;
}
第5课文本编程之二输出文字【参考资料:孙鑫VC++教学视频】
算法:
第一步:准备文字;
第二步:输出文字;
程序实例:
第一步:是在View类里面已经有的ondraw函数:
CString str; CString是没有基类的。可变长度。
str="维新科学技术培训中心";
第二步:
pDC->TextOut(50,50,str); pDc是参数传递进来的一个指针。这句的含义是输出。
第二项功能:输出文字
可以在视类里面捕获消息DRAW消息:
View类里面已经有ondraw响应函数:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
}
增加一些代码,简单的输出文字:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
CString str;
str="维新科学技术培训中心";
pDC->TextOut(50,50,str);
}
在左边的菜单里的底下里有resource,看到一个String Table ,双击下,就能看到一些ID号。
在下面空白地方,双击,添加一个新的。
★提醒:字符串在MFC里面也是一个资源,我们同样可以通过insert菜单,插入一个字符串资源,然后我们使用这个资源;
在这里:我们insert一个字符串资源,它的ID是IDS_WEIXIN;
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
//第一步:
CString str;
str.LoadString(IDS_WEIXIN);
//第二步:
pDC->TextOut(0,200,str);
}
第5课文本编程之三路径层【参考资料:孙鑫VC++教学视频】
路径层:可以特殊显示某个部分;就相当于军阀割据,在划线里面。都是我的。
当作图的时候,如果想要在整幅图形其中的某个部分和其它部分有所区别,我们可以把这部分图形放到路径层当中,然后指定调用指定互操作模式调用SelectClipPath( int nMode )函数来使路径层和覆盖在其上新绘图剪切区域进行互操作,达到特殊效果。
步骤:
1、打开路径层;CDC::BeginPath();
2、画图,或者输出文字等等;
3、关闭路径层;CDC::EndPath();
第三项功能:路径层
可以在视类里面捕获消息DRAW消息:
View类里面已经有ondraw响应函数:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
CString str;
str="维新科学技术培训中心";
pDC->TextOut(50,50,str);
CSize sz=pDC->GetTextExtent(str);
//返回一个CSize对象。和Size的结构体类似。分别表示宽度和高度。每一个字符串都是不一样的。两个ww和两个ii的长度大小是不一样的。
这个函数是特定的,获取当前在屏幕上的字符串的信息。
放的位子也要注意的。有特定的。
str.LoadString(IDS_WEIXIN);
pDC->TextOut(0,200,str);
pDC->BeginPath();
pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);
pDC->EndPath();
}
画了一个矩形,放在路径层里面;如果这个矩形不放在路径层里面,会和文字形成叠加,覆盖了文字;
并且由于这个矩形是用白色填充的,所以就看不到文字;
下面,我们要画上网格线,横线和竖线,这些网格线不放在路径层里面:
for(int i=0;i<300;i+=10)
{
pDC->MoveTo(0,i);
pDC->LineTo(300,i); //画横线
pDC->MoveTo(i,0);
pDC->LineTo(i,300); //画竖线
}
路径层最精华的部分出现在下面:
在for循环之前增加一句话:
pDC->SelectClipPath(RGN_DIFF);
函数原型为:
BOOL SelectClipPath( int nMode );
这个函数就是路径层的精华了,它的意思是:把当前的路径层作为特殊的一个剪切区域(绘图区域限定在这个区域内)==绘图的区域 显示出来,显示出来的效果由这个函数的参数决定;
这里的参数有:
RGN_AND The new clipping region includes the intersection (overlapping areas) of the current clipping region and the current path.
此模式只保留显示路径层所有的内容,其余区域消失;
RGN_COPY The new clipping region is the current path.
RGN_DIFF The new clipping region includes the areas of the current clipping region, and those of the current path are excluded.
此模式只显示路径层部分的内容,其余区域不变,类似于“脱颖而出”;
RGN_OR The new clipping region includes the union (combined areas) of the current clipping region and the current path.
RGN_XOR The new clipping region includes the union of the current clipping region and the current path, but without the overlapping areas.
完整的代码如下:
void CTestView::OnDraw(CDC* pDC)
{
CTestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
//简单输出文字
CString str;
str="维新科学技术培训中心";
pDC->TextOut(50,50,str);
CSize sz=pDC->GetTextExtent(str);
str.LoadString(IDS_WEIXIN);
pDC->TextOut(0,200,str);
pDC->BeginPath();
pDC->Rectangle(50, 50, 50+sz.cx, 50+sz.cy);
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);
}
}
第5课文本编程之四字符输入【参考资料:孙鑫VC++教学视频】
主要内容是:移动光标、字符输入、删除字符;
算法思想就是:
1.输入abc ,按照原来,是先输出a后,在a后面输出b,在b后,以b的后面为原点开始输出c。
但是这种算法不好。
2.输入a的时候,按照道理,a当做一个char。输入b的时候,把ab整体当做一个整体的char字符串,当输入c的时候,把abc整体当做一个整体的char字符串。然后刷新,然后客户的肉眼就觉得吧,后一次比前一次多了一个字母,会让人觉得,这个字母是后来弹出来的,后来加上去的。从而达到我们的目的。
So 第二种算法好。
算法:
第一步:在view类里面增加两个变量;
新点了一个点,就要把旧的那个点的字符串清空。
就出来了一个m_ptOrigin
CString m_strLine;CPoint m_ptOrigin;
第二步:初始化这两个变量,在view类的构造函数里面:
m_strLine="";
m_ptOrigin=0;
第三步:让光标跟随鼠标,在左键响应函数里面:
SetCaretPos(point);//静态的函数,point就是一个点。
第四步:编写onchar响应函数,键盘响应函数;
S1:设定字体;
CFont font; //创建一个字体
font.CreatePointFont(300,"华文行楷",NULL); //用font对象自己的初始化函数
CFont *pOldFont=dc.SelectObject(&font);
S2:获取字体尺寸信息;
CClientDC dc(this); 定义一个DC
TEXTMETRIC tm;
dc.GetTextMetrics(&tm); 获取字体的高度
S3:是回车吗?是,转到S4;否则,转到S5;
S4:清空字符串,并设定下一行的位置;
if(0x0d==nChar) //如果是回车0x0d
{
m_strLine.Empty();
m_ptOrigin.y+=tm.tmHeight;
}
S5:是退格键吗?是转到S6;否则,转到S7;
S6:消除一个字符;
退格键的算法:
S6.1:把整个字符串颜色设置成背景色,相当于消除;
S6.2:把这个字符串左边(Len-1)个字符再输出一遍;
S6.3:设定原来的颜色;
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);
//减少一个字符。m_strLine.Left比如输入5,就是把字符串的前五个输出来。
dc.SetTextColor(clr); //要把文本设置成原来的颜色。
}
S7:加入新的字符:m_strLine+=nChar;
S8:将插入符随着字符而移动;
S8.1、将光标原位置+字符宽度=光标新位置;
CSize sz=dc.GetTextExtent(m_strLine);
CPoint pt;
pt.x=m_ptOrigin.x+sz.cx;
pt.y=m_ptOrigin.y;
SetCaretPos(pt); //移动到这个点。
S9、输出文字
dc.TextOut(m_ptOrigin.x,m_ptOrigin.y,m_strLine);
dc.SelectObject(pOldFont);
S10、设置原来的字体:
dc.SelectObject(pOldFont);
S11、结束;
第四项功能:字符输入
给View增加两个成员变量:
CString m_strLine用于存储当前输入行的内容;
CPoint m_ptOrigin用于保存鼠标移动引起插入符改变时的新行开始位置;
CTestView::CTestView()
{
// TODO: add construction code here
m_strLine="";
m_ptOrigin=0;
}
可以在视类里面捕获消息WM_CHAR消息:
并增加消息响应函数onchar函数:
void CTestView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
CView::OnChar(nChar, nRepCnt, nFlags);
}
还增加了一个左键响应函数:
void CTestView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
SetCaretPos(point);
CView::OnLButtonDown(nFlags, point);
}
是为了光标和左键跟随着自由移动;
Onchar响应函数完整的功能:
void CTestView::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课文本编程之五卡拉ok文字变色【参考资料:孙鑫VC++教学视频】
主要内容是:卡拉ok中歌词平滑变色,这里我们是想在绿色的文字上覆盖红色的文字;
★★★★★算法:
1:33:05
第一步:设置定时器,在view中oncreate响应函数中;
SetTimer(1,100,NULL); //每隔多少时间,发送一个消息。
第一个参数是,返回值。第二个参数是每隔多少时间。是毫秒单位。第三个是回调函数。
第二步:给View类添加WM_TIMER消息响应函数;
第三步:给View添加成员变量int m_nWidth用于保存颜色随时间流逝变化的起点;
第四步:在OnTimer中添加如下代码
S1:获取字体尺寸信息;
CClientDC dc(this);
TEXTMETRIC tm;
dc.GetTextMetrics(&tm);//获取字体属性
S2:设置变化的矩形;
m_nWidth+=5;//每次位置增加
CRect rect(0,200, m_nWidth,200+ tm.tmHeight);
S3:设置文字颜色
dc.SetTextColor(RGB(255,0,0)); 这里是红色
S4:准备文字
CString str;
str.LoadString(IDS_WEIXIN);
S5:输出文字
dc.DrawText(str,rect,DT_LEFT);
S6:如果矩形的宽度>文字的宽度,则转到S7;否则转到S8;
S7:从头开始变色:
S7.1:设置矩形宽度为0;
S7.2:设置颜色为绿色,以示区别;
S7.3:直接输出绿色的文字;
CSize sz=dc.GetTextExtent(str);
if(m_nWidth>sz.cx)
{
m_nWidth=0;
dc.SetTextColor(RGB(0,255,0)); // 颜色设为绿色
dc.TextOut(0,200,str);
}
S8:结束
第五项功能:平滑变色
主要使用函数DrawText
函数原型:
int DrawText( const CString& str, LPRECT lpRect, UINT nFormat );
//lpRect局限在一个矩形范围内。超出这个范围的,都截断不显示。
说明:
CDC::TextOut()是一个字母一个字母的输出,达不到平滑效果。
CDC::DrawText():将文字的输出局限于一个矩形区域,超出矩形区域的文字都被截断。利用这一特点,可每隔些时间增加矩形大小,从而可实现人眼中的平滑效果。
在OnTimer响应函数中完整代码:
void CTestView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//S1:获取字体尺寸信息;
CClientDC dc(this);
TEXTMETRIC tm;
//为了调用tm.tmHeight所以,才用TEXTMETRIC tm; 就可以获取文字的高度。
dc.GetTextMetrics(&tm);//获取字体属性
//S2:设置变化的矩形;
m_nWidth+=5;//每次位置增加
CRect rect(0,200, m_nWidth,200+ tm.tmHeight);
//S3:设置文字颜色
dc.SetTextColor(RGB(255,0,0));
//S4:准备文字
CString str;
str.LoadString(IDS_WEIXIN);
//S5:输出文字
dc.DrawText(str,rect,DT_LEFT);
//这个步骤是y方向150的位置,还有另外的一行文字;
// rect.top=150;
// rect.bottom=rect.top+tm.tmHeight;
// dc.DrawText(str,rect,DT_RIGHT);
// DT_RIGHT从字符串的最右边的字符开始输出,视觉就是浮动的,漂移的字符串,从左边飘出。。。。
//S6:如果矩形的宽度超过文字的宽度,则从头再来;
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);
}