依然是为了赶老师作业,又去学了点东西,然后做了个小项目。首先在开始做项目之前,说一下整体思路,要实现卡拉OK字幕效果,就要对文本类与定时器有一定的掌握,通过定时器的更新,可以实现字体颜色的变化,与字幕的跳转。
第一步:创建定时器:
1、创建mfc单文档项目,在view类添加消息响应事件WM_CREATE与WM_TIMER;
2、在OnCreate函数中添加定时器,定时器id号为1,100毫秒运行一次,代码如下:
int CKalaOkView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
// TODO: Add your specialized creation code here
SetTimer(1,100,NULL); //创建定时器
return 0;
}
第二步:定义变量
在view类头文件添加变量
private:
CString str[4]; //用于储存歌词
int songNum; //用于选择歌词
int m_nWidth; //用于定时器更新
int i; //第一句歌词的实现
CString strs; //储存客户区的歌词
bool start; //开始与暂停播放
在view类构造函数中初始化变量,这里选择《勉为其难》,主要是我做这个项目的时候一直在听这首歌,为了节省时间,我就只抄了几句歌词
str[0]="王冕 - 勉为其难";
str[1]="还要多少时间才能停止想念";
str[2]="在这样的夜晚你是否和我一样";
str[3]="不知道该找谁聊天";
m_nWidth=0;
songNum=0;
i=0;
strs=str[0];
start=false; //开始暂停
第三步:在OnTimer函数里设置画家,并让定时器开始计时
m_nWidth+=10;//每次移动10个像素
/*设置两个画家,并为其设置字体,颜色,大小,画家1用于显示底色,画家2用于改变颜色*/
CClientDC dc1(this);
CClientDC dc2(this);
CFont font;
font.CreatePointFont(400,"宋体",NULL);
CFont *pOldFont1=dc1.SelectObject(&font);
CFont *pOldFont2=dc2.SelectObject(&font);
dc1.SetTextColor(RGB(255,50,0));
dc2.SetTextColor(RGB(0,50,255));
第四步:在OnTimer函数里继续写,用于显示歌词与改变歌词颜色
由于注释都比较清晰,我就不再说明:
/*确定画家2绘图的地方*/
TEXTMETRIC tm;
dc2.GetTextMetrics(&tm);
CRect rect;
rect.left=400;
rect.top=400;
rect.right=400+m_nWidth;
rect.bottom=rect.top+tm.tmHeight;
if(i==0){ //第一次播放,显示第一行歌词
dc1.TextOut(400,400,strs);
}
dc2.DrawText(strs,rect,DT_LEFT);//画家2绘图,改变歌词颜色
CSize sz=dc2.GetTextExtent(strs);//获得歌词长度
/*实现歌词更新与循环播放*/
if(m_nWidth>sz.cx)
{
m_nWidth=0;
if(songNum<3){
songNum++;
}else{
songNum=0;
}
strs=str[songNum];
dc1.TextOut(400,400," ");//清空屏幕
dc1.TextOut(400,400,strs);
}
i++;//i>0,不需要再单独显示第一行歌词
第五步:实现播放与暂停
我们创建鼠标点击事件,通过改变变量start,让变量控制播放与暂停
鼠标事件如下:
void CKalaOkView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
start=!start;
CView::OnLButtonDown(nFlags, point);
}
之后,OnTimer函数代码如下:
void CKalaOkView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(start){//鼠标确定开始
m_nWidth+=10;//每次移动10个像素
/*设置两个画家,并为其设置字体,颜色,大小,画家1用于显示底色,画家2用于改变颜色*/
CClientDC dc1(this);
CClientDC dc2(this);
CFont font;
font.CreatePointFont(400,"宋体",NULL);
CFont *pOldFont1=dc1.SelectObject(&font);
CFont *pOldFont2=dc2.SelectObject(&font);
dc1.SetTextColor(RGB(255,50,0));
dc2.SetTextColor(RGB(0,50,255));
/*确定画家2绘图的地方*/
TEXTMETRIC tm;
dc2.GetTextMetrics(&tm);
CRect rect;
rect.left=400;
rect.top=400;
rect.right=400+m_nWidth;
rect.bottom=rect.top+tm.tmHeight;
if(i==0){ //第一次播放,显示第一行歌词
dc1.TextOut(400,400,strs);
}
dc2.DrawText(strs,rect,DT_LEFT);//画家2绘图,改变歌词颜色
CSize sz=dc2.GetTextExtent(strs);//获得歌词长度
/*实现歌词更新与循环播放*/
if(m_nWidth>sz.cx)
{
m_nWidth=0;
if(songNum<3){
songNum++;
}else{
songNum=0;
}
strs=str[songNum];
dc1.TextOut(400,400," ");//清空屏幕
dc1.TextOut(400,400,strs);
}
i++;//i>0,不需要再单独显示第一行歌词
}
CView::OnTimer(nIDEvent);
}
我们再为使用者提供提示,在OnDraw函数里添加代码:
void CKalaOkView::OnDraw(CDC* pDC)
{
CKalaOkDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
CFont font;
font.CreatePointFont(300,"微软雅黑",NULL);
CFont *pOldFont1=pDC->SelectObject(&font);
CString s("鼠标点击开始播放,再次点击暂停");
pDC->TextOut(400,50,s);
}
至此,一个简单的项目就完成了,效果如图:
总体来说,这个项目是很容易的,都不好意思说它是一个项目了,只能说是一个效果,但是其中可以学到文本类与定时器的内容。而且以后如果想做播放器的话,这个项目也非常具有参考价值。
再次补充:
突然才发现老师有要求,说要实现图片切换,所以的话就要引入几张图片,然后让每次歌词变化的时候都显示出来,这里如果想要改变图片的大小,那么就要获取图片的大小,但是由于我这里图片背景均为白色,方便起见,我就直接使用数字了,具体详细方法可以参照MFC开发——点击页面生成图标功能
代码如下:
头文件中添加数组
CBitmap bitmap[4]; //存储图片
构造函数初始化该数组:
bitmap[0].LoadBitmap(IDB_BITMAP1);//加载图片
bitmap[1].LoadBitmap(IDB_BITMAP2);
bitmap[2].LoadBitmap(IDB_BITMAP3);
bitmap[3].LoadBitmap(IDB_BITMAP4);
最后在定时器中实现:
void CKalaOkView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if(start){//鼠标确定开始
m_nWidth+=10;//每次移动10个像素
/*设置3个画家,并为其设置字体,颜色,大小,画家1用于显示底色,画家2用于改变颜色,画家3用于显示图片*/
CClientDC dc1(this);
CClientDC dc2(this);
CClientDC dc3(this);
CFont font;
font.CreatePointFont(400,"宋体",NULL);
CFont *pOldFont1=dc1.SelectObject(&font);
CFont *pOldFont2=dc2.SelectObject(&font);
dc1.SetTextColor(RGB(255,50,0));
dc2.SetTextColor(RGB(0,50,255));
/*确定画家2绘图的地方*/
TEXTMETRIC tm;
dc2.GetTextMetrics(&tm);
CRect rect;
rect.left=400;
rect.top=400;
rect.right=400+m_nWidth;
rect.bottom=rect.top+tm.tmHeight;
if(i==0){
CBrush brush(&bitmap[i]);//创建画刷
CRect rect(190,110,1200,880);
dc3.FillRect(&rect,&brush);//用画刷出一个矩形
//第一次播放,显示第一行歌词
dc1.TextOut(400,400,strs);
}
dc2.DrawText(strs,rect,DT_LEFT);//画家2绘图,改变歌词颜色
CSize sz=dc2.GetTextExtent(strs);//获得歌词长度
/*实现歌词更新与循环播放*/
if(m_nWidth>sz.cx)
{
m_nWidth=0;
if(songNum<3){
songNum++;
}else{
songNum=0;
}
strs=str[songNum];
CBrush brush(&bitmap[songNum]);//创建画刷
CRect rect(190,110,1200,880);
dc3.FillRect(&rect,&brush);//用画刷出一个矩形
dc1.TextOut(400,400," ");//清空屏幕
dc1.TextOut(400,400,strs);
}
i++;//i>0,不需要再单独显示第一行歌词
}
CView::OnTimer(nIDEvent);
}
最后效果如图所示: