最初搞出桌面歌词的应该属于千千静听这个当年风靡天下的音乐播放软件,虽然这些年酷我酷狗已经成了这行业的老大,也不能否认桌面歌词这一创举。windows从一开始肯定是不会考虑实现这样一种功能,实现了这个功能的人确实是挺有创意,在有限的框架下做出了最大的努力,才会有桌面歌词这样一个东西,而这之后,便是一种标准了。
我们今天讨论的是如何实现桌面歌词这样一种“特效”,如果仅仅是从歌词的多型性来看,我们首先想到的恐怕是“不规则窗口”了,于是有这样一种方法就是利用SetWindowsRgn这个函数,创建一个不规则的窗口,而不规则窗口的创建即是可以按照歌词来创建了。我们唯一不知道的是如何得到这个不规则窗口呢?有一种思路是建立一个白色的bitmap,然后输出字体,即我们的歌词,之后一个个像素点扫描,根据像素点的位置来确定不规则窗口。
但是windows其实还提供了另外一个函数,即UpdateLayeredWindow,该函数可以用来更新一个分层的窗口的位置,大小,形状,内容和半透明度,函数的原型如下:
BOOL UpdateLayeredWindow(
HWND hwnd,
HDC hdcDst,
POINT *pptDst,
SIZE *psize,
HDC hdcSrc,
POINT *pptSrc,
COLORREF crKey,
BLENDFUNCTION *pblend,
DWORD dwFlags
);
hwnd 一个分层的窗口句柄;一个分层的窗口当用CreateWindowEx
函数创建窗口时指定WS_EX_LAYERED;
hdcDst 屏幕的设备上下文(DC)句柄;如果指定为空,那么将会在函数调用时自己获得。
它用于当窗口内容更新时,与调色板颜色去匹配;如果hdcDst指定为Null,将使用默认调色板;
如果hdcSrc 为NULL, hdcDst 必须 NULL;
pptDst 一个POINT结构的指针(指定新的分层窗口的屏幕位置);如果位置没有改变,pptDst可以为NULL;\
psize 一个尺寸结构的指针(指定分层窗口新的大小);如果不改变窗口大小,psize可以为NULL;如果hdcSrc为NULL,psize必须为NULL;
hdcSrc 定义了的分层窗口绘图表面的DC句柄;这个句柄可以通过CreateCompatibleDC函数获得;如果窗口的可视范围和形状不发生变化,hdcSrc可以为NULL。
pptSrc 一个POINT结构的指针(指定了分层窗口在设备上下文的位置);如果hdcSrc为NULL,pptSrc应该是NULL;
crKey 指向一个COLORREF值(当合成分层窗口时使用指定颜色键值)。要生成COLORREF,使用RGB宏;
pblend 指向一个BLENDFUNCTION结构(当合成分层窗口时使用指定透明度值)。
dwFlags 这个参数可以是以下值之一:
ULW_ALPHA 使用pblend为混合功能,如果显示模式为256色或更少,这个值和ULW_OPAQUE效果相同;
ULW_COLORKEY 使用crKey值为颜色的透明度
ULW_OPAQUE 绘制一个不透明分层窗口
如果hdcSrc为NULL,dwFlags应为零
返回值:
如果函数成功,返回值为非零;如果函数失败,返回值为零。为了获得更多的错误信息,调用GetLastError
于是我们有了一种思路来利用这个函数实现我们的桌面歌词效果,步骤如下:
1、调用这个在user32.dll中的函数,我们需要先获得函数的地址:
void Lyric::SetWindowAlpha( HDC hdcDst, POINT *pptDst,SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey,BLENDFUNCTION *pblend, DWORD dwFlags) { HINSTANCE hInst = LoadLibrary(_T("User32.DLL")); if(hInst) { typedef BOOL (WINAPI *pfnUpdateLayeredWindow)(HWND hWnd, HDC hdcDst, POINT *pptDst, SIZE *psize, HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend, DWORD dwFlags); pfnUpdateLayeredWindow fun = NULL; fun = (pfnUpdateLayeredWindow)GetProcAddress(hInst, "UpdateLayeredWindow"); if (fun) { fun(this->m_hWnd, hdcDst, pptDst,psize, hdcSrc, pptSrc, crKey,pblend, dwFlags); FreeLibrary(hInst); } } }
2、建立一个windows扩展属性的窗口,并设置为WS_EX_LAYERED属性。
//注册窗口类 WNDCLASSEX wcex; memset(&wcex, 0, sizeof(wcex)); wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = ChaoProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wcex.lpszMenuName = NULL; wcex.lpszClassName = _T("Lyric"); wcex.hIconSm = NULL; RegisterClassEx(&wcex); //建立窗口 m_hWnd = CreateWindowEx(/*WS_EX_LAYERED | WS_EX_TRANSPARENT*/WS_EX_TOPMOST, _T("ChaoShadow"), NULL, WS_POPUPWINDOW , 0,0, nSize, nSize, hParentWnd, NULL, s_hInstance, NULL); //设置扩展风格 SetWindowLong(m_hWnd,GWL_EXSTYLE,GetWindowLong(m_hWnd,GWL_EXSTYLE)^0x80000);
3、建立白色位图,输出文字。
HDC hDc= GetWindowDC(m_hWnd); SetTextColor(hDc,RGB(37,124,89)); SetBkColor(hDc,RGB(255,255,255)); HDC hMen; hMen = CreateCompatibleDC(NULL); SetBkColor(hMen,RGB(255,255,255)); HBITMAP hBitmap; hBitmap = CreateCompatibleBitmap(hMen,nFontSize,nFontSize); SelectObject(hMen,hBitmap); RECT rect={0,0,nFontSize,nFontSize}; HBRUSH hBrushBg = CreateSolidBrush(RGB(255,255,255)); FillRect(hMen, &rect, hBrushBg); DeleteObject(hBrushBg); HFONT hFont; //创建字体 hFont=CreateFont(nFontSize,0,0,0,800,false,false,0, ANSI_CHARSET,OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS,_T("华文行楷")); SelectObject(hMen,hFont); TextOut(hMen,0,0,"Happy new year!",14);
4、设置非字体区域透明:
POINT pDst={0,0}; POINT PSrc={0,0}; SIZE mySize={nFontSize,nFontSize}; BLENDFUNCTION blendPixelFunction= { AC_SRC_OVER, 0, 0, AC_SRC_ALPHA }; SetWindowAlpha(hDc,&pDst, &mySize,hMen,&PSrc,RGB(255,255,255),&blendPixelFunction,1);
好了,至此我们已经完成了桌面歌词的效果了,如果你舍得花时间再研究研究的话,就是以下的效果了。怎么样,还可以吧。
如无特别说明,本博客文章皆为原创。转载请说明,来自吵吵博客。
原文链接:http://chaochaoblog.com/archives/1407
吵吵微信朋友圈,请付款实名加入:
谢谢博主分享学习了啊