I am doing some basic drawing on a Form using classes from System.Drawing (coding in C#, against .NET 4.7.2).
I would like to configure the form so that the coordinate range of the client area is (0, 0) to (100, 100) regardless of the form size. In other words, if we maximize the form, the lower-right coordinate should still be (100, 100).
Can this be done without having to roll my own scaling functions?
You can do this using Graphics.ScaleTransform()
.
Here's an example which sets the scaling such that the window coords are from 0 to 100 for width and height. Note that you have to repaint and recalculate the transform whenever the window size changes:
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
this.ResizeRedraw = true;
InitializeComponent();
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
setScaling(e.Graphics);
e.Graphics.DrawRectangle(Pens.Black, 5, 5, 90, 90); // Draw rectangle close to the edges.
}
void setScaling(Graphics g)
{
const float WIDTH = 100;
const float HEIGHT = 100;
g.ScaleTransform(ClientRectangle.Width/WIDTH, ClientRectangle.Height/HEIGHT);
}
}
}
This does not account for the window's aspect ratio, so even though you are drawing a square, it comes out as a rectangle if the window is not square.
If you want to keep a square aspect ratio, you can do that by also calculating a TranslateTransform()
. Note that this introduces a blank area at the top+bottom or left+right, depending on the aspect ratio of the window:
void setScaling(Graphics g)
{
const double WIDTH = 100;
const double HEIGHT = 100;
double targetAspectRatio = WIDTH / HEIGHT;
double actualAspectRatio = ClientRectangle.Width / (double)ClientRectangle.Height;
double h = ClientRectangle.Height;
double w = ClientRectangle.Width;
if (actualAspectRatio > targetAspectRatio)
{
w = h * targetAspectRatio;
double x = (ClientRectangle.Width - w) / 2;
g.TranslateTransform((float)x, 0);
}
else
{
h = w / targetAspectRatio;
double y = (ClientRectangle.Height - h) / 2;
g.TranslateTransform(0, (float)y);
}
g.ScaleTransform((float)(w / WIDTH), (float)(h / HEIGHT));
}