Удалить DropShadow для развернутого пользовательского окна WPF - PullRequest
4 голосов
/ 20 декабря 2011

У меня есть приложение 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 для окна WPF без полей

Это решение отлично работает при работе с WindowState.Normal!Однако, когда я развернул приложение и отключил DWMWA_NCRENDERING_POLICY, фон окна становится слегка прозрачным, и большинство моих элементов управления отображаются совершенно иначе, чем я привык.

На следующем рисунке вы видите развернутое состояниекак было изначально, так и с теневым кодом.Как вы можете видеть, это полностью меняет прозрачность окна с помощью теневого кода: o enter image description here

Что-то мне не хватает?Я читал библиотеку функций DWM , но не могу найти ответ ...

1 Ответ

2 голосов
/ 30 января 2012

Через некоторое время я вернулся к проблеме под другим углом и нашел лучшее решение:

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, 2, 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);
    }
}
...