我有一个带有自定义窗口边框的
WPF应用程序(.NET Framework 4).我使用
WPF Shell Integration Library禁用了玻璃边框,并绘制了自己的边框.但是我想在未最大化时在窗口边框周围添加一个DropShadow.我添加了这样的阴影:
private static bool DropShadow(Window window) { try { WindowInteropHelper helper = new WindowInteropHelper(window); int val = 2; int ret1 = DwmSetWindowAttribute(helper.Handle,2,ref val,4); if (ret1 == 0) { Margins m = new Margins { Bottom = 0,Left = 0,Right = 0,Top = 0 }; int ret2 = DwmExtendFrameIntoClientArea(helper.Handle,ref m); return ret2 == 0; } else { return false; } } catch (Exception ex) { // Probably dwmapi.dll not found (incompatible OS) return false; } }
有关详细信息,请参阅:DropShadow for WPF Borderless Window
使用WindowState.Normal时,此解决方案正常工作!但是,当我最大化应用程序并禁用DWMWA_NCRENDERING_POLICY时,窗口的背景变得稍微透明,并且我的大多数控件渲染完全不同于我以前的.
在下图中,您可以看到最初的最大化状态,以及阴影代码.正如您所看到的,它完全改变了窗口的透明度和阴影代码:o
有什么我想念的吗?我一直在阅读DWM Function library,但找不到答案……
解决方法
过了一会儿,我从另一个角度重新审视了这个问题并找到了一个更好的解决方案:
public class GlassWindow : Window { [SuppressUnmanagedCodeSecurity] internal static class DwmNativeMethods { [StructLayout(LayoutKind.Sequential)] internal struct DwmMargins { public int cxLeftWidth; public int cxRightWidth; public int cyTopHeight; public int cyBottomHeight; public DwmMargins(bool fullWindow) { this.cxLeftWidth = this.cxRightWidth = this.cyTopHeight = this.cyBottomHeight = fullWindow ? -1 : 0; } } [DllImport("DwmApi.dll")] internal static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd,ref DwmMargins m); [DllImport("DwmApi.dll")] internal static extern int DwmSetWindowAttribute(IntPtr hwnd,int attr,ref int attrValue,int attrSize); } private IntPtr windowHandle; protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); WindowInteropHelper interopHelper = new WindowInteropHelper(this); this.windowHandle = interopHelper.Handle; this.ToggleAreoGlass(this.WindowState != WindowState.Maximized); this.StateChanged += this.GlassWindowStateChanged; } private void ToggleAreoGlass(bool value) { // Enable NcRenderingPolicy int attrValue = 2; int result = DwmNativeMethods.DwmSetWindowAttribute(this.windowHandle,ref attrValue,4); if (result == 0) { // Extend DwmFrame DwmNativeMethods.DwmMargins margins = new DwmNativeMethods.DwmMargins(value); DwmNativeMethods.DwmExtendFrameIntoClientArea(this.windowHandle,ref margins); } } private void GlassWindowStateChanged(object sender,EventArgs e) { this.ToggleAreoGlass(this.WindowState != WindowState.Maximized); } }