Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not support Font Zoom Size in Win10 #14

Open
Yari27 opened this issue Feb 10, 2018 · 4 comments
Open

Not support Font Zoom Size in Win10 #14

Yari27 opened this issue Feb 10, 2018 · 4 comments
Labels

Comments

@Yari27
Copy link

Yari27 commented Feb 10, 2018

ColorPicker incorrectly converts the cursor position at magnification other than 100% DPI.

2018-02-10_18-56-51

change-font-size-windows-10

@cyotek
Copy link
Owner

cyotek commented Feb 10, 2018

Hello,

Thanks for taking the time to log the issue! However, this is actually a duplicate of #12

I spent quite a bit of time trying to get this to "just work", but unfortunately I can't get Windows to stop "lying" to me unless I use a manifest which states the application is DPI-aware. This is not something the Color Picker Controls can do; only their host application. If you add a manifest stating that your application supports high DPI, then this works absolutely fine. However, you have to be certain that your application really does support it. Quite a few of mine do UI positioning by hand and completely break in high DPI.

There is a branch of the controls where I've been dabbling in making the controls (especially the ColorGrid) work better when used in a high DPI application, but it's still dependant on the client manifest.

Unfortunately I just don't have a solution to make them work in a program that doesn't report it is DPI-aware. My advice for now is to try adding a manifest and see how your application fares with it.

Regards;
Richard Moss

@cyotek cyotek added the bug label Feb 10, 2018
@Yari27
Copy link
Author

Yari27 commented Feb 11, 2018

Just need some calculation and for me work great:
In the farthest corner of the screen, one pixel is missing, but it can be rounded off.

2018-02-11_12-58-32

Proof:
YouTube

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace PositonInFontZoomMode
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }
        private Point point;

        private void button1_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            point = DisplayTools.GetRoundedRealPoint(Cursor.Position);

            label1.Text = "Position: " + point.ToString();
            label2.Text = "Font Zoom: " + DisplayTools.GetFontZoom() + "%";

            panel1.BackColor = GetPixelColor(point);
            label3.Text = panel1.BackColor.ToString();
            pictureBox1.Image = TakeCenterSnapshot(point, pictureBox1.Size);
        }

        #region GetPixelColor

        [DllImport("user32.dll")]
        public static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("gdi32.dll")]
        public static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos);

        [DllImport("user32.dll")]
        public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

        public static Color GetPixelColor(int x, int y)
        {
            IntPtr hdc = GetDC(IntPtr.Zero);
            uint pixel = GetPixel(hdc, x, y);
            ReleaseDC(IntPtr.Zero, hdc);
            return Color.FromArgb((int)(pixel & 0x000000FF), (int)(pixel & 0x0000FF00) >> 8, (int)(pixel & 0x00FF0000) >> 16);
        }
        public static Color GetPixelColor(Point position)
        {
            return GetPixelColor(position.X, position.Y);
        }

        #endregion

        public static Bitmap TakeCenterSnapshot(Point source, Size size)
        {
            Bitmap bmp = new Bitmap(size.Width, size.Height);
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bmp);
            g.CopyFromScreen(new Point(source.X - size.Width / 2, source.Y - size.Height / 2), new Point(0, 0), size);
            return bmp;
        }
    }

    static class DisplayTools
    {
        [DllImport("gdi32.dll")]
        static extern int GetDeviceCaps(IntPtr hdc, int nIndex);

        private enum DeviceCap
        {
            Desktopvertres = 117,
            Desktophorzres = 118
        }

        public static Size GetPhysicalDisplaySize()
        {
            Graphics g = Graphics.FromHwnd(IntPtr.Zero);
            IntPtr desktop = g.GetHdc();

            int physicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.Desktopvertres);
            int physicalScreenWidth = GetDeviceCaps(desktop, (int)DeviceCap.Desktophorzres);

            return new Size(physicalScreenWidth, physicalScreenHeight);
        }

        public static Size GetVirtualDisplaySize()
        {
            return new Size(SystemInformation.VirtualScreen.Width, SystemInformation.VirtualScreen.Height);
        }

        public static int GetFontZoom()
        {
            Size resolution = GetPhysicalDisplaySize();
            Size virtualscreen = GetVirtualDisplaySize();
            int zoomH = (resolution.Height * 100) / virtualscreen.Height;
            int zoomW = (resolution.Width * 100) / virtualscreen.Width;

            return zoomH == zoomW ? zoomH : 100;
        }

        public static PointF GetRealPoint(Point cursor)
        {
            return new PointF(cursor.X * ((float)GetFontZoom() / 100),
                cursor.Y * ((float)GetFontZoom() / 100));
        }

        public static Point GetRoundedRealPoint(Point cursor)
        {
            return new Point((int)Math.Round(cursor.X * ((float)GetFontZoom() / 100), 0),
                (int)Math.Round(cursor.Y * ((float)GetFontZoom() / 100), 0));
        }

    }
}

@cyotek
Copy link
Owner

cyotek commented Feb 11, 2018

Hello,

Thanks for posting this, that's interesting. I'll test that out when I get a moment and integrate it into the Color Picker controls if I don't find any issues with it. Definitely would be nice to get this one addressed.

Regards;
Richard Moss

@UweKeim
Copy link

UweKeim commented Mar 22, 2021

After changing

return zoomH == zoomW ? zoomH : 100;

to

return Math.Max(zoomW, zoomH);

I managed to use this code snippet to fix the ScreenColorPicker control by replacing the call to

MousePosition

to

DisplayTools.GetRoundedRealPoint(MousePosition)

So thank you, @Yari27 for the code snippets.

See also this SO answer for a related solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants