分层窗口实现千千静听的透明歌词

来源:互联网 发布:数据漫游开了会扣费吗 编辑:程序博客网 时间:2024/05/16 08:31

千千静听的透明歌词有两个特点:

1.只有在点击到文字上时,才可以拖动,也就是说窗口是不规则的。

2.当设置为总是在前面,最顶层窗口时,歌词窗口的下层窗口的刷新也能体现到歌词上来,也就是歌词依然透明。

 

实现上述两点,很简单,就要把歌词窗口设置为分层窗口就OK了。下面介绍下分层窗口(从MSDN搬来的)

 

Layered Windows
Using a layered window can significantly improve performance and visual effects for a window that has a complex shape, animates its shape,
or wishes to use alpha blending effects.

 利用分层窗口可以实现不规则窗口和窗口的Alpha混合效果。
The system automatically composes and repaints layered windows and the windows of underlying applications.
As a result, layered windows are rendered smoothly, without the flickering typical of complex window regions.
In addition, layered windows can be partially translucent, that is, alpha-blended.

操作系统自动混合和重画分层窗口而且平滑渲染和没有抖颤。

To create a layered window, specify the WS_EX_LAYERED extended window style when calling the CreateWindowEx function,
 or call the SetWindowLong function to set WS_EX_LAYERED after the window has been created.
After the CreateWindowEx call, the layered window will not become visible
until the SetLayeredWindowAttributes or UpdateLayeredWindow function has been called for this window.

首先设置窗口的属性为WS_EX_LAYERED,在调用SetLayeredWindowAttributes来设置分层窗口的透明色或alpha混合值。

Note that WS_EX_LAYERED cannot be used for child windows.

也就是说子窗口不能是分层窗口。

 

To set the opacity level or the transparency color key for a given layered window,
call SetLayeredWindowAttributes. After the call,
the system may still ask the window to paint when the window is shown or resized.
However, because the system stores the image of a layered window,
the system will not ask the window to paint if parts of it are revealed as a result of relative window moves on the desktop.

也就是当分层窗口显示和调整大小的时候,操作系统会要求窗口重绘。但是若其他窗口移动,由于操作系统本身存储了分层窗口的镜像,所以此时分层窗口并不需要重绘。个人认为可以这样理解,当千千静听的歌词窗口被设置为顶层窗口时,歌词窗口并不会因为其他原因重绘,除非自己移动或改变大小。因为操作系统存储了镜像,所以当歌词秀窗口下面窗口播放视频而歌词暂停时,歌词窗口并不会因为视频的播放而需要重绘来实现透明效果。(有点像OVERLAY页面的绘图)
Legacy applications do not need to restructure their painting code if they want to add translucency or transparency effects for a window,
只要获取一个窗口的句柄,我们可以改变其为分层窗口,并设置透明色或alpha值,无需重构窗口的绘图代码。
because the system redirects the painting of windows that called SetLayeredWindowAttributes into off-screen memory and recomposes it to achieve the desired effect.

离屏内存存储窗口的IMAGE,系统再重新组织,经过Alpha运算达到想要的效果)

 

For faster and more efficient animation or if per-pixel alpha is needed,
call UpdateLayeredWindow. UpdateLayeredWindow should be used primarily
when the application must directly supply the shape and content of a layered window,
without using the redirection mechanism the system provides through SetLayeredWindowAttributes.
In addition, using UpdateLayeredWindow directly uses memory more efficiently,
because the system does not need the additional memory required for storing the image of the redirected window.
For maximum efficiency in animating windows,
call UpdateLayeredWindow to change the position and the size of a layered window.
Please note that after SetLayeredWindowAttributes has been called,
subsequent UpdateLayeredWindow calls will fail until the layering style bit is cleared and set again.

 

Hit testing of a layered window is based on the shape and transparency of the window.
This means that the areas of the window that are color-keyed or whose alpha value is zero
will let the mouse messages through.

分层窗口命中测试是基于窗口的形状和透明度。也就是说窗口的透明色部分或alpha值为0的部分都会让鼠标通过。这是实现千千静听基于歌词命中点击窗口的实现缘由。
However, if the layered window has the WS_EX_TRANSPARENT extended window style,
the shape of the layered window will be ignored and the mouse events will
be passed to other windows underneath the layered window.

 

 

下面是改变任何一个窗口实现透明的代码,主要有两点,一改变其风格为分层窗口,二是设置窗口的alpha值。

//  ===========================================================================
//  function pointer definitions for SetLayeredWindowAttributes in User32.dll
//  ===========================================================================
typedef BOOL (WINAPI *lpfn) (HWND hWnd, COLORREF cr, BYTE bAlpha, DWORD dwFlags);
lpfn g_pSetLayeredWindowAttributes;

  HMODULE hUser32 = GetModuleHandle(_T("USER32.DLL"));
    g_pSetLayeredWindowAttributes = (lpfn)GetProcAddress(hUser32, "SetLayeredWindowAttributes");

    if (g_pSetLayeredWindowAttributes == NULL)
        AfxMessageBox ("Layering is not supported in this version of Windows", MB_ICONEXCLAMATION);

 

 

下面是改变一个窗口的透明度了。
        ::SetWindowLong(hSetWnd, GWL_EXSTYLE, GetWindowLong(hSetWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
        g_pSetLayeredWindowAttributes(m_hCurrWnd, 0, (BYTE)m_slider.GetPos(), LWA_ALPHA);

 

下面是取消一个得透明设置。

  ::SetWindowLong(*p, GWL_EXSTYLE, GetWindowLong(m_hCurrWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
        ::RedrawWindow(*p, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);

 

 

具体代码可以到CodeProject搜索,名为WinTrans。注意这样的设置只对非Child窗口有效。相信依赖于分层窗口可以实现千千静听的歌词秀效果,依据歌词的不规则来点击。只要设置好透明色即可。而且系统重定向绘图,歌词窗口无需关注下面的窗口动态来刷新。