更新时间:2016-01-26 22:28:26浏览次数:1+次
好了,有了上面的三篇基础文章的分析后,我们可以开始讲动态歌词的实现原理了。如果你看完了上面的文章,应该是听得懂下面的原理的。如果听不懂,请回去看基础文章。
我们先看看实现的动态歌词颜色滚动覆盖效果:
【滚动了一部分的歌词,覆盖为了红色】
【滚动了大部分的文字,从左到右滚动覆盖】
动态歌词覆盖的效果是这样的:原先的歌词是蓝色的字符串,然后歌词滚动后,红色的覆盖了蓝色的字符串,随着时间的流逝,蓝色歌词字符串被红色的覆盖的越来越多,直到全部覆盖完,即表示此句歌词唱完。//输出底层的蓝色字符串
SetTextColor(hdc,RGB(0,0,255));
TextOut(hdc,50,50,txt,lstrlen(txt));
//在相同的位置输出红色字覆盖蓝色的字
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,50,50,txt,lstrlen(txt));
看到没,就这些代码就实现了颜色覆盖,而且准确覆盖。哈哈哈,其实很简单吧。txt字符数组当然是事先准备好的。memset(&logFont,0,sizeof(logFont));
logFont.lfHeight=50;
logFont.lfWeight=200;
hFont = CreateFontIndirect(&logFont);
那么字体、字符串、颜色覆盖都准备好了。我们要让颜色覆盖慢慢的滚动,那就要用一个计时器。我们同样在WM_CREATE消息中创建一个计时器,设置100ms的间隔,代码如下:SetTimer(hwnd,1,100,NULL);
在计时器消息WM_TIMER中,我们只是简单的让客户区无效,导致客户区重绘即可。动态歌词的动态滚动覆盖,就是在WM_PAINT消息中完成。我们回到歌词的动态滚动覆盖这个中心来。HRGN hrgn= CreateRectRgn(200+i,50,200+i+20,100);
CombineRgn(hRgn,hRgn,hrgn,RGN_OR);//将创建的区域合并到当前区域
i+=10;//更新下一个小区域的创建起始位置
DeleteObject(hrgn);//区域用完要删除
实际上,我们可以看到,在每一次客户区重绘的时候,都要合并形成新的区域,然后设置为当前的剪切区域。不要以为设置一次当前剪切区域后,就不用再设置了哦。因为每次消息处理的时候,DC都是重新获取的,都是初始化的默认值哦。#include "windows.h"
#include <tchar.h>
TCHAR txt[]=_T("C++技术网http://www.cjjjs.com,提供免费配套的C语言、C++语言、Win32编程、Linux编程、经典书籍下载、零基础编程课程、项目开发经验、学习经验、工作经验、数据结构、算法思维、程序员学习发展等一站式的服务。");
HRGN hRgn;
// - 项目是Unicode字符集
LRESULT CALLBACK WinProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static int i=0;
static LOGFONT logFont;
static HFONT hFont;
static RECT rectClient;
switch (message)
{
case WM_TIMER:
InvalidateRect(hwnd,NULL,FALSE);
return 0;
case WM_CREATE:
SetTimer(hwnd,1,100,NULL);
hRgn = CreateRectRgn(50,50,200,100);
memset(&logFont,0,sizeof(logFont));
logFont.lfHeight=50;
logFont.lfWeight=200;
hFont = CreateFontIndirect(&logFont);
GetClientRect(hwnd,&rectClient);
return 0;
case WM_PAINT:
{
hdc = BeginPaint(hwnd,&ps);
//形成新的区域
HRGN hrgn= CreateRectRgn(200+i,50,200+i+20,100);//创建一个小区域
CombineRgn(hRgn,hRgn,hrgn,RGN_OR);//将创建的区域合并到当前区域
i+=10;//更新下一个小区域的创建起始位置
DeleteObject(hrgn);//区域用完要删除
//输出底层的蓝色字符串
SelectObject(hdc,hFont);
SetTextColor(hdc,RGB(0,0,255));
TextOut(hdc,50,50,txt,lstrlen(txt));
//设置剪切区域
SelectObject(hdc,hRgn);//剪切区开始生效
//在相同的位置输出红色字覆盖蓝色的字
SetTextColor(hdc,RGB(255,0,0));
TextOut(hdc,50,50,txt,lstrlen(txt));
EndPaint(hwnd,&ps);
}
return 0;
case WM_DESTROY:
DeleteObject(hRgn);//删除区域
PostQuitMessage(0);
return 0;
default:
break;//跳出到默认处理
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lpCmd,int iShow)
{
TCHAR ClassName[] = _T("MyClass");
TCHAR title1[] = _T("C++技术网http://www.cjjjs.com");
WNDCLASS wndClass;
wndClass.cbClsExtra=0;
wndClass.cbWndExtra=0;
wndClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH);
wndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpfnWndProc = WinProc;
wndClass.lpszClassName = ClassName;
wndClass.lpszMenuName=NULL;
wndClass.style=CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS;
if(!RegisterClass(&wndClass))return 0;
HWND hwnd = CreateWindow(ClassName,title1,WS_OVERLAPPEDWINDOW,10,100,800,400,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,SW_SHOWNORMAL);
MSG msg;
while (GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
相关资讯