用以下参数调用该API,能实现类似Aero的模糊透明效果。
参数具体含义见
https://zhuanlan.zhihu.com/p/569258181
http://www.memotech.de/WindowComposition/Text.txt
http://www.memotech.de/WindowComposition/WindowComposition.zip
DWORD accent[4] = { 3,0,0,0 };
struct {
DWORD attrib;
PVOID pvData;
UINT cbData;
} AttribData = {19,accent,sizeof(accent)};
SetWindowCompositionAttribute(m_hWnd, &AttribData);
但会有个烦人的副作用:对主窗口调用该API后,上面的控件文本也会变透明。据测试,是一切用GDI绘制的黑色像素都会变透明。要想解决这一问题,按如下步骤操作(以VS2022为例):
- 项目文件夹中新建文件app.manifest,输入如下内容:
<?xml version="1.0" encoding="utf-8"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- Windows 10 and Windows 11 --> <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" /> <!-- Windows 8.1 --> <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" /> <!-- Windows 8 --> <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" /> </application> </compatibility> </assembly>
只把Win8加入supportedOS应该也行,三个都写上也无妨。目的就是让系统知道,该程序支持Win8以上版本,以使SetLayeredWindowAttributes函数支持子窗口(见MSDN)。
-
打开项目属性,确保选了“所有配置”和“所有平台”,在左侧导航栏点清单工具—输入和输出,右侧点附加清单文件右边的向下箭头,再点编辑。
- 输入app.manifest并确定(如图),回到项目属性页面再点确定。
- 給控件加上WS_EX_LAYERED扩展样式(改CreateWindowEx参数或用SetWindowLongPtr等) ,再对其调用SetLayeredWindowAttributes,alpha通道值设为255:
实际应用时,需要给每个控件都设置一遍,用EnumChildWindows即可,不再赘述。SetLayeredWindowAttributes(hControl, 0, 255, LWA_ALPHA);
此办法实际上是给特定子窗口关闭了透明模糊效果,原理不明,我实验了好久得出了此办法。此法也可用于嵌入父窗口的子对话框,对子对话框调用该函数后,无需EnumChildWindows,即可使该子对话框及其上所有控件都不再有透明效果,如图: