110,545
社区成员
发帖
与我相关
我的任务
分享
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace ImageScale
{
public partial class Form1 : Form
{
public Form1() {
InitializeComponent();
this.StartPosition = FormStartPosition.CenterScreen;
this.pictureBox1.BorderStyle = BorderStyle.FixedSingle;
this.pictureBox1.BackColor = Color.DarkGray;
this.pictureBox1.MouseWheel += new MouseEventHandler(pictureBox1_MouseWheel);
}
Bitmap m_bmp; //画布中的图像
Point m_ptCanvas; //画布原点在设备上的坐标
Point m_ptCanvasBuf; //重置画布坐标计算时用的临时变量
Point m_ptBmp; //图像位于画布坐标系中的坐标
float m_nScale = 1.0F; //缩放比例
Point m_ptMouseDown; //鼠标点下是在设备坐标上的坐标
string m_strMousePt; //鼠标当前位置对应的坐标
private void Form1_Load(object sender, EventArgs e) {
m_bmp = GetScreen();
//初始化 坐标
m_ptCanvas = new Point(pictureBox1.Width / 2, pictureBox1.Height / 2);
m_ptBmp = new Point(-(m_bmp.Width / 2), -(m_bmp.Height / 2));
}
//获取屏幕图像
public Bitmap GetScreen() {
Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
Screen.PrimaryScreen.Bounds.Height);
using (Graphics g = Graphics.FromImage(bmp)) {
g.CopyFromScreen(0, 0, 0, 0, bmp.Size);
}
return bmp;
}
//重绘图像
private void pictureBox1_Paint(object sender, PaintEventArgs e) {
Graphics g = e.Graphics;
g.TranslateTransform(m_ptCanvas.X, m_ptCanvas.Y); //设置坐标偏移
g.ScaleTransform(m_nScale, m_nScale); //设置缩放比
g.DrawImage(m_bmp, m_ptBmp); //绘制图像
g.ResetTransform(); //重置坐标系
Pen p = new Pen(Color.Cyan, 3);
g.DrawLine(p, 0, m_ptCanvas.Y, pictureBox1.Width, m_ptCanvas.Y);
g.DrawLine(p, m_ptCanvas.X, 0, m_ptCanvas.X, pictureBox1.Height);
p.Dispose();
//绘制网格线
float nIncrement = (50 * m_nScale); //网格间的间隔 根据比例绘制
for (float x = m_ptCanvas.X; x > 0; x -= nIncrement)
g.DrawLine(Pens.Cyan, x, 0, x, pictureBox1.Height);
for (float x = m_ptCanvas.X; x < pictureBox1.Width; x += nIncrement)
g.DrawLine(Pens.Cyan, x, 0, x, pictureBox1.Height);
for (float y = m_ptCanvas.Y; y > 0; y -= nIncrement)
g.DrawLine(Pens.Cyan, 0, y, pictureBox1.Width, y);
for (float y = m_ptCanvas.Y; y < pictureBox1.Width; y += nIncrement)
g.DrawLine(Pens.Cyan, 0, y, pictureBox1.Width, y);
//计算屏幕左上角 和 右下角 对应画布上的坐标
Size szTemp = pictureBox1.Size - (Size)m_ptCanvas;
PointF ptCanvasOnShowRectLT = new PointF(
-m_ptCanvas.X / m_nScale, -m_ptCanvas.Y / m_nScale);
PointF ptCanvasOnShowRectRB = new PointF(
szTemp.Width / m_nScale, szTemp.Height / m_nScale);
//显示文字信息
string strDraw = "Scale: " + m_nScale.ToString("F1") +
"\nOrigin: " + m_ptCanvas.ToString() +
"\nLT: " + Point.Round(ptCanvasOnShowRectLT).ToString() +
"\nRB: " + Point.Round(ptCanvasOnShowRectRB).ToString() +
"\n" + ((Size)Point.Round(ptCanvasOnShowRectRB)
- (Size)Point.Round(ptCanvasOnShowRectLT)).ToString();
Size strSize = TextRenderer.MeasureText(strDraw, this.Font);
//绘制文字信息
SolidBrush sb = new SolidBrush(Color.FromArgb(125, 0, 0, 0));
g.FillRectangle(sb, 0, 0, strSize.Width, strSize.Height);
g.DrawString(strDraw, this.Font, Brushes.Yellow, 0, 0);
strSize = TextRenderer.MeasureText(m_strMousePt, this.Font);
g.FillRectangle(sb, pictureBox1.Width - strSize.Width, 0, strSize.Width, strSize.Height);
g.DrawString(m_strMousePt, this.Font, Brushes.Yellow, pictureBox1.Width - strSize.Width, 0);
sb.Dispose();
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Middle) { //如果中键点下 初始化计算要用的临时数据
m_ptMouseDown = e.Location;
m_ptCanvasBuf = m_ptCanvas;
}
pictureBox1.Focus();
}
//平移图像
private void pictureBox1_MouseMove(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Middle) { //移动过程中 中键点下 重置画布坐标系
//我总感觉这样写不妥 但却是方便计算 如果多次这样搞的话 还是重载操作符吧
m_ptCanvas = (Point)((Size)m_ptCanvasBuf + ((Size)e.Location - (Size)m_ptMouseDown));
pictureBox1.Invalidate();
}
//计算 右上角显示的坐标信息
SizeF szSub = (Size)e.Location - (Size)m_ptCanvas; //计算鼠标当前点对应画布中的坐标
szSub.Width /= m_nScale;
szSub.Height /= m_nScale;
Size sz = TextRenderer.MeasureText(m_strMousePt, this.Font); //获取上一次的区域并重绘
pictureBox1.Invalidate(new Rectangle(pictureBox1.Width - sz.Width, 0, sz.Width, sz.Height));
m_strMousePt = e.Location.ToString() + "\n" + ((Point)(szSub.ToSize())).ToString();
sz = TextRenderer.MeasureText(m_strMousePt, this.Font); //绘制新的区域
pictureBox1.Invalidate(new Rectangle(pictureBox1.Width - sz.Width, 0, sz.Width, sz.Height));
}
//缩放图像
private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) {
if (m_nScale <= 0.3 && e.Delta <= 0) return; //缩小下线
if (m_nScale >= 4.9 && e.Delta >= 0) return; //放大上线
//获取 当前点到画布坐标原点的距离
SizeF szSub = (Size)m_ptCanvas - (Size)e.Location;
//当前的距离差除以缩放比还原到未缩放长度
float tempX = szSub.Width / m_nScale; //这里
float tempY = szSub.Height / m_nScale; //将画布比例
//还原上一次的偏移 //按照当前缩放比还原到
m_ptCanvas.X -= (int)(szSub.Width - tempX); //没有缩放
m_ptCanvas.Y -= (int)(szSub.Height - tempY); //的状态
//重置距离差为 未缩放状态
szSub.Width = tempX;
szSub.Height = tempY;
m_nScale += e.Delta > 0 ? 0.2F : -0.2F;
//重新计算 缩放并 重置画布原点坐标
m_ptCanvas.X += (int)(szSub.Width * m_nScale - szSub.Width);
m_ptCanvas.Y += (int)(szSub.Height * m_nScale - szSub.Height);
pictureBox1.Invalidate();
}
}
}