So berechnen Sie die Bildschirmposition eines Steuerelements (in Pixel) in WinUI 3C#

Ein Treffpunkt für C#-Programmierer
Anonymous
 So berechnen Sie die Bildschirmposition eines Steuerelements (in Pixel) in WinUI 3

Post by Anonymous »

Mein Ziel ist es, die Bildschirmposition des linken Randes des mittleren Blocks zu berechnen. Dies wird verwendet, um ein schwebendes Fenster genau am linken Rand zu positionieren.
Das Problem ist, dass der Wert, den ich bei der Berechnung der Bildschirmposition erhalte, nicht den Erwartungen entspricht. Diese Testanwendung zeigt die berechnete Position „vom Bildschirm“ und die tatsächlichen Bildschirmpositionen der schwebenden Fenster, wenn sie an ihren Platz gezogen werden.

Image
Berechnungen von Koordinaten in der Windows-Anwendung
Unter „ControlBlock“ ist die Breite des ControlBlocks und der „Fensterposition“ angegeben die Bildschirmkoordinaten berechnet mit:

Code: Select all

//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}";
Unter „LeftBlock“ steht die Breite des LeftBlocks und „LeftBlock Screen“ ist die falsch berechnete Bildschirmposition des linken Randes von LeftBlock:

Code: Select all

//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})";
Unterhalb von MiddleBlock werden verschiedene Werte berechnet: (Am interessantesten ist „Von Bildschirm“, sein X-Wert sollte derselbe sein, der in der „Bildschirmposition“ des schwebenden Fensters angezeigt wird).

Code: Select all

//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})";
Schwebende Fenster werden mit Bildschirmkoordinaten positioniert
Das schwebende Fenster wird an die richtige Position gezogen und „Bildschirmposition“ ist der Wert „floatingWindow.AppWindow.Position“.
Ich kann auch genaue Bildschirmkoordinaten angeben, die dann das schwebende Fenster mit „floatingWindow.AppWindow.Move(new PointInt32(targetX, targetY))“
Wenn ich das schwebende Fenster nahe der rechten Seite des Bildschirms positioniere, lautet die X-Koordinate 3397 + die Breite des Fensters (500), das liegt nahe an der Bildschirmauflösung (3840 x 2160).
Skalierungsverhältnis zwischen der virtuellen Auflösung und der realen Auflösung
Ich habe versucht, das Skalierungsverhältnis zu ermitteln, das in dieser Frage besprochen wurde, aber es ist so 1.0.
Wie erkennt man die aktuelle Bildschirmauflösung?
Frage
Weiß jemand, wie man die Bildschirmposition des linken Randes von MiddleBlock richtig berechnet? Offensichtlich sind die Koordinaten innerhalb der Anwendung keine Pixel. Ist eine Konvertierung erforderlich, um von Anwendungskoordinaten in Bildschirmkoordinaten zu gelangen?
Hinzugefügt
Eine Minimalversion, die nur den wesentlichen Teil enthält:
MinimalVersionPage.xaml

Code: Select all






















MinimalVersionPage.xaml.cs

Code: Select all

    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();
}
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post