WPF 셸 통합 라이브러리를 사용하여 최대화할 경우 창이 화면 밖으로 이동합니다.
WPF Shell Integration Library를 사용하여 wpf 앱의 사용자 정의 크롬을 만들고 있습니다.모두 좋지만 앱을 최대화하면 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>
창의 크기가 최대화되면 일반적으로 크기 조정 가장자리가 모호해지도록 창의 가장자리를 잘라냅니다.창과 내용 사이에 프록시 테두리를 두른 다음 두께를 최대화하면 이 문제를 해결할 수 있습니다.
이를 위해 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 이상의 경우 시스템 매개 변수는 다음과 같이 약간 다릅니다.
<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>
이것은 나에게 효과가 있었습니다.
<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>
왜 이런 일이 생기는 건가요?
Raymond Chen은 노트에서 이를 설명했습니다. 왜 최대화된 창의 치수가 모니터보다 큰가요?:
화면에 걸려 있는 8개의 픽셀은 창 테두리입니다.창을 최대화하면 창 관리자는 창의 클라이언트 영역이 작업 영역의 너비를 채우고 캡션 표시줄이 작업 영역의 높이를 채우도록 항목을 정렬합니다.결국 문서를 최대한 많이 보려고 할 것이므로 아무런 도움이 되지 않는 창 테두리를 표시할 필요가 없습니다.(명백한 이유로 캡션 표시줄이 화면에 표시됩니다.)
어떻게 처리합니까?
@조 카스트로는 올바른 접근법을 제안했습니다.기본적으로 창이 최대화될 때마다 창 주위에 테두리를 추가하거나 여백을 지정해야 합니다.그리고.SystemParameters.WindowResizeBorderThickness
또한 올바른 재산이지만...그것은 버그가 있습니다.
나에게, 그것은 줍니다.4px
대신 경계8px
스케일% 디스플레이 스케일로 )Display Settings
및 ) 및략대및략3px
정확한 7px
175%로.
잘못된 속성이 아니라 버그라고 확신하는 이유는 무엇입니까?
으로 내적로으부▁internSystemParameters.WindowResizeBorderThickness
GetSystemMetrics 호출을 사용하여 테두리의 장치 픽셀을 가져옵니다.다음을 조회합니다.CXFRAME (32)
그리고.CYFRAME(33)
인덱스를 생성한 다음 논리 픽셀로 변환합니다.
이제 이 오래된 버그 보고서를 확인합니다.
다음 코드 행을 사용합니다.
int cx = ::GetSystemMetrics(SM_CXSIZEFRAME); int cy = ::GetSystemMetrics(SM_CYSIZEFRAME); int cp = ::GetSystemMetrics(SM_CYCAPTION);
Visual Studio 2010과 함께 컴파일하면 Windows 7 컴퓨터에서 cx == 9, cy == 9 및 cp == 27이 생성됩니다.
Vision Studio 2012 RC와 동일한 코드를 동일한 컴퓨터에서 컴파일하면 cx == 5, cy == 5 및 cp == 27이 생성됩니다.
그리고 그 대답은:
Microsoft에서 2012년 7월 12일 오전 11시 3분에 게시했습니다. 버그를 제출해 주셔서 감사합니다.보고하신 문제는 Windows 문제인 것 같습니다. 버그를 전달했습니다.
하지만 이 질문에서 몇 가지 좋은 소식이 있습니다. GetSystemMetrics()는 .NET 4.5 및 .NET 4.0에 대해 다른 결과를 반환합니다.
.NET 4.5 이상의 경우 다음을 추가할 수 있습니다.SM_CXPADDEDBORDER (92)
둘 다에게 가치가 있는CXFRAME (32)
그리고.CYFRAME(33)
정확한 값을 얻을 수 있습니다.
최종적인 해결책은 무엇입니까?
고정 속성과 함께 @Joe Castro 접근법을 사용합니다.
public static class SystemParametersFix
{
public static Thickness WindowResizeBorderThickness
{
get
{
float dpix = GetDpi(GetDeviceCapsIndex.LOGPIXELSX);
float dpiy = GetDpi(GetDeviceCapsIndex.LOGPIXELSY);
int dx = GetSystemMetrics(GetSystemMetricsIndex.CXFRAME);
int dy = GetSystemMetrics(GetSystemMetricsIndex.CYFRAME);
// this adjustment is needed only since .NET 4.5
int d = GetSystemMetrics(GetSystemMetricsIndex.SM_CXPADDEDBORDER);
dx += d;
dy += d;
var leftBorder = dx / dpix;
var topBorder = dy / dpiy;
return new Thickness(leftBorder, topBorder, leftBorder, topBorder);
}
}
[DllImport("user32.dll")]
private static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("gdi32.dll")]
private static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
private static float GetDpi(GetDeviceCapsIndex index)
{
IntPtr desktopWnd = IntPtr.Zero;
IntPtr dc = GetDC(desktopWnd);
float dpi;
try
{
dpi = GetDeviceCaps(dc, (int)index);
}
finally
{
ReleaseDC(desktopWnd, dc);
}
return dpi / 96f;
}
private enum GetDeviceCapsIndex
{
LOGPIXELSX = 88,
LOGPIXELSY = 90
}
[DllImport("user32.dll")]
private static extern int GetSystemMetrics(GetSystemMetricsIndex nIndex);
private enum GetSystemMetricsIndex
{
CXFRAME = 32,
CYFRAME = 33,
SM_CXPADDEDBORDER = 92
}
}
내 프로젝트에는 캡션이 있습니다.높이가 0으로 설정되고 크기 조정 모드가 캔 크기 조정으로 설정됨그립이랑.적당한 두께를 위해 생각해 낸 코드입니다.
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가 그랬던 것처럼 테두리를 사용한 다음 창 상태가 변경될 때 업데이트하는 속성에 두께를 바인딩합니다.
코드가 장난스러운 것 같지만 아직 다른 해결책을 찾지 못했습니다.
창이 화면 밖으로 나가는 문제를 해결하려면 다음을 설정합니다.
this.ResizeMode = System.Windows.ResizeMode.NoResize;
자세한 내용은 JAPF의 "WPF 프로젝트의 메인 창 설정" 게시물을 참조하십시오.
여기서부터, 저는 세팅을 해볼까 생각했습니다.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;
}
창의 기본 내용 주위에 테두리를 추가하고 View Model의 속성에 바인딩하여 문제를 해결할 수 있었습니다.사용자가 최대화 버튼을 누르면 경계를 설정하는 명령이 트리거됩니다.두께는 7.최대화 버튼을 다시 누르면 테두리두께가 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");
}
});
}
언급URL : https://stackoverflow.com/questions/2967218/window-out-of-the-screen-when-maximized-using-wpf-shell-integration-library
'programing' 카테고리의 다른 글
코드 파일 대 코드 이면 (0) | 2023.05.18 |
---|---|
날짜 시간.yyyy-dd-MM 형식의 날짜로 구문 분석을 시도합니다. (0) | 2023.05.18 |
파일에 쓰지만 파일이 있는 경우 덮어씁니다. (0) | 2023.05.18 |
엑셀에서 두 날짜 타임스탬프의 시간과 분의 차이를 얻는 방법은 무엇입니까? (0) | 2023.05.18 |
데이터베이스를 호출하는 방법 및 위치.작성 및 데이터베이스를 확인합니다.이주? (0) | 2023.05.18 |