Неверные координаты на нескольких мониторах


У меня есть Datagrid, и я хочу знать положение ячейки данных для наложения на нее окна.
Он прекрасно работает только с одним монитором, но с несколькими мониторами окно смещается.
Вот код:

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

У кого-нибудь есть опыт позиционирования на нескольких мониторах?

Правка:
Я сделал следующее испытание:

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

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

Результаты:
- Одиночный Монитор: 0 30; 20 50; 100 130
= = > Всегда разница в 30 (может быть вызвана строка заголовка)
- Двойной Монитор: 0 30; 20 55; 100 153
==> При разнице 0,0 30. Но чем дальше я отодвигал окно от 0,0. чем больше становится разница, тем она должна оставаться неизменной. Очень странно!

EDIT2:
Вот мое решение, спасибо CodeNaked за подсказку:

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;
3 7

3 ответа:

Это может быть связано с нестандартной настройкой DPI, но я уверен, что эта настройка влияет на все мониторы. этот блог показывает, как получить правильную позицию. Но код фактически таков:

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;

Поведение, которое вы описали, неверно, и я не могу его воспроизвести. Я создал простое окно со следующим кодом:

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;
            };
    }
}
Последняя строка (=разница между двумя координатами) никогда не меняется.

Я не могу воспроизвести проблему вашего опыта. Верхний левый угол клиентской области окна (точка, возвращаемая PointToScreen) всегда переводится на 8 пикселей по горизонтали и 30 пикселей по вертикали из верхнего левого угла окна. Это на установке с двумя мониторами.

Вы должны быть в состоянии вычислить значения 8 и 30 из SystemParameters класс , однако я должен признать, что я не уверен точно, какие параметры использовать, чтобы получить фактические значения на моем система.