依然是为了赶老师作业,又去学了点东西,然后做了个小项目。首先在开始做项目之前,说一下整体思路,要实现卡拉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);
}

最后效果如图所示:
在这里插入图片描述

posted on 2019-10-05 00:26  准风璧谈  阅读(164)  评论(0编辑  收藏  举报