前言
假如屏幕是1920*1080,缩放是125%;
那么WPF窗口最大设置为1536*864就会占满屏幕。
获取鼠标位置
获取的是屏幕实际像素对应的位置。
代码语言:javascript复制using System.Runtime.InteropServices;
namespace ColorPicker.Utils
{
internal class ZPoint
{
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool GetCursorPos(out POINT pt);
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
}
}
调用
代码语言:javascript复制ZPoint.POINT point;
ZPoint.GetCursorPos(out point);
这样获取的坐标是屏幕的实际尺寸算的,即1920*1080。
如果我们根据这个值设置WPF的窗口就会发生偏移。
像素坐标转换为WPF坐标
代码语言:javascript复制ZPoint.POINT point;
ZPoint.GetCursorPos(out point);
Matrix transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
Point wpfPoint = transform.Transform(new System.Windows.Point(point.X, point.Y));
获取窗口的缩放率
代码语言:javascript复制using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Windows;
using System.Windows.Forms;
namespace ColorPicker.Utils
{
internal class ScreenHelper
{
private const string User32 = "user32.dll";
[DllImport(User32, CharSet = CharSet.Auto)]
[ResourceExposure(ResourceScope.None)]
public static extern bool GetMonitorInfo(HandleRef hmonitor, [In, Out] MONITORINFOEX info);
[DllImport(User32, ExactSpelling = true)]
[ResourceExposure(ResourceScope.None)]
public static extern bool EnumDisplayMonitors(HandleRef hdc, COMRECT rcClip, MonitorEnumProc lpfnEnum, IntPtr dwData);
public delegate bool MonitorEnumProc(IntPtr monitor, IntPtr hdc, IntPtr lprcMonitor, IntPtr lParam);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
public class MONITORINFOEX
{
internal int cbSize = Marshal.SizeOf(typeof(MONITORINFOEX));
internal RECT rcMonitor = new RECT();
internal RECT rcWork = new RECT();
internal int dwFlags = 0;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
internal char[] szDevice = new char[32];
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public RECT(Rect r)
{
left = (int)r.Left;
top = (int)r.Top;
right = (int)r.Right;
bottom = (int)r.Bottom;
}
}
[StructLayout(LayoutKind.Sequential)]
public class COMRECT
{
public int left;
public int top;
public int right;
public int bottom;
}
public static readonly HandleRef NullHandleRef = new HandleRef(null, IntPtr.Zero);
/// <summary>
/// 获取缩放比例
/// </summary>
/// <returns></returns>
public static double GetScalingRatio()
{
var logicalHeight = GetLogicalHeight();
var actualHeight = GetActualHeight();
if (logicalHeight > 0 && actualHeight > 0)
{
return logicalHeight / actualHeight;
}
return 1;
}
private static double GetActualHeight()
{
return SystemParameters.PrimaryScreenHeight;
}
private static double GetLogicalHeight()
{
var logicalHeight = 0.0;
MonitorEnumProc proc = (m, h, lm, lp) =>
{
MONITORINFOEX info = new MONITORINFOEX();
GetMonitorInfo(new HandleRef(null, m), info);
//是否为主屏
if ((info.dwFlags & 0x00000001) != 0)
{
logicalHeight = info.rcMonitor.bottom - info.rcMonitor.top;
}
return true;
};
EnumDisplayMonitors(NullHandleRef, null, proc, IntPtr.Zero);
return logicalHeight;
}
}
}
调用
代码语言:javascript复制ZPoint.POINT point;
ZPoint.GetCursorPos(out point);
var ScalingRatio = ScreenHelper.GetScalingRatio();
Console.WriteLine($"当前缩放比例为{ScalingRatio}%");
colorWin.Top = point.Y / ScalingRatio 4;
colorWin.Left = point.X / ScalingRatio 4;
这种作用和下面是一样的。
设置窗口在鼠标右下角
colorWin中添加如下方法
代码语言:javascript复制private void MoveBottomRightEdgeOfWindowToMousePosition()
{
var transform = PresentationSource.FromVisual(this).CompositionTarget.TransformFromDevice;
var mouse = transform.Transform(GetMousePosition());
Left = mouse.X 2;
Top = mouse.Y - ActualHeight - 2;
}
public System.Windows.Point GetMousePosition()
{
System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
return new System.Windows.Point(point.X, point.Y);
}
更新位置
代码语言:javascript复制new Thread(o => {
while (true) {
Dispatcher.Invoke(
() =>
{
if (Visibility == Visibility.Visible)
{
MoveBottomRightEdgeOfWindowToMousePosition();
}
}
);
Thread.Sleep(10);
}
})
{
IsBackground = true
}.Start();