My application (C#, WinForms, .NET 4.0, test under Windows 7 SP1) should work as follows:
There is a PictureBox somewhere on a Form. It's image has a rectangle area:
When user clicks that area, it is framed by a colored line:
This selection should take into account resizing of the Form:
And it also should take into account different DPI (assuming that it is set before application startup and never changes while application is running).
I wrote the following code:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private readonly RectangleF rectangleRelativeToPicturebox = new RectangleF(335.0F, 47.0F, 65.0F, 44.0F);
private Boolean rectangleIsClicked = false;
internal static readonly Pen clickedRectangleBorderPen = new Pen(Color.RoyalBlue, 4);
private readonly float pictureBoxInitialWidth, pictureBoxInitialHeight;
private float scaleByFormResizeX, scaleByFormResizeY, scaleByDpiX, scaleByDpiY, scaleX, scaleY;
public Form1()
{
InitializeComponent();
pictureBoxInitialWidth = pictureBox1.ClientSize.Width;
pictureBoxInitialHeight = pictureBox1.ClientSize.Height;
using (var graphics = CreateGraphics())
{
scaleByDpiX = graphics.DpiX / 96;
scaleByDpiY = graphics.DpiY / 96;
}
scaleByFormResizeX = 1.0F;
scaleByFormResizeY = 1.0F;
scaleX = scaleByFormResizeX * scaleByDpiX;
scaleY = scaleByFormResizeY * scaleByDpiY;
}
private void Form1_Resize(object sender, EventArgs e)
{
scaleByFormResizeX = pictureBox1.ClientSize.Width / pictureBoxInitialWidth;
scaleByFormResizeY = pictureBox1.ClientSize.Height / pictureBoxInitialHeight;
scaleX = scaleByFormResizeX * scaleByDpiX;
scaleY = scaleByFormResizeY * scaleByDpiY;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
if ((e.Location.X >= rectangleRelativeToPicturebox.Left * scaleX) && (e.Location.X <= rectangleRelativeToPicturebox.Right * scaleX) &&
(e.Location.Y >= rectangleRelativeToPicturebox.Top * scaleY) && (e.Location.Y <= rectangleRelativeToPicturebox.Bottom * scaleY))
rectangleIsClicked = true;
else
rectangleIsClicked = false;
pictureBox1.Refresh();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (rectangleIsClicked)
e.Graphics.DrawRectangle(clickedRectangleBorderPen, rectangleRelativeToPicturebox.X * scaleX, rectangleRelativeToPicturebox.Y * scaleY,
rectangleRelativeToPicturebox.Width * scaleX, rectangleRelativeToPicturebox.Height * scaleY);
}
}
}
I have the rectangle coordinates relative to the PictureBox.
I calculate scaleByFormResizeX
and scaleByFormResizeY
when the Form is resized.
That part works fine. But looks like I calculate scaleByDpiX
and scaleByDpiY
incorrectly, because for 120
DPI it looks like:
So whats wrong with my approach? Is there a better solution?
P.S. I've uploaded my sample application here