2011-08-03 15 views
10

Rozumiem, że współrzędne WPF różnią się od "rzeczywistych" współrzędnych ekranu (współrzędne pikseli), jeśli komputer nie korzysta z domyślnego ustawienia DPI. W moim programie chcę (1) dowiedzieć się, który monitor działa w oknie WPF i (2) otworzyć kolejne okno w lewym dolnym rogu tego samego monitora. Słyszałem, że ma odpowiednika Screen dla WPF więc używam wersji WinForm, w następujący sposób, który działa dobrze na domyślne 96 DPI:WPF: Konwersja współrzędnych ekranu i współrzędnych WPF

public void ChooseInitialPosition(Window w) // w is some other window 
{ 
    var scr = System.Windows.Forms.Screen.FromRectangle(
      new System.Drawing.Rectangle((int)w.Left, (int)w.Top, (int)w.Width, (int)w.Height)) 
      .WorkingArea; 

    this.Left = scr.Right - Width; 
    this.Top = scr.Bottom - Height; 
} 

Ale w drugiej DPI, oba etapy działać nieprawidłowo, a może umieścić okno całkowicie poza ekranem.

tej pory, wygląda na to mogę używać Visual.PointToScreen do pierwszej części:

var p1 = w.PointToScreen(new Point(0,0)); 
var p2 = w.PointToScreen(new Point(w.Width,w.Height)); 
var scr = System.Windows.Forms.Screen.FromRectangle(
    new System.Drawing.Rectangle((int)p1.X, (int)p1.Y, (int)(p2.X - p1.X), (int)(p2.Y - p1.Y))).WorkingArea; 

Nie jestem pewien, czy to ma rację, ponieważ nie może odpowiadać za granicami poprawnie. Ale druga część jest ważniejsza. Jak przekonwertować prostokąt ekranu "scr" na przestrzeń WPF, aby poprawnie ustawić Left i Top?

+2

Nie na pewno o obsłudze wielu monitorów, ale możesz poprawnie ustawić okno o n podstawowy ekran korzystający tylko z WPF (który jest świadomy DPI) bez żadnych odniesień do Windows Forms (który nie jest świadomy DPI) przy użyciu klasy SystemParameters. Odpowiednie właściwości automatycznie dostosowują się do różnych ustawień DPI. Przykład: window.Top = SystemParameters.FullPrimaryScreenHeight - (window.ActualHeight - SystemParameters.WindowCaptionHeight); // Działa na Vista i Windows 7, nie wiem o XP. –

Odpowiedz

25
  1. który ekran okno WPF jest:

    private static Screen GetScreen(Window window) 
    { 
        return Screen.FromHandle(new WindowInteropHelper(window).Handle); 
    } 
    
  2. otworzyć kolejne okno w lewym dolnym rogu tego samego ekranu:

    static Point RealPixelsToWpf(Window w, Point p) 
    { 
        var t = PresentationSource.FromVisual(w).CompositionTarget.TransformFromDevice; 
        return t.Transform(p); 
    } 
    private static void SetPositionBottomLeftCorner(Window sourceWindow, Window targetWindow) 
    { 
        var workingArea = GetScreen(sourceWindow).WorkingArea; 
        var corner = RealPixelsToWpf(sourceWindow, new Point(workingArea.Left, workingArea.Bottom)); 
        targetWindow.Left = corner.X; 
        targetWindow.Top = corner.Y - targetWindow.ActualHeight; 
    } 
    
+2

Dodano metodę pomocniczą RealPixelsToWpf(). – Qwertie

2

Czy to działa, jeśli umieścisz go w kodzie z tyłu okna?

protected override void OnContentRendered(System.EventArgs e) 
{ 
    base.OnContentRendered(e); 
    MoveToLowerRightCorner(); 
} 

private void MoveToLowerRightCorner() 
{ 
    var workingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea; 
    var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice; 
    var corner = transform.Transform(new Point(workingArea.Right, workingArea.Bottom)); 
    this.Left = corner.X - this.ActualWidth; 
    this.Top = corner.Y - this.ActualHeight; 
} 
Powiązane problemy