Неверные координаты на нескольких мониторах
У меня есть 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 ответа:
Это может быть связано с нестандартной настройкой 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
класс , однако я должен признать, что я не уверен точно, какие параметры использовать, чтобы получить фактические значения на моем система.