Ich arbeite derzeit an einigen hohen DPI-Probleme in unserer WPF-App (.NET 4.6.1 - System DPI-Bewusstsein ist aktiv).HorizontalOffset geht in die falsche Richtung für High DPI primären Bildschirm
Im Allgemeinen macht die App das, was wir erwarten - skalieren Sie abhängig von der aktuellen DPI-Einstellung, auch wenn Sie von Bildschirm A @ 100% auf Bildschirm B @ 150% bewegt wird, ändert sich die Gesamtskalierung korrekt "zur Hälfte -Punkt".
Die meisten der offenen Probleme waren dort, weil wir einige Pixel-/DIP-basierte Berechnungen hatten, die die DPI-Einstellung nicht berücksichtigten. Das habe ich festgelegt, indem sie in den richtigen DPI-Werte Berechnung:
var source = PresentationSource.FromVisual(this);
var dpiX = source?.CompositionTarget?.TransformToDevice.M11 ?? 1;
var dpiY = source?.CompositionTarget?.TransformToDevice.M22 ?? 1;
Dort fand ich die erste Merkwürdige aus (zumindest für mich):
- Wenn die primäre Anzeige eingestellt ist z.B. 125% bekomme ich 1,25 für
dpiX
für alle Bildschirme, sogar den sekundären Bildschirm @ 100%, aber dort sind alle Pixelwerte bereits mit 1,25 multipliziert (was bedeutet, dass ein 1600x1200 Pixel Bildschirm eine Arbeitsgröße von 2000x1500 hat). - Und es ist genau umgekehrt, wenn der primäre Bildschirm bei 100% ist und der sekundäre Bildschirm bei z. 150%: Ich bekomme immer 1 für
dpiX
, aber alle Werte sind bereits richtig und es ist keine Korrektur notwendig (=> oder multiplizieren/dividieren mit 1 bricht es nicht).
Aber nun zu meinem eigentlichen Problem:
Ich habe einige Popups ich mit der folgenden Bindung in der Mitte ihrer Platzierung Ziele am Abdrucken:
<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>
und Konverter:
Für den Fall 2 funktioniert alles schon ohne den auskommentierten Code, aber für den Fall 1 habe ich versucht, den DPI-Wert zu teilen und zu multiplizieren, aber am Ende war das Richtige zu mult iply es von -1
, damit es richtig funktioniert.
Warum ist das der Fall?
Und wie kann ich sicher feststellen, wenn dies benötigt wird? dpiX > 1
?
Ich bin auch offen für andere Lösungen für die Skalierung oder die Center-Platzierung als Ganzes.
P.S .: Ich habe Windows 10 1703 mit .NET 4.7 installiert (App zielt aus anderen Gründen immer noch auf 4.6.1).
UPDATE:
ich eine Demo-Lösung erstellt: https://github.com/chrfin/HorizontalOffsetError
Wenn der Hauptbildschirm bei 100% ist, ist es richtig:
aber wenn der Hauptbildschirm zum Beispiel ist 125% ist es aus:
aber wenn ich als ein * -1 bis der Offset es wieder korrekt ist:
... aber warum?
Warum brauchen Sie mit dpi umgehen, wenn die Positionierung? Messen Sie die tatsächliche Größe (nicht skalieren) und positionieren Sie sie. – Sinatr
@Sinatr: Weil es in Fall 1 nicht funktioniert ;-). Die Pop-ups werden in diesem Fall auf die falsche Seite verschoben. Beispiel: Ziel ist 130 Pixel breit, Popup ist 230 Pixel -> Offset = -50 Pixel => in Fall 2 Einstellung der horizontalen Offset zu -50 platziert das Pop-up in der Mitte des Ziels, aber für Fall 1 ist es dann 100 Pixel aus anstatt 0 oder 50px, ABER das Offset auf +50 setzt das Pop-up korrekt und ich weiß nicht warum oder wie zu erkennen wann + und wann -.... – ChrFin
@HansPassant: Danke für deine Eingabe, aber ich denke ich war mit diesem Teil nicht klar - das Problem tritt auch auf, wenn es nur einen Bildschirm mit zB gibt 150% oder das Fenster wird nicht bewegt. Sobald der primäre (oder einzige) Bildschirm nicht auf 100% steht, scheint das Problem aufzutreten. Ich werde versuchen, morgen eine kleine Demo-Lösung zu machen ... – ChrFin