问题描述
C#获取屏幕尺寸与位置与实际屏幕尺寸位置不一致
使用System.Windows.Forms.Screen.PrimaryScreen.Bounds获取的边界是 1536*864
而使用微信截图获取的屏幕大小是 1920*1080;
使用System.Windows.Forms.Cursor.Position和System.Windows.Forms.Control. MousePosition
以及user32.dll的GetCursorPos获取的点的颜色与实际位置的颜色也有偏差。
public void ScreenInfo()
{
//光标位置
Point CursorPos = System.Windows.Forms.Cursor.Position;
//鼠标光标的位置
Point MousePositionX =System.Windows.Forms.Control. MousePosition;
//整个屏幕的大小
Rectangle ScreenBounds = System.Windows.Forms.Screen.GetBounds(this);
Rectangle ScreenPrimaryScreenBounds = System.Windows.Forms.Screen.PrimaryScreen.Bounds;
//屏幕除任务栏以外的工作区域大小
Rectangle ScreenWorkingArea = System.Windows.Forms.Screen.GetWorkingArea(this);
Rectangle ScreenPrimaryScreenWorkingArea = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea;
Rectangle VirtualScreen = System.Windows.Forms.SystemInformation.WorkingArea;
}
分析原因
原来跟我的电脑设置了缩放比列有关系。
解决方案
1、获取【桌面的实际宽度】;
2、获取【显示的屏幕宽度】;
3、计算出缩放比列;
4、用缩放比列计算出实际的鼠标位置;
代码示例,获取鼠标位置得RGB值,如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Runtime.InteropServices;
namespace SMQH
{
class Win32Helper
{
/// <summary>
/// 该函数检索一指定窗口的客户区域或整个屏幕的显示设备上下文环境的句柄,
/// 以后可以在GDI函数中使用该句柄来在设备上下文环境中绘图。
/// </summary>
/// <param name="hWnd">设备上下文环境被检索的窗口的句柄,如果该值为NULL,GetDC则检索整个屏幕的设备上下文环境。</param>
/// <returns>如果成功,返回指定窗口客户区的设备上下文环境;如果失败,返回值为Null。</returns>
[DllImport("user32")]
public static extern IntPtr GetDC(IntPtr hWnd);
/// <summary>
/// 该函数释放设备上下文环境(DC)供其他应用程序使用。函数的效果与设备上下文环境类型有关。
/// 它只释放公用的和设备上下文环境,对于类或私有的则无效。
/// </summary>
/// <param name="hWnd">指向要释放的设备上下文环境所在的窗口的句柄。</param>
/// <param name="hDC">指向要释放的设备上下文环境的句柄。</param>
/// <returns>如果释放成功,则返回值为1;如果没有释放成功,则返回值为0。</returns>
[DllImport("user32")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32")]
public static extern bool GetCursorPos(out System.Drawing.Point pt);
/// <summary>
/// 该函数检索指定坐标点的像素的RGB颜色值。
/// </summary>
/// <param name="hDC">设备环境句柄。</param>
/// <param name="nXPos">指定要检查的像素点的逻辑X轴坐标。</param>
/// <param name="nYPos">指定要检查的像素点的逻辑Y轴坐标。</param>
/// <returns>返回值是该象像点的RGB值。如果指定的像素点在当前剪辑区之外;那么返回值是CLR_INVALID。</returns>
[DllImport("gdi32")]
public static extern uint GetPixel(IntPtr hDC, int nXPos, int nYPos);
[DllImport("gdi32")]
static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
public const int HORZRES = 8;
public const int VERTRES = 10;
public const int DESKTOPVERTRES = 117;
public const int DESKTOPHORZRES = 118;
/// <summary>
/// 获取当前鼠标位置颜色
/// </summary>
/// <returns></returns>
public static System.Drawing.Color GetPixelColor()
{
Point pnt = new Point(0, 0);
IntPtr hdc = GetDC(IntPtr.Zero);
GetCursorPos(out pnt);
float ScaleX = (float)GetDeviceCaps(hdc, DESKTOPHORZRES) / (float)GetDeviceCaps(hdc, HORZRES);
float ScaleY = (float)GetDeviceCaps(hdc, DESKTOPVERTRES) / (float)GetDeviceCaps(hdc, VERTRES);
uint pixel = GetPixel(hdc, (int)(pnt.X * ScaleX), (int)(pnt.Y * ScaleY));
ReleaseDC(IntPtr.Zero, hdc);
Color color = Color.FromArgb((int)(pixel & 0x000000FF),
(int)(pixel & 0x0000FF00) >> 8,
(int)(pixel & 0x00FF0000) >> 16);
return color;
}
}
}