使用DWM实现Aero Glass效果

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

DWM相关操作的MSDN说明:Desktop Window Manager (DWM) APIs.

http://msdn.microsoft.com/en-us/library/aa969527(v=VS.85).aspx

Header Dwmapi.h
Library Dwmapi.lib
DLL Dwmapi.dll

一、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_DWMNCRENDERINGCHANGEDwParam指示当前状态。

二、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关闭时绘制为灰色:

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

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

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

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

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

五、在窗口上绘制图形

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

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

六、文本的绘制

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

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

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

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

七、缩略图关联

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

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

 

源代码下载

??
  • 3
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
是的,Qt可以使用DWM(Desktop Window Manager)API来显示窗口的缩略图。DWMWindows Vista及其后续版本中引入的窗口管理器,它允许应用程序显示窗口内容的缩略图。 Qt提供了QWinThumbnailToolBar和QWinThumbnailWidget两个类来实现这个功能。QWinThumbnailToolBar类允许您在任务栏缩略图上添加自定义工具栏按钮,而QWinThumbnailWidget类允许您在任务栏缩略图上显示自定义窗口内容。 您可以使用DwmRegisterThumbnail函数注册一个窗口的缩略图,并使用DwmUpdateThumbnailProperties函数更新缩略图的属性。然后,您可以使用QWinThumbnailWidget类来显示缩略图。 以下是一个简单的示例代码,演示如何在Qt中使用DWM API显示窗口的缩略图: ```cpp #include <QApplication> #include <QMainWindow> #include <QWinThumbnailToolBar> #include <QWinThumbnailWidget> #include <Windows.h> #include <dwmapi.h> int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow mainWindow; mainWindow.show(); QWinThumbnailToolBar thumbnailToolBar(&mainWindow); thumbnailToolBar.addButton(QIcon(":/icon.png"), "Button 1"); QWinThumbnailWidget thumbnailWidget(&mainWindow); thumbnailWidget.setWindow(mainWindow.windowHandle()); HWND hwnd = (HWND)mainWindow.winId(); HRESULT hr = DwmRegisterThumbnail(hwnd, thumbnailWidget.winId(), &thumbnailWidget); if (SUCCEEDED(hr)) { DWM_THUMBNAIL_PROPERTIES props; props.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY; props.fVisible = TRUE; props.opacity = 255; props.rcDestination.left = 100; props.rcDestination.top = 100; props.rcDestination.right = 300; props.rcDestination.bottom = 300; hr = DwmUpdateThumbnailProperties(thumbnailWidget.thumbnail(), &props); } return a.exec(); } ``` 请注意,使用DWM API显示窗口的缩略图需要Windows Vista及其后续版本的操作系统,并且需要启用桌面窗口管理器(Desktop Window Manager)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值