wpf - WPF 无边框窗口的 DropShadow

标签 wpf windows transparency dropshadow

我有一个 WindowStyle 设置为无的 WPF 窗口。有什么方法可以强制此窗口投下阴影(就像 WindowStyle 不是 none 时得到的那样)?我不想将 AllowTransparency 设置为 true,因为它会影响性能。而且我也不想禁用硬件渲染(我在某处读到透明度在禁用时表现更好)。

最佳答案

我写了一个小实用程序类,它能够完全按照您的要求进行操作:在无边框 Window 上放置一个标准阴影,但将 AllowsTransparency 设置为 假的

您只需调用 DropShadowToWindow(Window window) 方法。最好在窗口的构造函数的 InitializeComponent() 之后立即调用此调用,但即使在显示窗口之后调用它也能正常工作。

using System;
using System.Drawing.Printing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

public static class DwmDropShadow
{
    [DllImport("dwmapi.dll", PreserveSig = true)]
    private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);

    [DllImport("dwmapi.dll")]
    private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref Margins pMarInset);

    /// <summary>
    /// Drops a standard shadow to a WPF Window, even if the window is borderless. Only works with DWM (Windows Vista or newer).
    /// This method is much more efficient than setting AllowsTransparency to true and using the DropShadow effect,
    /// as AllowsTransparency involves a huge performance issue (hardware acceleration is turned off for all the window).
    /// </summary>
    /// <param name="window">Window to which the shadow will be applied</param>
    public static void DropShadowToWindow(Window window)
    {
        if (!DropShadow(window))
        {
            window.SourceInitialized += new EventHandler(window_SourceInitialized);
        }
    }

    private static void window_SourceInitialized(object sender, EventArgs e)
    {
        Window window = (Window)sender;

        DropShadow(window);

        window.SourceInitialized -= new EventHandler(window_SourceInitialized);
    }

    /// <summary>
    /// The actual method that makes API calls to drop the shadow to the window
    /// </summary>
    /// <param name="window">Window to which the shadow will be applied</param>
    /// <returns>True if the method succeeded, false if not</returns>
    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;
        }
    }
}

关于wpf - WPF 无边框窗口的 DropShadow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3372303/

相关文章:

.net - WPF 后台 worker 和 ProgressBar

c++ - 使用 Windows API 获取文件关联

python - 无法在命令提示符下两次捕获KeyboardInterrupt?

C#:从超过 1 个类扩展

c# - 在 WPF 应用程序中全局设置文化 (en-IN)

html - 透明边框的CSS是什么?

PHP imagick 检测透明度

image - 如何在JavaCV中将png透明层更改为白色

c# - WinForms 中的 WPF 控件

linux - Git - 在 Linux 上使用 Linux 风格的行尾,在 Windows 上使用 Windows 风格的行尾