用VC++6.0创建有玻璃透明特效的窗体

来源:互联网 发布:高质量c编程指南pdf 编辑:程序博客网 时间:2024/05/01 07:55
Vista/Win7的磨砂玻璃特效让人总是垂涎三尺,要是能在自己的程序中实现这一特效是再好不过的事了!
我可不仅仅说的是边框磨砂透明哦!而是全窗体!
现在就跟着我来试试这魔幻的玻璃特效吧!

首先介绍下dwm:
在除 Windows Vista Home Basic 之外的所有 Windows Vista 版本中均提供 DWM 界面,通过 dwm.exe 可以启动该界面。
系统中的所有应用程序都可以从 DWM 获益,而无需进行修改或重新编译。
不过,选择利用特定 DWM 功能的应用程序可以调用 dwmapi.dll 中的界面(DWM 的公用界面),然后将这些界面传递到 dwm.exe。
界面声明可在 dwmapi.h 中找到,并且可以从 windowssdk.msdn.microsoft.com 在线获取最新的 API 信息。
Windows Vista 在设计上对每个窗口都使用图形加速器,而不是仅针对三维 DirectX? 应用程序。
为了实现这一点,DWM 需要与 WDDM 通信,后者是图形处理器和视频内存的最终所有者。
(DWM 依赖于 milcore.dll,后者是与 Windows Presentation Foundation 共享的组件,用于输出和呈现到 DirectX。)
呈现操作由 DWM 中的单独线程处理,拥有 DirectX 设备的用户无法对其进行访问。
另外,大多数应用程序本身有处理呈现操作和 UI 的线程(如典型的 Win32? 应用程序中的 USER 消息弹出线程),但其与 DWM 的呈现线程不冲突。
DWM 获取一个窗口列表,并在树结构中管理其位图,然后将其组合到最终桌面。换言之,每个应用程序均呈现自己的位图,然后由 DWM 进行组合。
应用程序的主窗口线程呈现其场景,DWM 呈现线程对该场景进行访问,并且呈现线程通过其 DirectX 界面更新桌面。
传递的信息被压缩为仅对以前呈现的更改(差异),大型数据(如图像)则置于共享内存中。
这就潜在地允许在一台计算机上生成场景,而最终的呈现操作可以在另一台计算机上完成。
使用过 OpenGL 的三维程序员会对此体系结构非常熟悉,它允许服务器管理三维场景,并且仅将差异发送到客户端计算机。
您可以分布式呈现三维场景,并让其在任何数量的客户端计算机上使用完全硬件加速运行。此体系结构使 DWM 能够为远程桌面方案提供一级支持。
尽管 Windows Vista 将与旧版 Windows XP 兼容驱动程序一起运行,但需要让 WDDM 视频驱动程序来获得所有 DWM 功能。
与某些假定情况相反,DWM 不需要 DirectX 10,但它确实需要更多的视频/纹理内存和支持 Shader Model 2.0 或更高版本的视频卡。
使用 WDDM 的最大改变是它引入了 Video Memory Manager (VidMM),后者可以在系统内存和视频内存之间交换视频内存分布。
这意味着 WDDM 可以虚拟化视频卡的资源,因而在共享和交换视频内存方面以及在不同应用程序的不同线程之间对图形处理器进行上下文切换方面可以做得更好。
以前几乎不可能稳定地运行多个三维应用程序,原因是驱动程序无法处理上下文切换。
而且在 WDDM 出现之前,没有可用的正式计划,因此通常会出现一个 DirectX 应用程序耗尽其他应用程序的资源。
而使用 WDDM 就很难发生这种情况。Windows Vista 对驱动程序的控制也严格得多,并要求比以前 Windows 版本的驱动程序更强大可靠。

废话不多说,开始吧!
首先建立一个普通MFC工程(基本对话框)
在这里我建的工程名为glass

在glassDlg.h中添加以下代码:


typedef struct _MARGINS {     int cxLeftWidth;     int cxRightWidth;     int cyTopHeight;     int cyBottomHeight; }MARGINS,*PMARGINS; STDAPI DwmExtendFrameIntoClientArea(HWND hWnd,const MARGINS* pMarInset); 

类声明里面添加:

MARGINS m; 

在glassDlg.cpp中添加以下代码:
#include <windows .h> #include <winbase .h> #pragma comment(lib,"dwmapi") 

在OnInitDialog()中添加

m.cxLeftWidth= -1; m.cxRightWidth =-1; m.cyBottomHeight =-1; m.cyTopHeight = -1; DwmExtendFrameIntoClientArea(m_hWnd,&m); 

完了,就这么简单,你试试?

找不到dwmapi.h和dwmapi.lib?没关系,微软SDK里面去搜吧!没装?去Google吧!

若需要可以发邮件找我索取代码!

mailto:www.lcl@gmail.com

附部分dwmAPI:

DwmEnableComposition 启用或禁用 DWM 组合。DWM 将在当前进程中或直到重设前保持此设置。更改设置会导致发出WM_DWMCOMPOSITIONCHANGED 通知。
多数应用程序不需要调用此函数,但您可能需要监视 Windows 的最终消息

DwmIsCompositionEnabled 获取桌面启用 DWM 组合的状态

DwmSetWindowAttribute 为窗口设置指定的 DWM 属性的值,控制如何处理 DWM 过渡,是否允许非客户端呈现,以及 Flip 3D 将如何处理窗口。
例如,如果对某个窗口关闭非客户端呈现,则稍后扩展框架或使窗口后面的内容变模糊的要求将会失败

DwmGetWindowAttribute 为指定窗口检索指定 DWMWINDOWATTRIBUTE 的当前值

DwmGetColorizationColor 检索用于 DWM 玻璃组合的当前颜色。此值基于当前颜色方案。更改此设置将导致发出 WM_WMCOLORIZATIONCOLORCHANGED 通知

DwmDefWindowProc 在使用 WM_NCHITTEST 通知进行调用时以及由于在扩展了客户端框架而需要处理 WM_NCCALCSIZE 及类似消息时,使 DWM 命中测试位于非客户端区域

在您的程序中呈现玻璃效果相当简单。DWM 为此提供了两个函数:

DwmExtendFrameIntoClientArea 一个简单的函数,将非客户端框架的边缘扩展到窗口内

DwmEnableBlurBehindWindow 一种更为复杂的函数,对玻璃效果的呈现方式提供更多的控制

由于所有组合窗口都通过 DWM 呈现到一个屏外窗口,然后进行组合后再呈现到桌面上,因此获取这些图像并提供应用程序的实时缩略图表示并不困难。
DWM 为您提供了四个函数来控制缩略图的呈现方式

DwmQueryThumbnailSourceSize 返回 DWM 缩略图的原始大小

DwmRegisterThumbnail 创建目标窗口和源窗口之间的缩略图关系

DwmUnregisterThumbnail 删除由 DwmRegisterThumbnail 创建的 DWM 缩略图关系

DwmUpdateThumbnailProperties 更新给定缩略图的属性。



BOOL SetLayeredWindowAttributes( HWND hwnd, // handle to the layered window COLORREF crKey, // specifies the color key BYTE bAlpha, // value for the blend function DWORD dwFlags // action );

<Requirements>
Windows NT/2000/XP: Included in Windows 2000 and later.
Windows 95/98/Me: Unsupported.
Header: Declared in Winuser.h; include Windows.h.
Library: Use User32.lib.

一些常量:
WS_EX_LAYERED = 0x80000;
LWA_ALPHA = 0x2;
LWA_COLORKEY=0x1
其中dwFlags有LWA_ALPHA和LWA_COLORKEY
LWA_ALPHA被设置的话,通过bAlpha决定透明度.
LWA_COLORKEY被设置的话,则指定被透明掉的颜色为crKey,其他颜色则正常显示.
注:要使使窗体拥有透明效果,首先要有WS_EX_LAYERED扩展属性(旧sdk也没有的).

三、例子代码:
在OnInitDialog()加入:
//加入WS_EX_LAYERED扩展属性 SetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE, GetWindowLong(this->GetSafeHwnd(),GWL_EXSTYLE)^0x80000); HINSTANCE hInst = LoadLibrary("User32.DLL"); if(hInst) { typedef BOOL (WINAPI *MYFUNC)(HWND,COLORREF,BYTE,DWORD); MYFUNC fun = NULL; //取得SetLayeredWindowAttributes函数指针 fun=(MYFUNC)GetProcAddress(hInst, "SetLayeredWindowAttributes"); if(fun)fun(this->GetSafeHwnd(),0,128,2); FreeLibrary(hInst); }

原创粉丝点击