Wrong coordinates on multiple monitors
Asked Answered
W

3

7

I have a Datagrid and I want to know the position of a datacell for overlaying it with a window.
It works fine with only one monitor, but with multiple monitors, the window is displaced.
Here's the code:

Point point = cell.PointToScreen(new Point(0, 0));
...
Window myWindow = new Window();
myWindow.Top = point.Y;
myWindow.Left = point.X;

Somebody has some experience with positioning on multiple monitors?

EDIT:
I made following test:

public MyWindow()
{
    ...
    this.LocationChanged += MyWindow_LocationChanged;
}

void MyWindow_LocationChanged(object sender, EventArgs e)
{
    Console.WriteLine(this.Top + " <--> " + this.PointToScreen(new Point(0, 0)).Y);
}

Results:
- Single-Monitor: 0 <--> 30; 20 <--> 50; 100 <--> 130
==> Always difference of 30 (may be caused by title bar)
- Dual-Monitor: 0 <--> 30; 20 <--> 55; 100 <--> 153
==> At 0,0 difference of 30. But the more I moved the window away from 0,0. the greater becomes the difference, but should stay the same. Very strange!

EDIT2:
Here's my solution, thanks to CodeNaked for the hint:

Point point = cell.PointToScreen(new Point(0, 0));
...
Window myWindow = new Window();
PresentationSource source = PresentationSource.FromVisual(this);
myWindow.Top = point.Y / source.CompositionTarget.TransformToDevice.M22;
myWindow.Left = point.X / source.CompositionTarget.TransformToDevice.M11;
Wickham answered 17/5, 2011 at 11:59 Comment(5)
Please post the values you get and the values you expect.Prescription
I don't know what I have to except. The PointToScreen and the point of the window are the same, so the error is already in the PointToScreen-Method.Wickham
Added some test-results to question.Wickham
I see no problem. As you move the window, the element at the position (0,0) in the window changes its absolute coordinates...Prescription
No, both values are the top-left-corner of the window, and of course it changes on moving, but PointToScreen changes faster than this.Top (see edited example). That can't be correct.Wickham
H
6

This may have to do with a non-standard DPI setting, but I'm pretty sure that setting affects all monitors. This blog shows how to get the correct position. But the code is effectively:

PresentationSource source = PresentationSource.FromVisual(control);

double dpiX = 96.0 * source.CompositionTarget.TransformToDevice.M11;
double dpiY = 96.0 * source.CompositionTarget.TransformToDevice.M22;

window.Left = point.X * 96.0 / dpiX;
window.Top = point.Y * 96.0 / dpiY;
Haiku answered 17/5, 2011 at 19:19 Comment(1)
Great, it works, thanks. But in my case it even works without the dpi-parameter (96.0), see edit in my question.Wickham
P
1

The behavior you described is not correct and I can't reproduce it. I created a simple Window with the following code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        LocationChanged += (s, e) =>
            {
                var screen = PointToScreen(new Point(0, 0));
                var window = new Point(Left, Top);
                var diff = screen - window;
                textbox.Text = window.ToString() + Environment.NewLine + 
                               screen.ToString() + Environment.NewLine + diff;
            };
    }
}

The last line (= the difference between the two coordinates) never changes.

Prescription answered 17/5, 2011 at 14:0 Comment(3)
The same with your example, the difference becomes more and more greater on moving away from 0,0 ...Wickham
I tested it on a dualscreen system and moved the window on both monitors... diff is always constant. Is there something special with your setup?Prescription
I will check this out tomorrow. Thanks for your help so far.Wickham
D
0

I'm unable to reproduce the problem your experience. The upper left corner of the client area of the window (the point returned by PointToScreen) is always translated 8 pixels horizontally and 30 pixels vertically from the upper left corner of the window. This is on a two-monitor setup.

You should be able to compute the values 8 and 30 from the SystemParameters class, however I must admit that I'm not sure exactly what parameters to use to arrive at the actual values on my system.

Deration answered 17/5, 2011 at 13:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.