从Windows Vista开始,Aero Glass效果被应用在了Home Premium以上的系统中(Home Basic不具有该效果)。这种效果是由DWM(Desktop Window Manager)来控制的。对于一般的程序,缺省将在窗口边框应用这种效果。但如果我们想要更多的控制,比如让客户区的一部分也呈现这种效果,那也非常的简单。不需要我们在程序里做任何复杂的算法,我们只需要调API,交给DWM去做就可以了。

一、Composition(窗口合成) and Non-client Rendering(非客户区渲染)

非客户区通常包括窗口标题栏和窗口边框。缺省状态下,非客户区会被渲染成毛玻璃效果,这也称为Compostion。有几个函数可以控制系统和当前窗口的渲染方式。同时也有Windows消息用于接受渲染模式的改变。

1.检测系统是否开启Aero Glass。使用 函数 DwmIsCompositionEnabled 检测系统当前是否开启了Aero Glass特效。它接受一个BOOL参数,并将当前状态存储到其中。函数原型:HRESULT DwmIsCompositionEnabled(BOOL *pfEnabled );

2.开启/关闭Aero Glass。使用函数DwmEnableComposition 开启或关闭系统Aero Glass效果,传入DWM_EC_ENABLECOMPOSITION 开启,传入DWM_EC_DISABLECOMPOSITION 关闭。

3.开启/关闭当前窗口的非客户区渲染。函数DwmSetWindowAttribute 用于设置窗口属性,属性DWMWA_NCRENDERING_POLICY 控制当前窗口是否使用非客户区渲染。DWMNCRP_ENABLED 开启,DWMNCRP_DISABLED 关闭。当系统的Aero Glass关闭时,设置无效。与之对应,使用函数DwmGetWindowAttribute 可以检测当前窗口属性。

4.响应系统Aero Glass的开启或关闭。当Aero Glass被开启或关闭时,Windows会发送消息WM_DWMCOMPOSITIONCHANGED , 使用 函数 DwmIsCompositionEnabled 检测状态。

5.响应窗口非客户区渲染的开启或关闭。当前窗口的非客户区渲染开启或关闭时,Windows会发送消息WM_DWMNCRENDERINGCHANGED ,wParam 指示当前状态。

二、Transition(窗口动画) and ColorizationColor(主题颜色)

Transition控制是否以动画方式显示窗口的最小化和还原。通过使用函数DwmSetWindowAttribute ,设置属性DWMWA_TRANSITIONS_FORCEDISABLED ,开启或关闭窗口动画。该设置只对当前窗口有效。

当用户通过控制面板修改主题颜色时,Windows将发送消息WM_DWMCOLORIZATIONCOLORCHANGED ,程序中通过函数DwmGetColorizationColor 取得当前主题颜色,以及是否透明。通过响应颜色的变更,可以让程序的颜色风格随主题风格而变化。

三、开启客户区域Aero Glass效果

函数DwmEnableBlurBehindWindow 开启客户区的Aero Glass效果,第一个参数为窗口句柄,第二个参数为一个DWM_BLURBEHIND 结构。其中fEnable 设置是否开启客户区Glass效果。hRgnBlur 设置Glass效果的区域,该项设置为NULL将使整个客户区呈现Glass效果,设置为一个正确的区域后,该区域将呈现Glass效果, 而区域以外为完全透明。要呈现透明效果需要客户区原始的颜色为黑色,可以在WM_PAINT 消息中绘制客户区,下面的代码使用GDI+,在Aero Glass开启时将整个窗口绘制为黑色,Aero Glass关闭时绘制为灰色:

  1. case WM_PAINT:
  2. {
  3. PAINTSTRUCT ps;
  4. HDC hDC = BeginPaint(hWnd, &ps);
  5. //不要直接使用窗口句柄创建Graphics,会导致闪烁
  6. Graphics graph(hDC);
  7. //清除客户区域
  8. RECT rcClient;
  9. GetClientRect(hWnd, &rcClient);
  10. BOOL bCompEnabled;
  11. DwmIsCompositionEnabled(&bCompEnabled);
  12. SolidBrush br(bCompEnabled? Color::Black : Color::DarkGray);
  13. graph.FillRectangle(&br, Rect(rcClient.left, rcClient.top,
  14. rcClient.right, rcClient.bottom));
  15. EndPaint(hWnd, &ps);
  16. }
  17. break;

[DllImport("dwmapi.dll")]
  static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);

struct DWM_BLURBEHIND
        {
            public uint dwFlags;
            public bool fEnable;
            public IntPtr hRgnBlur;
            public bool fTransitionOnMaximized;
        }

DWM_BLURBEHIND blur=new DWM_BLURBEHIND();
            blur.dwFlags = 0x00000001 | 0x00000002;
            blur.fEnable = true;
            DwmEnableBlurBehindWindow(this.Handle, ref blur);

GDI+的初始化和关闭仍然是必须的:

====================================================================

MSDN:

DWM_BLURBEHIND structure

Specifies Desktop Window Manager (DWM) blur-behind properties. Used by the DwmEnableBlurBehindWindow function.

Syntax

C++
typedef struct _DWM_BLURBEHIND {DWORD dwFlags;BOOL  fEnable;HRGN  hRgnBlur;BOOL  fTransitionOnMaximized;
} DWM_BLURBEHIND, *PDWM_BLURBEHIND;

Members

dwFlags

A bitwise combination of DWM Blur Behind constant values that indicates which of the members of this structure have been set.

fEnable

TRUE to register the window handle to DWM blur behind; FALSE to unregister the window handle from DWM blur behind.

hRgnBlur

The region within the client area where the blur behind will be applied. A NULL value will apply the blur behind the entire client area.

fTransitionOnMaximized

TRUE if the window's colorization should transition to match the maximized windows; otherwise, FALSE.

=====================================================

  1. //初始化GDI+
  2. ULONG_PTR token;
  3. GdiplusStartupInput input;
  4. GdiplusStartup(&token, &input, NULL);
  5. //*********************************
  6. //关闭GDI+
  7. GdiplusShutdown(token);

下面代码将整个客户区设置为Glass效果:

  1. DWM_BLURBEHIND bb = {0};
  2. bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
  3. bb.fEnable = true;
  4. bb.hRgnBlur = NULL;
  5. DwmEnableBlurBehindWindow(hWnd, &bb);

下面代码将客户区中心一个椭圆的区域设置为Glass效果:

  1. RECT rect;
  2. GetWindowRect(hWnd, &rect);
  3. int width = 300, height = 200;
  4. //居中椭圆形
  5. HRGN hRgn = CreateEllipticRgn((rect.right - rect.left)/2 - width/2,
  6. (rect.bottom - rect.top)/2 - height/2, (rect.right - rect.left)/2 + width/2,
  7. (rect.bottom - rect.top)/2 + height/2);
  8. DWM_BLURBEHIND bb = {0};
  9. bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
  10. bb.fEnable = true;
  11. bb.hRgnBlur = hRgn;
  12. DwmEnableBlurBehindWindow(hWnd, &bb);

四、窗口边框向客户区扩展

上面的方式中,非客户区和客户区之间仍然有界限。如何增大Glass效果的范围,并且消除界限呢?那就是使窗口边框向客户区扩展,利用函数DwmExtendFrameIntoClientArea 实现。函数接受一个窗口句柄和一个MARGINS 类型的参数。MARGINS指定了在上下左右4个方向上扩展的范围。如果4个值均为-1,则扩展到整个客户区。

  1. MARGINS margins = {50, 50, 50, 50};
  2. DwmExtendFrameIntoClientArea(hWnd, &margins);

  1. MARGINS margins2 = {-1};    //将扩展到整个客户区
  2. DwmExtendFrameIntoClientArea(hWnd, &margins2);

五、在窗口上绘制图形

PNG图片带有alpha通道,可以与Aero Glass很好的配合。利用GDI+显示PNG图片非常方便,下面的代码将一张PNG图片加载到内存中:

  1. Bitmap bmp  = Bitmap::FromFile(L"Ferrari.png", false);

在WM_PAINT消息处理中,将整个客户区绘制为黑色以后,利用GDI+将图片绘制到窗口客户区:

  1. //绘制图形
  2. int width = bmp->GetWidth();
  3. int height = bmp->GetHeight();
  4. Rect rc(30, 30, width, height);
  5. graph.DrawImage(bmp, rc, 0, 0, width, height, UnitPixel);

六、文本的绘制

当窗口大范围的透明之后,窗口上的文字的阅读成了一个问题。Windows的解决办法是为文字加上发光效果(Glowing),标题栏的文本使用的就是这种方式。我们在自己的程序中可以使用DrawThemeTextEx 函数来绘制发光的文字。该函数的原型定义如下:

  1. HRESULT DrawThemeTextEx(          HTHEME hTheme,
  2. HDC hdc,
  3. int iPartId,
  4. int iStateId,
  5. LPCWSTR pszText,
  6. int iCharCount,
  7. DWORD dwFlags,
  8. LPRECT pRect,
  9. const DTTOPTS *pOptions
  10. );

hTheme是一个主题句柄,可以使用OpenThemeData 获得, OpenThemeData 函数接受一个窗口句柄,和主题类的名称。iPartId和iStateId分别代表主题类中的Part和State,所有可用的主题类、Part和state在SDK的帮助文档中可以查看到。pszText是要绘制的文本。iCharCount为文字个数,-1代表绘制全部文本。dwFlags指定文本格式。pRect为文本绘制区域。pOptions中可以设定文本的发光、阴影等效果。HDC是一个设备上下文句柄,为了实现类似于标题栏中文本的发光效果,这里不能使用由BeginPaint 得到的句柄,而是要使用CreateCompatibleDC 创建一个内存中的句柄,并且要创建一张位图,通过内存句柄将文本绘制到位图上。然后再将位图转移到窗口上。下面的函数封装了绘制发光文本的过程:

  1. //绘制发光文字
  2. void DrawGlowingText(HDC hDC, LPWSTR szText, RECT &rcArea,
  3. DWORD dwTextFlags = DT_LEFT | DT_VCENTER | DT_SINGLELINE, int iGlowSize = 10)
  4. {
  5. //获取主题句柄
  6. HTHEME hThm = OpenThemeData(GetDesktopWindow(), L"TextStyle");
  7. //创建DIB
  8. HDC hMemDC = CreateCompatibleDC(hDC);
  9. BITMAPINFO bmpinfo = {0};
  10. bmpinfo.bmiHeader.biSize = sizeof(bmpinfo.bmiHeader);
  11. bmpinfo.bmiHeader.biBitCount = 32;
  12. bmpinfo.bmiHeader.biCompression = BI_RGB;
  13. bmpinfo.bmiHeader.biPlanes = 1;
  14. bmpinfo.bmiHeader.biWidth = rcArea.right - rcArea.left;
  15. bmpinfo.bmiHeader.biHeight = -(rcArea.bottom - rcArea.top);
  16. HBITMAP hBmp = CreateDIBSection(hMemDC, &bmpinfo, DIB_RGB_COLORS, 0, NULL, 0);
  17. if (hBmp == NULL) return;
  18. HGDIOBJ hBmpOld = SelectObject(hMemDC, hBmp);
  19. //绘制选项
  20. DTTOPTS dttopts = {0};
  21. dttopts.dwSize = sizeof(DTTOPTS);
  22. dttopts.dwFlags = DTT_GLOWSIZE | DTT_COMPOSITED;
  23. dttopts.iGlowSize = iGlowSize;  //发光的范围大小
  24. //绘制文本
  25. RECT rc = {0, 0, rcArea.right - rcArea.left, rcArea.bottom - rcArea.top};
  26. HRESULT hr = DrawThemeTextEx(hThm, hMemDC, TEXT_LABEL, 0, szText, -1, dwTextFlags , &rc, &dttopts);
  27. if(FAILED(hr)) return;
  28. BitBlt(hDC, rcArea.left, rcArea.top, rcArea.right - rcArea.left,
  29. rcArea.bottom - rcArea.top, hMemDC, 0, 0, SRCCOPY | CAPTUREBLT);
  30. //Clear
  31. SelectObject(hMemDC, hBmpOld);
  32. DeleteObject(hBmp);
  33. DeleteDC(hMemDC);
  34. CloseThemeData(hThm);
  35. }

在绘制了图形后,加入下面代码绘制一段文本:

  1. //绘制文本
  2. RECT rcText = {10, 10, 300, 40};
  3. DrawGlowingText(hDC, L"  一点点中文 and some english", rcText);

因为字体发光的缘故,在文本左侧留下一个空格看起来会舒服一些。效果如下:

七、缩略图关联

DWM API中还有一个功能,即缩略图关联。它允许我们将一个窗口的缩略图显示到自己窗口的客户区。缩略图不同于截图,它是实时更新的。下面的代码将在窗口客户区显示QQ影音播放器的缩略图:

  1. HRESULT hr = S_OK;
  2. HTHUMBNAIL thumbnail = NULL;
  3. HWND hWndSrc = FindWindow(_T("QQPlayer Window"), NULL);
  4. hr = DwmRegisterThumbnail(hWnd, hWndSrc, &thumbnail);
  5. if (SUCCEEDED(hr))
  6. {
  7. RECT rc;
  8. GetClientRect(hWnd, &rc);
  9. DWM_THUMBNAIL_PROPERTIES dskThumbProps;
  10. dskThumbProps.dwFlags = DWM_TNP_RECTDESTINATION | DWM_TNP_VISIBLE | DWM_TNP_OPACITY ;
  11. dskThumbProps.fVisible = TRUE;
  12. dskThumbProps.opacity = 200;
  13. dskThumbProps.rcDestination = rc;
  14. hr = DwmUpdateThumbnailProperties(thumbnail,&dskThumbProps);
  15. }

首先通过窗口标题查找到源窗口句柄,然后使用DwmRegisterThumbnail 注册缩略图关联,注册成功后,通过DwmUpdateThumbnailProperties 更新缩略图属性,其中设定了是否可视、透明度以及目标绘制区域。得到下面的效果:

源代码下载

参考资料:

-------------------------------------------------------------------------------------------------------------------------------------------------
数据库优化
数据库教程
数据库实战经验分享博客

百度云下载

百度网盘下载

无损音乐免费下载

分类:  c#+Winform, c++/汇编/逆向分析/脱壳破解

C#迅雷七窗体特效,使用DWM实现Aero Glass效果相关推荐

  1. 【转】MFC 迅雷七窗体特效,使用DWM实现Aero Glass效果

    从Windows Vista开始,Aero Glass效果被应用在了Home Premium以上的系统中(Home Basic不具有该效果).这种效果是由DWM(Desktop Window Mana ...

  2. C# Winform 窗体美化(七、Win7 Aero 毛玻璃效果)

    七.Win7 Aero 毛玻璃效果 在 Win7 上有一种 Aero 效果,毛玻璃透明效果,搭配不同风格的颜色,效果很好.在学习 Winform 美化的时候顺便看到的这种效果,也整理进来了. 注意:W ...

  3. 游戏开发入门(七)特效系统

    视频链接:游戏开发入门(七)特效系统(6节课 时常:约2小时20分钟) 该视频课程与其他本系列的课程不太一样,因为在很多游戏或者很多引擎中并没有一个专门的"特效系统",而是把各种特 ...

  4. 视频批量剪辑:如何给视频添加特效,比如:色彩变幻效果特效,怎么制作?

    视频太多,如何给视频添加特效,比如:色彩变幻效果特效,要如何制作?可以批量操作吗?可以,今天就让小编来教教大家如何去批量给视频添加色彩变幻效果特效功能 首先第一步,我们要进入视频剪辑高手并在上方三个板 ...

  5. flash特效原理:图片滑动放大效果(2)

    flash特效原理:图片滑动放大效果(1) http://blog.csdn.net/hero82748274/archive/2009/10/22/4715312.aspx 最近看了一些关于动态注册 ...

  6. python 画三角形matli_Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果示例

    本文实例讲述了Python实现PS滤镜特效Marble Filter玻璃条纹扭曲效果.分享给大家供大家参考,具体如下: 这里用 Python 实现 PS 滤镜特效,Marble Filter, 这种滤 ...

  7. AE 超人飞天特效 地面震裂崩飞效果 。SU 可以快速建立模型。室内室外。通过将CAD 的图拖拽 拉伸成面

    今天完成 工资结算发放. 继续TX PDF AE 超人飞天特效  地面震裂崩飞效果 人中枪弹爆头效果 需要相关素材, 比如地面震裂 崩飞 的素材 枪弹 的血液飞溅的素材等 跟踪,动态模糊,快速模糊, ...

  8. 计算机的aero界面是一种,Win8桌面UI大变脸 去除Aero Glass等特效

    在Windows 8话题中,谈论最多的莫过于其Metro用户界面和触摸操作为重点的设计,很多人认为微软这一步跨地太大了.今天,在官方博客中,微软介绍了改进Windows 8用户界面的更多决定. 首先, ...

  9. 69.深度解密网络项目七:利用闲鱼进行互联网有效果性创业的整体操作步骤

    网络营销推广技术.技巧深度解密(网络项目七)指南: 1.本文档适合零基础以及互联网营销推广工作者,主要讲解关于利用闲鱼进行创业的网络项目. 2.原创版权文档,任何抄袭或者全部.部分模仿都是侵权行为. ...

最新文章

  1. flat在java中的含义_java – 在flatingBy中使用flatMap的优雅方法
  2. 很有用的X264和ffmpeg的设置
  3. redis 多线程_唬人的Redis多线程,也就那么回事
  4. 深度学习可以与大数据分手吗?
  5. c json保存整型数组_命令行JSON解析神器jq
  6. 关于多线程编程您不知道的5 件事---有关高性能线程处理的微妙之处 (转)
  7. 新地址 贴吧_建议收藏 | 新媒体人必备5大工具
  8. PCBA方案开发设计—咖啡秤厨房电子秤PCBA方案
  9. 后ERP时代Oracle EBS的机遇与挑战,云和奥创沉心钻研十年谈
  10. [linux内核] 3.系统调用处理过程
  11. 模拟爬虫下载QQ空间相册高清图片
  12. 随机运算HTML5代码,js随机数学加法计算答题代码
  13. 个人重装系统前备份___1000款最杰出的软件清单:
  14. 回撤率 python_最大回撤用python怎么计算
  15. 快到假期了,还抢不到票?可以试试这两个工具
  16. Linux设置服务器定时重启
  17. springboot结合企业微信开发(一)发送消息,使用binarywang
  18. 企业微信JSSDK接口页面加载完无法立即执行的问题
  19. 什么是alpha matting?
  20. 解决阿里云服务器通过域名访问被拒

热门文章

  1. 基于迁移学习的旋转机械故障诊断方法研究学习笔记
  2. 实用工具:CMD这么有用 附源码
  3. ka电器表示什么意思_路中FU、KM、KA、KT、KV、SA、FR和SB分别是什么电器元件的文字符号...
  4. IRIG-B码产生器
  5. 可视化图表工具,让数据直观反映问题
  6. 什么是物联网,物联网未来几年的发展前景怎么样?
  7. 直接在 PS 上使用 Google Font 字体:Fontea Photoshop 扩展工具推荐
  8. 2022-07-14 第九组 韩文清
  9. 小米笔记本Pro no bootable devices 问题解决方案,干活必备
  10. 大学计算机怎么开机,电脑开机卡logo,大学生没电脑玩急坏了,这到底是怎么回事?...