Проблема в том, что значение, которое я получаю при вычислении положения экрана, не соответствует ожидаемому. Это тестовое приложение показывает расчетное положение «От экрана» и фактическое положение плавающих окон на экране при перетаскивании на место.

Расчеты координат в приложении Windows
Под «ControlBlock» указана ширина ControlBlock а «Позиция окна» — это координаты экрана, рассчитанные с помощью:
//Application window position
var mainWindow = (Application.Current as App) ? ._window;
PointInt32 windowPos = mainWindow.AppWindow.Position;
//Get monitor from a window
IntPtr hwnd = WinRT.Interop.WindowNative.GetWindowHandle(mainWindow);
IntPtr hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
//Control block
WindowPos.Text = $ "Window Pos: ({windowPos.X:N0}, {windowPos.Y:N0})";
ControlBlockWidth.Text = $ "Width: {ControlBlock.ActualWidth:N0}";
Ниже «LeftBlock» указана ширина LeftBlock, а «LeftBlock Screen» — неправильно рассчитанное положение левого края LeftBlock на экране:
//Left block
LeftBlockWidth.Text = $ "Width: {LeftBlock.ActualWidth:N0}";
var transformLeftBlock = LeftBlock.TransformToVisual(mainWindow.Content as UIElement);
var pointLeftBlock = transformLeftBlock.TransformPoint(new Point(0, 0));
LeftBlockScreenCoord.Text = $ "LeftBlock Screen: ({pointLeftBlock.X + windowPos.X:N0}, {pointLeftBlock.Y + windowPos.Y:N0})";
Ниже MiddleBlock рассчитываются различные значения: (Наиболее интересным является «С экрана», его значение X должно быть таким же, как показано в «Позиции экрана» плавающего окна).
//Middle block
var transform = MiddleBlock.TransformToVisual(LeftBlock);
var pointInRoot = transform.TransformPoint(new Point(0, 0));
MiddleBlockFromLeftBlock.Text = $ "From LeftBlock: ({pointInRoot.X:N0}, {pointInRoot.Y:N0})";
var transform2 = MiddleBlock.TransformToVisual(RootGrid);
var pointInRoot2 = transform2.TransformPoint(new Point(0, 0));
MiddleBlockFromRootGrid.Text = $ "From RootGrid: ({pointInRoot2.X:N0}, {pointInRoot2.Y:N0})";
var transform3 = MiddleBlock.TransformToVisual(mainWindow.Content as UIElement);
var pointInRoot3 = transform3.TransformPoint(new Point(0, 0));
MiddleBlockWindowCoord.Text = $ "From AppWindow: ({pointInRoot3.X:N0}, {pointInRoot3.Y:N0})";
MiddleBlockScreenCoord.Text = $ "From Screen: ({pointInRoot3.X + windowPos.X:N0}, {pointInRoot3.Y + windowPos.Y:N0})";
Плавающие окна позиционируются по координатам экрана
Плавающие окна перетаскиваются в нужное положение, а «Положение экрана» — это значение «floatingWindow.AppWindow.Position».
Я также могу указать точные координаты экрана, которые затем позиционируют плавающее окно с помощью «floatingWindow.AppWindow.Move(new) PointInt32(targetX, targetY))»
Если я расположим плавающее окно ближе к правой стороне экрана, координата X будет равна 3397 + ширина окна (500), что близко к разрешению экрана (3840x2160).
Коэффициент масштабирования между виртуальным разрешением и реальным разрешением
Я попытался получить коэффициент масштабирования, который обсуждался в этом вопросе, но это 1.0.
Как определить текущее разрешение экрана?
Вопрос
Кто-нибудь знает, как правильно рассчитать положение левого края экрана MiddleBlock? Очевидно, что координаты внутри приложения не являются пикселями. Нужно ли какое-либо преобразование для перехода от координат приложения к координатам экрана?
Добавлено
Минимальная версия, содержащая только основную часть:
MinimalVersionPage.xaml
MinimalVersionPage.xaml.cs
public sealed partial class MinimalVersionPage : Page
{
public MinimalVersionPage()
{
InitializeComponent();
}
private void UpdateCoordsButton_Click(object sender, RoutedEventArgs e)
{
//Application window position
var mainWindow = (Application.Current as App)?._window;
PointInt32 windowPos = mainWindow.AppWindow.Position;
//Left block
WindowPos.Text = $"Window Pos: ({windowPos.X:N0}, {windowPos.Y:N0})";
LeftBlockWidth.Text = $"Width: {LeftBlock.ActualWidth:N0}";
//Middle block
var transform3 = MiddleBlock.TransformToVisual(mainWindow.Content as UIElement);
var pointInRoot3 = transform3.TransformPoint(new Point(0, 0));
MiddleBlockWindowCoord.Text = $"From AppWindow: ({pointInRoot3.X:N0}, {pointInRoot3.Y:N0})";
MiddleBlockScreenCoord.Text = $"From Screen: ({pointInRoot3.X + windowPos.X:N0}, {pointInRoot3.Y + windowPos.Y:N0})";
}
private void CreateWindow_Click(object sender, RoutedEventArgs e)
{
var floatingWindow = new Window
{
Title = "Floating Window"
};
floatingWindow.AppWindow.Resize(new Windows.Graphics.SizeInt32(500, 700));
var presenter = floatingWindow.AppWindow.Presenter as Microsoft.UI.Windowing.OverlappedPresenter;
if (presenter != null)
{
presenter.IsAlwaysOnTop = true;
}
var stackPanel = new StackPanel
{
Padding = new Thickness(20),
Spacing = 10
};
var coordinateText = new TextBlock
{
Text = "Screen Position: (0, 0)",
FontSize = 16,
HorizontalAlignment = HorizontalAlignment.Center
};
stackPanel.Children.Add(coordinateText);
floatingWindow.Content = stackPanel;
// Set up a timer to update the coordinates every 16 milliseconds (~60 FPS)
var dispatcherQueue = floatingWindow.DispatcherQueue;
var timer = dispatcherQueue.CreateTimer();
timer.Interval = TimeSpan.FromMilliseconds(16);
timer.IsRepeating = true;
timer.Tick += (s, args) =>
{
var position = floatingWindow.AppWindow.Position;
var size = floatingWindow.AppWindow.Size;
coordinateText.Text = $"Screen Position: ({position.X}, {position.Y})";
};
floatingWindow.Closed += (s, args) =>
{
timer.Stop();
};
timer.Start();
floatingWindow.Activate();
}
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... in-winui-3
Мобильная версия