현재 WPF 앱의 일부 높은 DPI 문제 (.NET 4.6.1 - 시스템 DPI 인식이 활성화 됨)에서 작업 중입니다.HorizontalOffset이 높은 DPI 기본 화면에 대해 잘못된 방향으로 이동합니다.
일반적으로 응용 프로그램은 현재 디스플레이 DPI 설정에 따라, 또한 화면 A @ 100 %에서 화면 B @ 150 %로 이동하면 전체 배율이 올바르게 변경됩니다. " -포인트".
대부분의 공개 문제는 DPI 설정을 고려하지 않은 픽셀 -/DIP 기반 계산이 있었기 때문에 발생했습니다. 이 나는 올바른 DPI 값으로 계산하여 고정 : 나는 (적어도 나에게) 처음 이상한 것은 발견이
var source = PresentationSource.FromVisual(this);
var dpiX = source?.CompositionTarget?.TransformToDevice.M11 ?? 1;
var dpiY = source?.CompositionTarget?.TransformToDevice.M22 ?? 1;
: 기본 디스플레이로 설정하면
- 를 예를 들면, 125 % 모든 화면에 대해
dpiX
의 경우 1.25, 보조 화면의 경우 @ 100 %이지만 모든 픽셀 값에 이미 1.25가 곱해졌습니다 (즉, 1600x1200 픽셀 화면의 작업 크기는 2000x1500입니다). - 주 화면이 100 %이고 보조 화면이 예를 들어 100 % 인 경우 정확히 다른 방법입니다. 150 % : 나는 항상
dpiX
에 대해 1을 얻지 만, 모든 값은 이미 정확하고 보정이 필요하지 않습니다 (=> 곱하기/나누기가 1이면 깨지 않습니다).
하지만 지금 내 실제 문제 :
<Popup.HorizontalOffset>
<MultiBinding Converter="{lth:CenterConverter}">
<Binding RelativeSource="{RelativeSource Self}" Path="PlacementTarget.ActualWidth" />
<Binding RelativeSource="{RelativeSource Self}" Path="Child.ActualWidth" />
<Binding RelativeSource="{RelativeSource Self}" Path="." />
</MultiBinding>
</Popup.HorizontalOffset>
컨버터 :
좀 다음 바인딩에 내가 그들의 게재 위치 목표의 중심에 배치하고 팝업이
public class CenterConverter : MarkupExtension, IMultiValueConverter
{
public override object ProvideValue(IServiceProvider serviceProvider) => this;
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values.Any(v => v == DependencyProperty.UnsetValue))
return Double.NaN;
double placementTargetWidth = (double)values[0];
double elementWidth = (double)values[1];
var offset = (placementTargetWidth - elementWidth)/2;
////if (values.Length >= 3 && values[2] is Visual)
////{
//// var source = PresentationSource.FromVisual((Visual)values[2]);
//// var dpiX = source?.CompositionTarget?.TransformToDevice.M11 ?? 1;
//// offset *= -1; //dpiX;
////}
return offset;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); }
}
사례 2의 경우 모두 주석 처리 된 코드없이 올바르게 작동하지만 사례 1의 경우 DPI 값을 나누고 곱하려고 시도하지만 결국에는 올바른 것이 멀티가됩니다. 그것을 제대로 작동 시키려면 -1
으로 iply하십시오.
왜 그런 경우가 아닙니까?
그리고 이것이 필요할 때 어떻게 적절하게 감지 할 수 있습니까? dpiX > 1
?
스케일링 문제 나 센터 배치와 관련하여 다른 솔루션에 대해서도 열려 있습니다.
피씨 : .NET 4.7이 설치된 Windows 10 1703을 실행 중입니다 (다른 이유로 인해 앱은 여전히 4.6.1을 대상으로합니다).
UPDATE :
하지만 기본 화면 예컨대 인 경우 메인 화면이 올바른지 100 % 인 경우 https://github.com/chrfin/HorizontalOffsetError
: I는 데모 용액을 만든
하지만보다하다면 * 추가 -1이 다시 올 오프셋에 : 125 %는이 꺼져
... 그런데 왜?
왜 위치 할 때 dpi로 처리해야합니까? 실제 크기를 측정하고 (크기를 조정하지 마십시오) 위치를 지정하십시오. – Sinatr
@Sinatr : 케이스 1에서 작동하지 않기 때문에 ;-). 이 경우 팝업이 잘못된 쪽으로 이동합니다. 예 : 타겟 크기가 130px이고 팝업 크기가 230px -> offset = -50px => 경우 2의 경우 수평 오프셋을 -50으로 설정하면 대상의 중앙에 팝업이 표시되지만 사례 1의 경우에는 100px가됩니다 0 또는 50 픽셀 대신 오프셋을 +50으로 설정하면 팝업이 올바르게 표시되고 + 및 언제 또는 언제 어떻게 감지하는지 알 수 없습니다. – ChrFin
@HansPassant : 입력 해 주셔서 감사합니다.하지만 내가 그 부분으로는 분명하지 않다고 생각합니다. 예를 들어 단 하나의 화면 만 있다면 문제가 발생합니다. 150 % 또는 창 이동되지 않습니다. 기본 (또는 유일한) 화면이 100 %가 아닌 즉시 문제가 발생합니다. 내일 작은 데모 솔루션을 만들려고 노력할 것입니다 ... – ChrFin