WPF:使窗口不可调整,但保持框架?

我有一个没有标题栏的窗口WindowStyle == WindowStyle.None )。 整个窗口使用Aero玻璃效果。 当我使窗口不可调整( ResizeMode == ResizeMode.NoResize )时,玻璃效果消失,我的控件只能在半空中悬挂。 (本质上,窗口本身消失,但留下内容。)

有没有办法让窗户变得不可调整,而不是摆脱窗框?


我已经阅读了在无边框WPF窗口上启用Vista玻璃效果的问题,但这不是我想要的 – 我想保持窗口边框。 对于我希望我的窗口看起来像的例子,点击启用了Aero的Alt + Tab。


为了澄清, 我不想让鼠标hover在窗口边框上时显示resize的游标 。 这实际上是我希望我的窗口看起来像:

投影机http://img.zgserver.com/c%23/2mg4jty.png

解决scheme不一定是严格的WPF – 我很好,用Win32 API来实现这一点。

您可以挂接wndproc并拦截WM_WINDOWPOSCHANGING消息。 不是严格的WPF,但可能是你最好的选择。

如果你想隐藏调整大小的光标,那么你最好的选择就是拦截WM_NCHITTEST 。 调用DefWindowProc(获取默认行为),并测试返回值; 如果是HTBOTTOM,HTBOTTOMLEFT,HTBOTTOMRIGHT,HTTOP,HTTOPLEFT或HTTOPRIGHT,请将返回值更改为HTBORDER。

基于Erics的答案。

示例图像

 public partial class MainWindow : Window { [DllImport("DwmApi.dll")] public static extern int DwmExtendFrameIntoClientArea( IntPtr hwnd, ref MARGINS pMarInset); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern IntPtr DefWindowProc( IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam); private const int WM_NCHITTEST = 0x0084; private const int HTBORDER = 18; private const int HTBOTTOM = 15; private const int HTBOTTOMLEFT = 16; private const int HTBOTTOMRIGHT = 17; private const int HTLEFT = 10; private const int HTRIGHT = 11; private const int HTTOP = 12; private const int HTTOPLEFT = 13; private const int HTTOPRIGHT = 14; public MainWindow() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainWindow_Loaded); } void MainWindow_Loaded(object sender, RoutedEventArgs e) { try { // Obtain the window handle for WPF application IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle; HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr); mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0); mainWindowSrc.AddHook(WndProc); // Set Margins MARGINS margins = new MARGINS(); margins.cxLeftWidth = 10; margins.cxRightWidth = 10; margins.cyBottomHeight = 10; margins.cyTopHeight = 10; int hr = DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins); // if (hr < 0) { //DwmExtendFrameIntoClientArea Failed } } // If not Vista, paint background white. catch (DllNotFoundException) { Application.Current.MainWindow.Background = Brushes.White; } } private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { // Override the window hit test // and if the cursor is over a resize border, // return a standard border result instead. if (msg == WM_NCHITTEST) { handled = true; var htLocation = DefWindowProc(hwnd, msg, wParam, lParam).ToInt32(); switch (htLocation) { case HTBOTTOM: case HTBOTTOMLEFT: case HTBOTTOMRIGHT: case HTLEFT: case HTRIGHT: case HTTOP: case HTTOPLEFT: case HTTOPRIGHT: htLocation = HTBORDER; break; } return new IntPtr(htLocation); } return IntPtr.Zero; } private void Button_Click(object sender, RoutedEventArgs e) { this.Close(); } } [StructLayout(LayoutKind.Sequential)] public struct MARGINS { public int cxLeftWidth; // width of left border that retains its size public int cxRightWidth; // width of right border that retains its size public int cyTopHeight; // height of top border that retains its size public int cyBottomHeight; // height of bottom border that retains its size }; <Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="150" Width="200" Background="Transparent" WindowStyle="None" ResizeMode="CanResize" > <Grid Background="White" Margin="10,10,10,10"> <Button Content="Go Away" Click="Button_Click" Height="20" Width="100" /> </Grid> </Window> 

一个诡异的做法是设置MinWidth / MaxWidth和MinHeight / MaxHeight属性,使其不可调整。 当然,问题是你仍然会得到调整大小的游标越过边界。

为什么不为窗口创建窗口边框? 它使用偏移来设置窗口的颜色。 所以,一个简单的方法就是将整个边框包裹在窗口周围,然后获得自己的颜色!