diff --git a/WpfApp1/NativeMethods.cs b/WpfApp1/NativeMethods.cs index 927009c..ea7eafe 100644 --- a/WpfApp1/NativeMethods.cs +++ b/WpfApp1/NativeMethods.cs @@ -1,35 +1,61 @@ using System; using System.Runtime.InteropServices; -using System.Windows; -using System.Windows.Interop; namespace WpfApp1 { public static class NativeMethods { - [DllImport("user32.dll", EntryPoint = "SetWindowLong")] - public static extern int SetWindowLong32(HandleRef hWnd, WindowLongFlags nIndex, int dwNewLong); + public const int WM_NCCALCSIZE = 0x83; + public const int WM_NCPAINT = 0x85; - [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")] - public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, WindowLongFlags nIndex, IntPtr dwNewLong); + [DllImport("kernel32", SetLastError = true)] + private static extern IntPtr LoadLibrary(string lpFileName); - public static IntPtr SetWindowLongPtr(HandleRef hWnd, WindowLongFlags nIndex, IntPtr dwNewLong) + [DllImport("dwmapi.dll", PreserveSig = false)] + public static extern bool DwmIsCompositionEnabled(); + + [DllImport("kernel32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); + + [StructLayout(LayoutKind.Sequential)] + public struct MARGINS + { + public int leftWidth; + public int rightWidth; + public int topHeight; + public int bottomHeight; + } + + private delegate int DwmExtendFrameIntoClientAreaDelegate(IntPtr hwnd, ref MARGINS margins); + + public static int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins) { - return IntPtr.Size == 8 ? SetWindowLongPtr64(hWnd, nIndex, dwNewLong) : new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32())); + var hModule = LoadLibrary("dwmapi"); + + if (hModule == IntPtr.Zero) + { + return 0; + } + + var procAddress = GetProcAddress(hModule, "DwmExtendFrameIntoClientArea"); + + if (procAddress == IntPtr.Zero) + { + return 0; + } + + var delegateForFunctionPointer = (DwmExtendFrameIntoClientAreaDelegate)Marshal.GetDelegateForFunctionPointer(procAddress, typeof(DwmExtendFrameIntoClientAreaDelegate)); + + return delegateForFunctionPointer(hwnd, ref margins); } - public enum WindowLongFlags + public static bool IsDwmAvailable() { - GWL_EXSTYLE = -20, - GWLP_HINSTANCE = -6, - GWLP_HWNDPARENT = -8, - GWL_ID = -12, - GWL_STYLE = -16, - GWL_USERDATA = -21, - GWL_WNDPROC = -4, - DWLP_USER = 0x8, - DWLP_MSGRESULT = 0x0, - DWLP_DLGPROC = 0x4 + if (LoadLibrary("dwmapi") == IntPtr.Zero) + { + return false; + } + return true; } internal enum WVR diff --git a/WpfApp1/WindowChromeLoadedBehavior.cs b/WpfApp1/WindowChromeLoadedBehavior.cs index 40d70fb..394a5c8 100644 --- a/WpfApp1/WindowChromeLoadedBehavior.cs +++ b/WpfApp1/WindowChromeLoadedBehavior.cs @@ -11,6 +11,8 @@ namespace WpfApp1 { public class WindowChromeLoadedBehavior : Behavior { + private Window window; + protected override void OnAttached() { base.OnAttached(); @@ -25,7 +27,7 @@ protected override void OnDetaching() private void OnLoaded(object sender, RoutedEventArgs e) { - var window = Window.GetWindow(AssociatedObject); + window = Window.GetWindow(AssociatedObject); if (window == null) return; @@ -59,29 +61,50 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b { switch (msg) { - // WM_NCCALCSIZE - case 0x83: + case NativeMethods.WM_NCPAINT: + RemoveFrame(); + handled = false; + break; + + case NativeMethods.WM_NCCALCSIZE: + + handled = false; + var rcClientArea = (RECT)Marshal.PtrToStructure(lParam, typeof(RECT)); - rcClientArea.Bottom += (int)(WindowChromeHelper.WindowResizeBorderThickness.Bottom / 2); - Marshal.StructureToPtr(rcClientArea, lParam, false); - - handled = true; - + var retVal = IntPtr.Zero; - if (wParam == new IntPtr(1)) { retVal = new IntPtr((int)NativeMethods.WVR.REDRAW); } - return retVal; } return IntPtr.Zero; } + private void RemoveFrame() + { + if (Environment.OSVersion.Version.Major >= 6 && NativeMethods.IsDwmAvailable()) + { + if (NativeMethods.DwmIsCompositionEnabled() && SystemParameters.DropShadow) + { + NativeMethods.MARGINS margins; + + margins.bottomHeight = -1; + margins.leftWidth = 0; + margins.rightWidth = 0; + margins.topHeight = 0; + + var helper = new WindowInteropHelper(window); + + NativeMethods.DwmExtendFrameIntoClientArea(helper.Handle, ref margins); + } + } + } + [Serializable] [StructLayout(LayoutKind.Sequential)] public struct RECT