2011-12-20 2 views
4

У меня есть приложение WPF (.NET Framework 4) с пользовательской границей окна. Я отключил стеклянную границу, используя WPF Shell Integration Library, и нарисую собственную границу. Однако я хочу добавить DropShadow вокруг границы окна, когда он не максимизирован. Я добавил тень, как это:Удалить DropShadow для максимального пользовательского окна WPF

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 enter image description here

Есть что-то, что мне не хватает? Я читал через DWM Function library, но не могу найти ответ ...

+1

Это может принести пользу вам для использования [Snoop] (http://snoopwpf.codeplex.com/) здесь - это действительно хороший инструмент для шпиона WPF, который позволяет вам видеть все различные отображаемые слои вашего приложения WPF, а также текущие значения свойств. –

+0

Ничего не пришло, когда Snooping мое приложение, оба экземпляра точно такие же! Это где-то в winapi, что все пошло не так, я просто не знаю, почему ... поскольку я отключу политику рендеринга красиво, когда приложение максимизируется! – Kolky

ответ

2

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

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); 
    } 
}