如何获取Windows窗口最小化、最大化、还原动画过程中的RECT值
方案1:通过DWM公开API获取实时窗口边界
直接使用DWM公开的DwmGetWindowAttribute接口,传入DWMWA_EXTENDED_FRAME_BOUNDS参数即可获取窗口在DWM合成阶段的实际绘制边界,该值会跟随系统窗口动画实时更新,不会像GetWindowRect一样直接返回动画结束后的最终值。
C#端的导入和调用示例:
using System.Runtime.InteropServices; [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport("dwmapi.dll")] private static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out RECT pvAttribute, int cbAttribute); private const int DWMWA_EXTENDED_FRAME_BOUNDS = 9; // 调用方法,在动画过程中每次需要更新裁剪时执行 public RECT GetRealTimeWindowBounds(IntPtr hwnd) { RECT bounds; DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, out bounds, Marshal.SizeOf<RECT>()); return bounds; }
你可以在CompositionTarget.Rendering事件触发时调用该方法获取实时边界,传入ClipCompositionRoot方法更新裁剪区域即可实现和系统动画的同步。
该API从Windows 7开始就已正式公开,所有支持Windows.UI.Composition亚克力效果的Windows版本都可以正常使用,没有兼容性风险。
方案2:完全接管窗口动画(无同步问题)
如果不想依赖系统动画的状态查询,可以直接关闭当前窗口的系统内置动画,自行实现最大化/最小化/还原的全部动效:
- 监听窗口的
WM_WINDOWPOSCHANGING消息,拦截窗口状态变更指令 - 自行计算动画的起始、终止位置和大小参数
- 用
Windows.UI.Composition同时驱动WPF窗口的位置位移和亚克力层的裁剪动画,两者使用相同的缓动曲线和时长,完全不会出现不同步的问题。
方案3:现有自定义动画适配
你当前已经实现了自定义的缩放动画,可以直接给裁剪区域的Offset和Size属性也绑定同样参数的关键帧动画,和缩放动画共用同一套缓动函数和时长,不需要额外查询窗口边界,即可实现裁剪和动画的同步。
不建议使用DWM私有函数实现该需求,私有接口没有官方兼容性承诺,Windows版本更新后极易出现功能失效、崩溃等问题。
内容的提问来源于stack exchange,提问作者Selastin
相关产品推荐
相关产品推荐

