我正在使用WPF Shell Integration Library创建我的wpf应用的自定义chrome。 一切都很好,但是当最大化应用时,屏幕外有6或7个像素。
这是我正在使用的代码:
<Style TargetType="{x:Type local:MainWindow}">
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome
ResizeBorderThickness="6"
CaptionHeight="10"
CornerRadius="0"
GlassFrameThickness="1"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MainWindow}">
<Grid>
<Border BorderThickness="1" BorderBrush="#389FD1" Background="#389FD1">
<ContentPresenter Margin="0,22,0,0" Content="{TemplateBinding Content}"/>
</Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" >
<TextBlock Text="{Binding NombreUsuario}" Foreground="White" Margin="5,5,20,5" Opacity=".8" />
<Button Style="{StaticResource ImageButton}" Height="20" Width="20" Margin="0" Click="WindowMinimize" shell:WindowChrome.IsHitTestVisibleInChrome="True">
<Image Height="10" Width="10" Source="/Resources/Images/minimize.png" />
</Button>
<Button Style="{StaticResource ImageButton}" Height="20" Width="20" Margin="0" Click="WindowMaximizeRestore" shell:WindowChrome.IsHitTestVisibleInChrome="True" >
<Image Height="10" Width="10" Source="/Resources/Images/maximize.png" />
</Button>
<Button Style="{StaticResource ImageButton}" Height="20" Width="20" Margin="0" Click="WindowClose" shell:WindowChrome.IsHitTestVisibleInChrome="True">
<Image Height="10" Width="10" Source="/Resources/Images/close.png" />
</Button>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
答案 0 :(得分:46)
Windows最大化时会裁剪窗口边缘,以遮挡通常调整大小的边缘。您可以通过在窗口和内容之间放置代理边框来解决此问题,然后在最大化时增加厚度。
我修改了lib附带的示例来执行此操作,可以对您的示例进行相同的基本更改:
<ControlTemplate TargetType="{x:Type local:SelectableChromeWindow}">
<Border BorderBrush="Green">
<Border.Style>
<Style TargetType="{x:Type Border}">
<Setter Property="BorderThickness" Value="0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=ThisWindow, Path=WindowState}" Value="Maximized">
<Setter Property="BorderThickness" Value="{Binding Source={x:Static shell:SystemParameters2.Current}, Path=WindowResizeBorderThickness}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid [...]/>
</Border>
</ControlTemplate>
我希望有所帮助。
对于.net 4.5及以上版本, SystemParameters略有不同,例如:
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}, Path=WindowState}" Value="Maximized">
<Setter Property="BorderThickness" Value="{Binding Source={x:Static SystemParameters.WindowResizeBorderThickness}}"/>
</DataTrigger>
答案 1 :(得分:7)
这对我有用:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Microsoft.Windows.Shell"
xmlns:Views="clr-namespace:BorderLessWpf.Views">
<Style TargetType="{x:Type Views:ShellView}" >
<Setter Property="shell:WindowChrome.WindowChrome">
<Setter.Value>
<shell:WindowChrome
ResizeBorderThickness="6"
CaptionHeight="10"
CornerRadius="0"
GlassFrameThickness="1"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="WindowState" Value="Maximized">
<Setter Property="BorderThickness" Value="6" />
</Trigger>
</Style.Triggers>
</Style>
答案 2 :(得分:2)
要解决窗口离开屏幕的问题,只需设置:
this.ResizeMode = System.Windows.ResizeMode.NoResize;
参见JAPF's "Set up the main window of your WPF project" post 了解更多信息。
答案 3 :(得分:2)
在我的项目中,我将CaptionHeight设置为0,将ResizeMode设置为CanResizeWithGrip。这是我提出的适当厚度的代码。
Thickness maximizeFix = new Thickness(SystemParameters.WindowNonClientFrameThickness.Left +
SystemParameters.WindowResizeBorderThickness.Left,
SystemParameters.WindowNonClientFrameThickness.Top +
SystemParameters.WindowResizeBorderThickness.Top
- SystemParameters.CaptionHeight,
SystemParameters.WindowNonClientFrameThickness.Right +
SystemParameters.WindowResizeBorderThickness.Right,
SystemParameters.WindowNonClientFrameThickness.Bottom +
SystemParameters.WindowResizeBorderThickness.Bottom);
我将使用像Joe Castro那样的边框,然后将厚度绑定到我在窗口状态发生变化时更新的属性。
代码似乎很笨拙,但我还没有找到另一种解决方案。
答案 4 :(得分:2)
Raymond Chen在他的笔记Why are the dimensions of a maximized window larger than the monitor?中对此进行了解释:
挂在屏幕上的多余八个像素是窗口 边界。当您最大化窗口时,窗口管理器会安排 东西,以便窗口的客户区填充您的宽度 工作区,它加上标题栏填充了工作区的高度 区。毕竟,您希望看到尽可能多的文档。 无需向您显示不适合您的窗口边框 任何好处。 (它将标题栏留在屏幕上 原因。)
@Joe Castro提出了正确的方法。基本上,每次最大化时,您都必须在窗口周围添加边框(或指定边距)。并且SystemParameters.WindowResizeBorderThickness
也是正确的属性,但是... 它有一个错误。
对我来说,它会为{%{1}}而不是正确的4px
边框(100%的显示比例(可以在8px
中进行更改)和大约Display Settings
而不是正确的{{ 1}}代表175%。
内部3px
使用GetSystemMetrics调用来获取边框的设备像素。它查询7px
和SystemParameters.WindowResizeBorderThickness
索引,然后将其转换为逻辑像素。
现在检查此old bug report:
采用以下代码行:
CXFRAME (32)
使用Visual Studio 2010编译时,在我的Windows7计算机上, 产生:cx == 9,cy == 9和cp == 27。
如果我使用Vision Studio 2012 RC在相同的代码上编译完全相同的代码 机器,结果是:cx == 5,cy == 5和cp == 27。
答案:
Microsoft于2012年7月12日上午11:03发布 感谢您提交错误。您报告的问题似乎是Windows问题,并且 我们已将错误转发给他们。
但是这个问题有一些好消息:GetSystemMetrics() returns different results for .NET 4.5 & .NET 4.0
对于.NET 4.5和更高版本,您只需将CYFRAME(33)
值添加到 int cx = ::GetSystemMetrics(SM_CXSIZEFRAME);
int cy = ::GetSystemMetrics(SM_CYSIZEFRAME);
int cp = ::GetSystemMetrics(SM_CYCAPTION);
和SM_CXPADDEDBORDER (92)
即可获得正确的值。
使用@Joe Castro方法,但具有固定属性:
CXFRAME (32)
答案 5 :(得分:1)
从here开始,我想我会尝试设置WindowChrome.NonClientFrameEdges
。
通过一些实验,结果证明,您可以通过在最大化时将其设置为NonClientFrameEdges.Bottom
并在未最大化时将其设置为NonClientFrameEdges.None
来获得所需效果。
这使得边距除了底部之外的所有边都消失,但关键是导致任务栏下的重叠不再发生。
将WindowChrome设置为之前到WindowState是很重要的,所以在我的代码隐藏中我有函数(MainGrid2保存禁止状态栏的所有窗口内容,并且StatusGrid保持状态巴):
private void Maximise()
{
StatusGrid.Margin = new Thickness(7, 0, 7, 0);
MainGrid2.Margin = new Thickness(12, 12, 12, 0);
chrome.NonClientFrameEdges = NonClientFrameEdges.Bottom;
WindowChrome.SetWindowChrome(this, chrome);
WindowState = System.Windows.WindowState.Maximized;
}
private void Restore()
{
StatusGrid.Margin = new Thickness(0);
MainGrid2.Margin = new Thickness(5, 5, 5, 0);
chrome.NonClientFrameEdges = NonClientFrameEdges.None;
WindowChrome.SetWindowChrome(this, chrome);
WindowState = System.Windows.WindowState.Normal;
}
答案 6 :(得分:0)
我设法通过在窗口的主要内容周围添加边框并将其绑定到ViewModel中的属性来解决该问题。当用户按下最大化按钮时,将触发一个命令,该命令将BorderThickness设置为7。再次按下最大化按钮时,BorderThickness被设置为0。
<!-- Content of my window -->
<Border BorderThickness="{Binding BorderThickness}" BorderBrush="{StaticResource OffsetBlackBrush}">
<Grid>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<Button Content="-" Command="{Binding MinimizeCommand}" Style="{StaticResource WindowControlButton}" />
<Button Content="[ ]" Command="{Binding MaximizeCommand}" Style="{StaticResource WindowControlButton}" />
<Button Content="X" Command="{Binding CloseCommand}" Style="{StaticResource WindowCloseButton}" />
</StackPanel>
</Grid>
</Border>
<!-- BorderThickness property in VM -->
public int BorderThickness { get; set; } = 0;
/// <summary>
/// Maximizes the current window
/// </summary>
public RelayCommand MaximizeCommand
{
get => new RelayCommand(param =>
{
if (!_view.GetWindowState())
{
BorderThickness = 7;
_view.SetWindowState("Maximize"); // Change window state to maximized using interface passed into ctor
}
else
{
BorderThickness = 0;
_view.SetWindowState("Normal");
}
});
}