Как прочитать цвет другого монитора пикселей - PullRequest
0 голосов
/ 08 апреля 2020

Я следовал за этот ответ , и он отлично работает с одним монитором (несмотря на то, что ему было 11 лет: D). Но когда я подключил второй монитор и использую его, он больше не работает. Вместо этого он всегда дает странный цвет, как и весь черный, когда x > 2500

enter image description here

Редактировать: я обнаружил проблему, это было связано с разным масштабом текста на оба монитора (1-й - 125% и 2-й - 100%), я изменяю настройку на 125% и работаю как брелок. Теперь проблема в том, как мне автоматически c определить масштабирование шрифта на другом мониторе (в настоящее время я использую this для первого монитора)

1 Ответ

0 голосов
/ 09 апреля 2020

Таким образом, проблема заключается в разных масштабах на каждом мониторе

Во-первых, я определяю индекс, на котором монитор входит point с этим ответом :

    private int ConvertMousePointToScreenIndex(Point mousePoint)
    {
        //first get all the screens 
        System.Drawing.Rectangle ret;

        for (int i = 1; i <= Screen.AllScreens.Count(); i++)
        {
            ret = Screen.AllScreens[i - 1].Bounds;
            if (ret.Contains(mousePoint))
                return i - 1;
        }
        return 0;
    }

Во-вторых, мне просто нужно получить real width / virtual width этого индексированного монитора на основе этого ответа

        const int ENUM_CURRENT_SETTINGS = -1;

        public double GetScale(Point point)
        {
            Screen screen = Screen.AllScreens[ConvertMousePointToScreenIndex(point)];
            DEVMODE dm = new DEVMODE();
            dm.dmSize = (short)Marshal.SizeOf(typeof(DEVMODE));
            EnumDisplaySettings(screen.DeviceName, ENUM_CURRENT_SETTINGS, ref dm);

            double RealWidth = dm.dmPelsWidth;
            double VirtualWidth = screen.Bounds.Width;
            return RealWidth / VirtualWidth;
        }

        [DllImport("user32.dll")]
        public static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref DEVMODE lpDevMode);

        [StructLayout(LayoutKind.Sequential)]
        public struct DEVMODE
        {
            private const int CCHDEVICENAME = 0x20;
            private const int CCHFORMNAME = 0x20;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
            public string dmDeviceName;
            public short dmSpecVersion;
            public short dmDriverVersion;
            public short dmSize;
            public short dmDriverExtra;
            public int dmFields;
            public int dmPositionX;
            public int dmPositionY;
            public ScreenOrientation dmDisplayOrientation;
            public int dmDisplayFixedOutput;
            public short dmColor;
            public short dmDuplex;
            public short dmYResolution;
            public short dmTTOption;
            public short dmCollate;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 0x20)]
            public string dmFormName;
            public short dmLogPixels;
            public int dmBitsPerPel;
            public int dmPelsWidth;
            public int dmPelsHeight;
            public int dmDisplayFlags;
            public int dmDisplayFrequency;
            public int dmICMMethod;
            public int dmICMIntent;
            public int dmMediaType;
            public int dmDitherType;
            public int dmReserved1;
            public int dmReserved2;
            public int dmPanningWidth;
            public int dmPanningHeight;
        }

И, наконец, применить его к GetColorAt :

        [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
        public static extern int BitBlt(IntPtr hDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);

        Bitmap screenPixel = new Bitmap(1, 1, PixelFormat.Format32bppArgb);
        public Color GetColorAt(Point location)
        {
            double scale = GetScale(location);
            using (Graphics gdest = Graphics.FromImage(screenPixel))
            {
                using (Graphics gsrc = Graphics.FromHwnd(IntPtr.Zero))
                {
                    IntPtr hSrcDC = gsrc.GetHdc();
                    IntPtr hDC = gdest.GetHdc();
                    int retval = BitBlt(hDC, 0, 0, 1, 1, hSrcDC, (int)Math.Round(point.X * scale), (int)Math.Round(point.Y * scale), (int)CopyPixelOperation.SourceCopy);
                    gdest.ReleaseHdc();
                    gsrc.ReleaseHdc();
                }
            }

            return screenPixel.GetPixel(0, 0);
        }
...