У меня есть окно, которое не имеет строки заголовка (WindowStyle == WindowStyle.None
). Все окно использует Аэро стеклянный эффект. Когда я делаю окно неизменяемого размера (ResizeMode == ResizeMode.NoResize
), стеклянный эффект исчезает, и мои средства управления просто зависают в воздушном пространстве. (По существу само окно исчезает, но оставляет свое содержание.)
Существует ли способ для меня сделать окно неизменяемого размера, не избавляясь от рамки окна?
Я читал, вопрос Включают эффект стекла Vista на безграничное окно WPF, но это не совсем, что я хочу - я хотел бы сохранить границу окна. Для примера того, на что я хотел бы, чтобы мое окно было похоже, совершите нападки, Alt+Tab с Аэро включил.
Для разъяснения я делаю не хотят, чтобы изменить размер курсоры обнаружились вообще при парении над границей окна. Это по существу, на что я хочу, чтобы мое окно было похоже:
Решением не должен быть строго WPF - хорошо с бездельничанием с API Win32 для достижения этого.
Вы можете подключить wndproc и перехватить сообщение WM_WINDOWPOSCHANGING. Это не совсем WPF, но, вероятно, лучший вариант.
Если вы хотите скрыть курсоры изменения размера, то лучшим вариантом будет перехват WM_NCHITTEST. Вызовите DefWindowProc (чтобы получить поведение по умолчанию) и проверьте возвращаемое значение; если это HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTTOP, HTTOPLEFT или HTTOPRIGHT, измените возвращаемое значение на HTBORDER.
Почему бы вам просто не создать эту границу окна для окна? Он использует смещение для установки цветов окна. Итак, простой способ - просто обернуть окно рамкой и, кроме того, получить свои собственные цвета!
Один из хакерских способов сделать это - установить свойства MinWidth / MaxWidth и MinHeight / MaxHeight, чтобы сделать его безразмерным. Конечно, проблема в том, что курсоры изменения размера все равно выходят за границы.
На основе ответа Эрика.
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>