2024年1月2日发(作者:)

MFC对话框开启Aero“毛玻璃”半透明效果(一)

必备要求:

1. Vista 及以上操作系统。

2. VS2008 SP1 及以上编译环境。

导入下列文件:

#include

#pragma comment (lib , "" )

对话框的基类要选择 CDialogEx,而不是 CDialog。

在 OnInitDialog() 中添加下列代码:

BOOL bDwm ;

DwmIsCompositionEnabled (&bDwm );

if (bDwm )

{

MARGINS mrg = {-1};

DwmExtendFrameIntoClientArea (m_hWnd , &mrg );

SetBackgroundColor (RGB (0, 0, 0));

}

效果图:

MFC对话框开启Aero“毛玻璃”半透明效果(二)

这张图的缺陷,不用说,就是那2个按钮了。为什么会这样的呢?

因为 DWM 使用 alpha 通道来绘图。然而,诞生已久的 GDI 并不支持 alpha 通道。

想用 alpha 通道来绘图,必须使用 GDI+ 或者 WPF 这类先进的东东。

碰巧的是,GDI 里面的黑色 RGB(0, 0, 0) 和 DWM 的完全透明色 00000000 恰好是一样的。

于是,DWM 就把 GDI 的黑色当作了透明色。这就是为什么在前一个例子里面要把背景设为黑色的原因。

这样也带来一个负面效果:GDI 的控件,都是用黑色作为默认颜色的,现在成了透明色,当然会看不清楚了。

让我们改变一下,换个别的颜色作为透明色。(当然,这个颜色绝对不能在对话框中出现。)

首先要设置窗口具有 WS_EX_LAYERED 属性。可以修改资源或者调用 SetWindowLong() 实现。

有了这个属性,窗口就不能正常显示了,除非设置了透明色。

#define TRANSPARENT_COLOR RGB (200, 201, 202)

在 OnInitDialog() 中修改代码为:

SetLayeredWindowAttributes (TRANSPARENT_COLOR , 0, LWA_COLORKEY );

BOOL bDwm ;

DwmIsCompositionEnabled (&bDwm );

if (bDwm )

{

MARGINS mrg = {-1};

DwmExtendFrameIntoClientArea (m_hWnd , &mrg );

SetBackgroundColor (TRANSPARENT_COLOR );

}

效果图(右):

MFC对话框开启Aero“毛玻璃”半透明效果(三)

这张图,要说有什么不完美的地方,那就是2个按钮的边框了。

按钮是默认的圆角矩形,可那周围一圈白白的算是怎么回事?跟 Aero 很不协调!

为2个按钮添加变量,可以用类向导,也可以手动添加。注意:类型要选择 CMFCButton 而不是 CButton!

在头文件中定义变量:

private:

CMFCButton m_btnOK ;

CMFCButton m_btnCancel ;

在 DoDataExchange() 中添加数据支持:

DDX_Control (pDx , IDOK , m_btnOK );

DDX_Control (pDx , IDCANCEL , m_btnCancel );

在 OnInitDialog() 中修改代码为:

SetLayeredWindowAttributes (TRANSPARENT_COLOR , 0, LWA_COLORKEY );

BOOL bDwm ;

DwmIsCompositionEnabled (&bDwm );

if (bDwm )

{

MARGINS mrg = {-1};

DwmExtendFrameIntoClientArea (m_hWnd , &mrg );

SetBackgroundColor (TRANSPARENT_COLOR );

CMFCVisualManager ::SetDefaultManager (RUNTIME_CLASS (CMFCVisualManagerWindows ));

CMFCButton ::EnableWindowsTheming ();

}

最终效果:

MFC对话框开启Aero“毛玻璃”半透明效果(四)

本来应该不会有这篇四的,但因为发现了 bug,所以要 patch 一下。

之前那个程序,退出的时候提示内存泄漏。

Detected memory leaks!

Dumping objects ->

f:/dd/vctools/vc7libs/ship/atlmfc/src/mfc/(35) : {664} client block at

0x02BE30D8, subtype c0, 376 bytes long.

a CMFCVisualManagerWindows object at $02BE30D8, 376 bytes long

Object dump complete.

这是 CMFCVisualManagerWindows 的问题了。

解决方法:

把: CMFCVisualManager ::SetDefaultManager (RUNTIME_CLASS (CMFCVisualManagerWindows ));

至于原因嘛,暂时还不知道。难道这是 MFC 的 bug ?

换成:CMFCVisualManager ::SetDefaultManager (RUNTIME_CLASS (CMFCVisualManagerWindows7 ));