internal static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, [In] ref MARGINS pMarInset);
private IntPtr HwndHook(IntPtr hWnd, int message, IntPtr wParam, IntPtr lParam, ref bool handled) { IntPtr returnval = IntPtr.Zero; switch (message) { case Constants.WM_NCCALCSIZE: /* Hides the border */ handled = true; break; case Constants.WM_NCPAINT: { if (!ShouldHaveBorder()) { var val = 2; UnsafeNativeMethods.DwmSetWindowAttribute(_mHWND, 2, ref val, 4); var m = new MARGINS { bottomHeight = 1, leftWidth = 1, rightWidth = 1, topHeight = 1 }; UnsafeNativeMethods.DwmExtendFrameIntoClientArea(_mHWND, ref m); //if (Border != null) // Border.BorderThickness = new Thickness(1); } else { //AddBorder(); } handled = true; } break; case Constants.WM_NCACTIVATE: { /* As per http://msdn.microsoft.com/en-us/library/ms632633(VS.85).aspx , "-1" lParam * "does not repaint the nonclient area to reflect the state change." */ returnval = UnsafeNativeMethods.DefWindowProc(hWnd, message, wParam, new IntPtr(-1)); //if (!ShouldHaveBorder()) // if (wParam == IntPtr.Zero) // AddBorder(); // else // RemoveBorder(); handled = true; } break; case Constants.WM_GETMINMAXINFO: /* http://blogs.msdn.com/b/llobo/archive/2006/08/01/maximizing-window-_2800_with-windowstyle_3d00_none_2900_-considering-taskbar.aspx */ WmGetMinMaxInfo(hWnd, lParam); /* Setting handled to false enables the application to process it's own Min/Max requirements, * as mentioned by jason.bullard (comment from September 22, 2011) on http://gallery.expression.microsoft.com/ZuneWindowBehavior/ */ handled = false; break; case Constants.WM_NCHITTEST: // don't process the message on windows that can't be resized var resizeMode = AssociatedObject.ResizeMode; if (resizeMode == ResizeMode.CanMinimize || resizeMode == ResizeMode.NoResize || AssociatedObject.WindowState == WindowState.Maximized) { break; } // get X & Y out of the message var screenPoint = new Point(UnsafeNativeMethods.GET_X_LPARAM(lParam), UnsafeNativeMethods.GET_Y_LPARAM(lParam)); // convert to window coordinates var windowPoint = AssociatedObject.PointFromScreen(screenPoint); var windowSize = AssociatedObject.RenderSize; var windowRect = new Rect(windowSize); windowRect.Inflate(-6, -6); // don't process the message if the mouse is outside the 6px resize border if (windowRect.Contains(windowPoint)) { break; } var windowHeight = (int)windowSize.Height; var windowWidth = (int)windowSize.Width; // create the rectangles where resize arrows are shown var topLeft = new Rect(0, 0, 6, 6); var top = new Rect(6, 0, windowWidth - 12, 6); var topRight = new Rect(windowWidth - 6, 0, 6, 6); var left = new Rect(0, 6, 6, windowHeight - 12); var right = new Rect(windowWidth - 6, 6, 6, windowHeight - 12); var bottomLeft = new Rect(0, windowHeight - 6, 6, 6); var bottom = new Rect(6, windowHeight - 6, windowWidth - 12, 6); var bottomRight = new Rect(windowWidth - 6, windowHeight - 6, 6, 6); // check if the mouse is within one of the rectangles if (topLeft.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTTOPLEFT; } else if (top.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTTOP; } else if (topRight.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTTOPRIGHT; } else if (left.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTLEFT; } else if (right.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTRIGHT; } else if (bottomLeft.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTBOTTOMLEFT; } else if (bottom.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTBOTTOM; } else if (bottomRight.Contains(windowPoint)) { returnval = (IntPtr)Constants.HTBOTTOMRIGHT; } if (returnval != IntPtr.Zero) { handled = true; } break; case Constants.WM_INITMENU: var window = AssociatedObject as SparrowWindow; if (window != null) { if (!window.ShowMaxRestoreButton) { UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_MAXIMIZE, Constants.MF_GRAYED | Constants.MF_BYCOMMAND); } else if (window.WindowState == WindowState.Maximized) { UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_MAXIMIZE, Constants.MF_GRAYED | Constants.MF_BYCOMMAND); UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_RESTORE, Constants.MF_ENABLED | Constants.MF_BYCOMMAND); UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_MOVE, Constants.MF_GRAYED | Constants.MF_BYCOMMAND); } else { UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_MAXIMIZE, Constants.MF_ENABLED | Constants.MF_BYCOMMAND); UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_RESTORE, Constants.MF_GRAYED | Constants.MF_BYCOMMAND); UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_MOVE, Constants.MF_ENABLED | Constants.MF_BYCOMMAND); } if (!window.ShowMinButton) { UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_MINIMIZE, Constants.MF_GRAYED | Constants.MF_BYCOMMAND); } if (AssociatedObject.ResizeMode == ResizeMode.NoResize || window.WindowState == WindowState.Maximized) { UnsafeNativeMethods.EnableMenuItem(UnsafeNativeMethods.GetSystemMenu(hWnd, false), Constants.SC_SIZE, Constants.MF_GRAYED | Constants.MF_BYCOMMAND); } } break; } return(returnval); }