WPF SkiaSharp Canvas 单击鼠标位置

WPF SkiaSharp Canvas Click Mouse position

注意:这是一个 C# SkiaSharp WPF 应用程序。

当我重新绘制 SKCanvas(这是我的应用程序的整个宽度)时,我会记录宽度和高度。现在忽略高度。在 4K 显示器上,宽度被正确记录为 3840 像素(最大化时)。

当我点击最左边的canvas时,记录的鼠标X位置几乎为零

但是,当我点击 canvas 的最右侧时,给出的 X 位置为 2552,而不是我预期的接近 3840 的位置?

这是我用来在单击鼠标时获取鼠标位置的代码。

private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    var pixelPosition = e.GetPosition(sender as SKElement);
    // ...
}

和我的 XAML:

<skia:SKElement
    Name="MyCanvas"
    PaintSurface="MyCanvas_PaintSurface"
    MouseLeftButtonDown="MyCanvas_MouseLeftButtonDown"
    />

我还检查了 MyCanvasSizeChanged 事件中的 width/height,它也没有报告 3840,它报告宽度为 2552?

知道为什么报告的宽度是 2552 而实际宽度是 3840 吗?

正如@Leandro 指出的那样,您的 DPI 缩放比例为 150%。您可以在 .NET Framework >= 4.6.2.NET Core >= 3.0 中使用 GetDpi method of VisualTreeHelper. It returns a DpiScale 结构获取 DPI 比例包含缩放水平和垂直 DPI 比例因子。

private void MyCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
   var mainWindow = Application.Current.MainWindow;
   var dpiScale = VisualTreeHelper.GetDpi(mainWindow);

   var dpiScaleX = dpiScale.DpiScaleX;
   var dpiScaleY = dpiScale.DpiScaleY;

   var pixelPosition = e.GetPosition(sender as Canvas);
   var scaledPixelPosition = new System.Windows.Point(pixelPosition.X * dpiScaleX, pixelPosition.Y * dpiScaleY);

   // ...your code.
}

如果您使用的是没有 GetDpi 的较低版本的框架,则可以改用 this

var mainWindow = Application.Current.MainWindow;

Matrix m = PresentationSource.FromVisual(mainWindow).CompositionTarget.TransformToDevice;
var dpiScaleX = m.M11;
var dpiScaleY = m.M22;