Максимальное пользовательское окно теряет эффект тени
У меня есть пользовательское окно WPF, определяемое как:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" MinHeight="300" Height="350" MinWidth="600" Width="700" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" WindowStyle="None">
Я нашел класс онлайн, который создает тени для теней, как показано ниже. Это работает хорошо, даже с уменьшением размера, пока я не получу максимальное окно. Как только я увеличиваю окно или изменяю состояние окна другого окна (например, Visual Studio), я теряю тень и я не могу ее вернуть. Любые идеи?
Класс тени:
Public Class DropShadow
Private Shared _handler As EventHandler = New EventHandler(AddressOf window_SourceInitialized)
<DllImport("dwmapi.dll", PreserveSig:=True)> _
Private Shared Function DwmSetWindowAttribute(hwnd As IntPtr, attr As Integer, ByRef attrValue As Integer, attrSize As Integer) As Integer
End Function
<DllImport("dwmapi.dll")> _
Private Shared Function DwmExtendFrameIntoClientArea(hWnd As IntPtr, ByRef pMarInset As Margins) As Integer
End Function
Public Shared Sub DropShadowToWindow(window As Window)
If Not DropShadow(window) Then
AddHandler window.SourceInitialized, _handler
AddHandler window.SizeChanged, New SizeChangedEventHandler(AddressOf windowSizeChanged)
End If
End Sub
Private Shared Sub window_SourceInitialized(sender As Object, e As EventArgs)
Dim window As Window = DirectCast(sender, Window)
DropShadow(window)
RemoveHandler window.SourceInitialized, _handler
End Sub
Private Shared Function DropShadow(window As Window) As Boolean
Try
Dim helper As New WindowInteropHelper(window)
Dim val As Integer = 2
Dim ret1 As Integer = DwmSetWindowAttribute(helper.Handle, 2, val, 4)
If ret1 = 0 Then
Dim m As New Margins() With { _
.Bottom = 0, _
.Left = 0, _
.Right = 0, _
.Top = 0 _
}
Dim ret2 As Integer = DwmExtendFrameIntoClientArea(helper.Handle, m)
Return ret2 = 0
Else
Return False
End If
Catch ex As Exception
' Probably dwmapi.dll not found (incompatible OS)
Return False
End Try
End Function
Private Shared Sub windowSizeChanged(sender As Object, e As SizeChangedEventArgs)
Dim window As Window = DirectCast(sender, Window)
DropShadow(window)
End Sub
End Class
Ответы
Ответ 1
Чтобы создать эффект тени, имея возможность изменить размер формы, попробуйте следующее:
-
Задайте в окне следующие свойства:
- ResizeMode = "CanResizeWithGrip"
- AllowsTransparency = "True"
- WindowStyle = "None"
- Фон = "Прозрачный"
- BorderThickness = "3"
-
После объявления окна добавьте элемент Border
- Создайте элемент
Border.Effect
внутри рамки
-
Для эффекта границы добавьте следующее:
<DropShadowEffect BlurRadius="5" Color="Black" Opacity="0.8" ShadowDepth="0.5" />
Это создаст следующее (без панели управления в правом верхнем углу):
![enter image description here]()
Полный XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" MinHeight="500" Height="350" MinWidth="300" Width="700" ResizeMode="CanResizeWithGrip" AllowsTransparency="True" WindowStyle="None" Background="White" BorderThickness="3">
<Border>
<Border.Effect>
<DropShadowEffect BlurRadius="5" Color="Black" Opacity="0.8" ShadowDepth="0.5" />
</Border.Effect>
<!-- Put your content in here -->
</Border>
</Window>
Ответ 2
Итак, я нашел способ заставить это работать.
Вам нужно использовать библиотеку интеграции WPF Shell (здесь), чтобы выполнить эту работу за вас. Как написано MS, они исправили (по-видимому) любые проблемы с выполнением кода P/Invoke.
Таким образом, легко получить окно, которое не имеет стекла Aero, изменяет размер по краям, имеет область заголовка, которая ведет себя с привязкой Aero, и имеет тень, которая появляется снова после min/maxing.
Это код для моего окна (обратите внимание, что вам нужно указать Microsoft.Windows.Shell
)
<Window x:Class="MyLibrary.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="http://schemas.microsoft.com/winfx/2006/xaml/presentation/shell"
Title="MainWindow"
WindowStyle="SingleBorderWindow"
ResizeMode="CanResizeWithGrip"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="449"
d:DesignWidth="677"
Foreground="White"
Background="Black">
<shell:WindowChrome.WindowChrome>
<shell:WindowChrome CaptionHeight="35"
GlassFrameThickness="0,0,0,1"
ResizeBorderThickness="5" />
</shell:WindowChrome.WindowChrome>
<Grid x:Name="LayoutRoot">
</gGrid>
</Window>
<shell:WindowChrome>
- это место, где вы устанавливаете все переменные для взаимодействия.
-
CaptionHeight
: Это высота области заголовка (заголовок), которая позволяет использовать Aero, двойное нажатие, как обычно, в строке заголовка.
-
GlassFrameThickness
: установка этого параметра на 0,0,0,1
по какой-то причине удаляет хром (стекло), сохраняет квадратную рамку и добавляет тени.
-
ResizeBorderThickness
: Это толщина на краю окна, где вы можете изменить размер окна.
Другие вещи, которые следует учитывать, поскольку вы сохраняете свойство Window.WindowStyle равным SingleBorderWindow
и разрешаете библиотеке Shell удалять заголовок, кнопки и другие хром.
Итак, я как бы потратил впустую свою щедрость, но это похоже на вполне жизнеспособное решение, которое работает!
EDIT:
Вот изображение результата: ![Sample Metro WPF Application]()
Я также предложил пример проекта http://code.google.com/p/sample-metro-wpf-application/. Это лицензия MIT, и люди могут ее использовать, но они хотят.
Ответ 3
Вот немного минимального кода, который делает то, что вам нужно.
<Window x:Class="WindowChromeSpike.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="0,0,0,1" CornerRadius="0" />
</WindowChrome.WindowChrome>
<!-- window contents: just a blue rectangle for demo purposes -->
<Border Background="#0093C0" />
</Window>
Это окно ведет себя как обычное окно, в котором оно может быть:
- изменено по краям
- перетаскивается в область заголовка
- щелкните правой кнопкой мыши область заголовка, чтобы отобразить системное меню
- максимизируется/восстанавливается двойным щелчком по области заголовка
- привязаны к сторонам экрана, перетаскивая или используя горячие клавиши (Win 10)
У него также есть тень.
Конечный результат выглядит следующим образом:
![введите описание изображения здесь]()