问题描述
我有一个WPF窗口,且WindowStyle设置为none.有什么方法可以强制此窗口添加阴影(就像WindowStyle不为none时所获得的阴影一样)?我不想将AllowTransparency设置为true,因为它会影响性能.而且我也不想禁用硬件渲染(我读过某个地方,禁用它会提高透明度.)
I have a WPF Window with WindowStyle set to none. Is there some way I can force this window to drop a shadow (like the one you get when WindowStyle is not none)? I don't want to set AllowTransparency to true, because it affects the performance. And I also don't want to disable hardware rendering (I read somewhere that transparency performs better with it disabled).
推荐答案
我编写了一个实用工具类,它能够完全满足您的要求:在无边界的Window
上放置标准阴影,但设置了AllowsTransparency
到false
.
I have written a little utility class that is able to do exactly what you want: drop a standard shadow over a borderless Window
but having AllowsTransparency
set to false
.
您只需要调用DropShadowToWindow(Window window)
方法.最好在窗口的构造函数InitializeComponent()
之后进行此调用,但是即使在显示窗口之后调用它也可以工作.
You just have to call the DropShadowToWindow(Window window)
method. It is preferred that you make this call just after the window's constructor's InitializeComponent()
, but it will work even if you call it after the window is shown.
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无边界窗口的DropShadow的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!