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 ));


发布评论