jq获取当前分辨率和缩放率
大家好,
我将描述一种缩放对象的方法,这样无论您在其上绘制画布的大小如何,它们都能正确地适合您的屏幕。 这将是一个相当简单的入门方法,有望激发您的想象力并帮助您入门。 这确实是一种通用的图形方法,但是为了简单起见,我将在带有GDI +的WinForms中进行。 如果愿意,可以将相同的原理应用于XNA或DirectX。
好的,让我们开始吧。 我们需要先绘制一些东西,所以让我们创建一个可以使用的简单对象层次结构。 我将从三个对象开始……接口类IDrawableObject,然后是另外两个类DrawableRectangle和DrawableCircle,它们都从该接口继承。
public interface IDrawableObject
{
void Draw(Graphics g);
}
public class DrawableRectangle : IDrawableObject
{
#region Private Members
private Point m_location = new Point();
private Size m_size = new Size();
private Color m_drawColor;
#endregion
#region Public Properties
public Color Color
{
get { return m_drawColor; }
set { m_drawColor = value; }
}
public Point Location
{
get { return m_location; }
set { m_location = value; }
}
public Size Size
{
get { return m_size; }
set { m_size = value; }
}
public int X
{
get { return m_location.X; }
set { m_location.X = value; }
}
public int Y
{
get { return m_location.Y; }
set { m_location.Y = value; }
}
public int Width
{
get { return m_size.Width; }
set { m_size.Height = value; }
}
public int Height
{
get { return m_size.Height; }
set { m_size.Height = value; }
}
#endregion
#region Constructors
public DrawableRectangle() { }
public DrawableRectangle(Point location, Size size)
: this()
{
m_location = location;
m_size = size;
}
public DrawableRectangle(int x, int y, int width, int height)
: this(new Point(x, y), new Size(width, height))
{
}
public DrawableRectangle(Point location, Size size, Color color)
: this(location, size)
{
m_drawColor = color;
}
public DrawableRectangle(int x, int y, int width, int height, Color color)
: this(new Point(x, y), new Size(width, height), color)
{
}
#endregion
#region IDrawableObject
public void Draw(Graphics g)
{
if (g != null)
{
g.DrawRectangle(new Pen(m_drawColor), m_location.X, m_location.Y, m_size.Width, m_size.Height);
}
}
#endregion
}
public class DrawableCircle : IDrawableObject
{
#region Private Members
private Point m_location;
private int m_radius;
private Color m_drawColor;
#endregion
#region Public Properties
public Color Color
{
get { return m_drawColor; }
set { m_drawColor = value; }
}
public Point Location
{
get { return m_location; }
set { m_location = value; }
}
public int X
{
get { return m_location.X; }
set { m_location.X = value; }
}
public int Y
{
get { return m_location.Y; }
set { m_location.Y = value; }
}
public int Radius
{
get { return m_radius; }
set { m_radius = value; }
}
#endregion
#region Constructors
public DrawableCircle() { }
public DrawableCircle(Point location, int radius)
: this()
{
m_location = location;
m_radius = radius;
}
public DrawableCircle(int x, int y, int radius)
: this(new Point(x, y), radius)
{
}
public DrawableCircle(Point location, int radius, Color color)
: this(location, radius)
{
m_drawColor = color;
}
public DrawableCircle(int x, int y, int radius, Color color)
: this(new Point(x, y), radius, color)
{
}
#endregion
#region IDrawableObject
public void Draw(Graphics g)
{
if (g != null)
{
g.DrawEllipse(new Pen(m_drawColor), m_location.X - m_radius, m_location.Y - m_radius, m_radius * 2, m_radius * 2);
}
}
#endregion
}
让我们以320x200的窗口大小开始(因为我是QBasic怀旧的:D)。
我们还可以设置一个圆形,以在窗体的中心绘制一个矩形。
我们可以在窗体上创建IDrawableObjects的列表,我们不妨继续重写OnPaint事件以绘制它们。
public partial class Form1 : Form
{
private List<IDrawableObject> m_drawList = new List<IDrawableObject>();
private Size m_baseSize;
public Form1()
{
InitializeComponent();
m_baseSize = new Size(320, 200);
this.Size = new Size(m_baseSize.Width, m_baseSize.Height);
DrawableCircle c = new DrawableCircle(m_baseSize.Width / 2, m_baseSize.Height / 2, 50, Color.Red);
DrawableRectangle r = new DrawableRectangle(c.X - 50, c.Y - 100, 100, 50, Color.Blue);
m_drawList.Add(c);
m_drawList.Add(r);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
foreach (IDrawableObject obj in m_drawList)
{
obj.Draw(e.Graphics);
}
}
}
好的,我们如何缩放这些对象,以便如果我们切换到不同的分辨率(即,不同的表单大小),则事物将正确显示?
好吧,我们将需要计算一个比例,然后我们将不得不使用该比例来更改工程图。
让我们从计算比例开始...我们可以用一个点来做,但是让我们使用PointF对象并在以后舍入以保持精度。
让我们在表单中添加一个私人成员...
private PointF m_scale;
获取比例就像生成当前对象画布大小与基础画布大小之比一样简单。
我们可以创建一个方法来执行此操作并将其放在Form类中。
private PointF CalculateScale(float baseX, float baseY, float newX, float newY)
{
return new PointF(newX / baseX, newY / baseY);
}
现在在构造函数中,我们可以计算比例尺...
m_scale = CalculateScale((float)m_baseSize.Width, (float)m_baseSize.Height, this.Size.Width, this.Size.Height);
显然,如果运行此命令,将生成X = 1和Y = 1的比例,因此让我们在构造函数中更改代码,只需将基本大小乘以2,即可将表单的大小设置为两倍。
this.Size = new Size(m_baseSize.Width * 2, m_baseSize.Height * 2);
是的,所以现在如果运行代码,我们将看到对象不再位于中心,并且将生成2的比例尺。我们需要更新接口以提供新的绘图方法DrawScaled,我们可以在我们的对象上实施以充分利用规模。
public interface IDrawableObject
{
void Draw(Graphics g);
void DrawScaled(Graphics g, PointF scale);
}
让我们先做圆圈...我们可以使用以下内容更新DrawableCircle方法...
public void DrawScaled(Graphics g, PointF scale)
{
if (g != null)
{
g.DrawEllipse
(
new Pen(m_drawColor),
(m_location.X - m_radius) * scale.X,
(m_location.Y - m_radius) * scale.Y,
(m_radius * 2) * scale.X,
(m_radius * 2) * scale.Y
);
}
}
我们要做的就是将每个坐标乘以比例,将其移动到正确的位置。
现在,如果我们运行它,我们将得到一个更大的圆圈,它又回到了以表格为中心的位置。
当然,现在我们的矩形也需要更新,但这很容易...我们做同样的事情。
public void DrawScaled(Graphics g, PointF scale)
{
if (g != null)
{
g.DrawRectangle
(
new Pen(m_drawColor),
m_location.X * scale.X,
m_location.Y * scale.Y,
m_size.Width * scale.X,
m_size.Height * scale.Y
);
}
}
现在,如果我们运行代码,一切都会恢复到应有的状态。
现在,我们可以将表单的大小更改为任意数字,并且仍会在表单中心获得一个圆形绘图,并在其顶部放置一个矩形。
为了演示这一点,让我们向表单上的resize事件添加事件侦听器。 我们需要做的就是重新计算比例尺并使表单无效以强制重新绘制。
在构造函数中...
this.Resize += new EventHandler(Form1_Resize);
然后实现事件处理程序...
void Form1_Resize(object sender, EventArgs e)
{
m_scale = CalculateScale(m_baseSize.Width, m_baseSize.Height, this.Width, this.Height);
this.Invalidate();
}
您可以将此缩放原理应用于您在表单上绘制的任何内容。
请注意,我在这里所做的操作不考虑宽高比,而是直接计算比例。
如果您想保持宽高比,则需要多做一些计算以获得正确的缩放比例,但是代码看起来不会有太大不同。
确实,这是一个简单的问题,即找到较大的尺寸,宽度或高度并将比例尺锁定为较小的值。
这会强制缩放在宽度和高度上相同,并且使用较小的缩放系数可确保您不会在屏幕上缩小。
这是完整的代码,希望人们发现它有用:)
public partial class Form1 : Form
{
private List<IDrawableObject> m_drawList = new List<IDrawableObject>();
private PointF m_scale;
private Size m_baseSize;
public Form1()
{
InitializeComponent();
m_baseSize = new Size(320, 200);
this.Size = new Size(640, 480);
this.Resize += new EventHandler(Form1_Resize);
m_scale = CalculateScale((float)m_baseSize.Width, (float)m_baseSize.Height, this.Size.Width, this.Size.Height);
DrawableCircle c = new DrawableCircle(m_baseSize.Width / 2, m_baseSize.Height / 2, 50, Color.Red);
DrawableRectangle r = new DrawableRectangle(c.X - 50, c.Y - 100, 100, 50, Color.Blue);
m_drawList.Add(c);
m_drawList.Add(r);
}
void Form1_Resize(object sender, EventArgs e)
{
m_scale = CalculateScale(m_baseSize.Width, m_baseSize.Height, this.Width, this.Height);
this.Invalidate();
}
private PointF CalculateScale(float baseX, float baseY, float newX, float newY)
{
return new PointF(newX / baseX, newY / baseY);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
foreach (IDrawableObject obj in m_drawList)
{
obj.DrawScaled(e.Graphics, m_scale);
}
}
}
#region Drawable Objects
public interface IDrawableObject
{
void Draw(Graphics g);
void DrawScaled(Graphics g, PointF scale);
}
public class DrawableRectangle : IDrawableObject
{
#region Private Members
private Point m_location = new Point();
private Size m_size = new Size();
private Color m_drawColor;
#endregion
#region Public Properties
public Color Color
{
get { return m_drawColor; }
set { m_drawColor = value; }
}
public Point Location
{
get { return m_location; }
set { m_location = value; }
}
public Size Size
{
get { return m_size; }
set { m_size = value; }
}
public int X
{
get { return m_location.X; }
set { m_location.X = value; }
}
public int Y
{
get { return m_location.Y; }
set { m_location.Y = value; }
}
public int Width
{
get { return m_size.Width; }
set { m_size.Height = value; }
}
public int Height
{
get { return m_size.Height; }
set { m_size.Height = value; }
}
#endregion
#region Constructors
public DrawableRectangle() { }
public DrawableRectangle(Point location, Size size)
: this()
{
m_location = location;
m_size = size;
}
public DrawableRectangle(int x, int y, int width, int height)
: this(new Point(x, y), new Size(width, height))
{
}
public DrawableRectangle(Point location, Size size, Color color)
: this(location, size)
{
m_drawColor = color;
}
public DrawableRectangle(int x, int y, int width, int height, Color color)
: this(new Point(x, y), new Size(width, height), color)
{
}
#endregion
#region IDrawableObject
public void Draw(Graphics g)
{
if (g != null)
{
g.DrawRectangle(new Pen(m_drawColor), m_location.X, m_location.Y, m_size.Width, m_size.Height);
}
}
public void DrawScaled(Graphics g, PointF scale)
{
if (g != null)
{
g.DrawRectangle
(
new Pen(m_drawColor),
m_location.X * scale.X,
m_location.Y * scale.Y,
m_size.Width * scale.X,
m_size.Height * scale.Y
);
}
}
#endregion
}
public class DrawableCircle : IDrawableObject
{
#region Private Members
private Point m_location;
private int m_radius;
private Color m_drawColor;
#endregion
#region Public Properties
public Color Color
{
get { return m_drawColor; }
set { m_drawColor = value; }
}
public Point Location
{
get { return m_location; }
set { m_location = value; }
}
public int X
{
get { return m_location.X; }
set { m_location.X = value; }
}
public int Y
{
get { return m_location.Y; }
set { m_location.Y = value; }
}
public int Radius
{
get { return m_radius; }
set { m_radius = value; }
}
#endregion
#region Constructors
public DrawableCircle() { }
public DrawableCircle(Point location, int radius)
: this()
{
m_location = location;
m_radius = radius;
}
public DrawableCircle(int x, int y, int radius)
: this(new Point(x, y), radius)
{
}
public DrawableCircle(Point location, int radius, Color color)
: this(location, radius)
{
m_drawColor = color;
}
public DrawableCircle(int x, int y, int radius, Color color)
: this(new Point(x, y), radius, color)
{
}
#endregion
#region IDrawableObject
public void Draw(Graphics g)
{
if (g != null)
{
g.DrawEllipse(new Pen(m_drawColor), m_location.X - m_radius, m_location.Y - m_radius, m_radius * 2, m_radius * 2);
}
}
public void DrawScaled(Graphics g, PointF scale)
{
if (g != null)
{
g.DrawEllipse
(
new Pen(m_drawColor),
(m_location.X - m_radius) * scale.X,
(m_location.Y - m_radius) * scale.Y,
(m_radius * 2) * scale.X,
(m_radius * 2) * scale.Y
);
}
}
#endregion
}
#endregion
如果您发现任何问题,请随时让我知道。
我不假装不能不时地把东西弄丢;)
翻译自: https://bytes.com/topic/c-sharp/insights/909141-object-scaling-varying-resolutions
jq获取当前分辨率和缩放率