1. 常用结构
1) Point:点坐标
2) Size:大小
3) Rectangle:包括位置与大小
Rectangle.Location:位置坐标
Rectangle.Size:大小
4) Pen:画笔
红色笔:Pens.Red,黑色笔:Pens.Black
其它的一次类推。
5) Brush:画刷
红色画刷:Brushes.Red 黑色画刷:Brushes.Black
其它以此类推。
2. 坐标变换
对象 |
屏幕坐标转化为客户区坐标 |
客户区坐标转化为屏幕坐标 |
Point |
PointToClinet(Point pt) |
PointToScreen(Point pt) |
Rectangle |
RectangleToClient |
RectangleToScreen |
涉及坐标的程序必须先考虑是否需要坐标变换
坐标平移:
X目标=X现在+dx
Y目标=Y现在+dy
坐标缩放:
X目标=X现在*dx
Y目标=Y现在*dy
坐标旋转:
X目标=X现在*Cos(α)+Y现在*Sin(α)
Y目标= X现在*Sin(α)+Y现在*Cos(α)
综合后
引入矩阵
综合后的公式可以写为
坐标变换会因为顺序的不同而产生不同的结果,多次坐标变换的结果是多个矩阵相乘。
右下角矩阵说明
X |
Y |
隐含列 |
Sx 缩放因子 |
Ry旋转因子 |
0 |
Rx旋转因子 |
sy缩放因子 |
0 |
Dx平移因子 |
Dy平移因子 |
1 |
图-1 原始矩阵
图-2 x轴平移100个像素
图-3 y轴平移100个像素
图-4 x轴放大1.5倍
图-5 y轴放大1.5倍
图-6 x轴旋转0.5
图-7 y轴旋转0.5
3. 鼠标事件
事件名称 |
说明 |
OnMouseUp |
鼠标松开 |
OnMouseDown |
鼠标按下 |
OnMouseMove |
鼠标移动 |
OnMouseEnter |
鼠标进入 |
OnMouseLeave |
鼠标离开 |
OnMouseHover |
鼠标停留。Hover事件至多在Enter与Leave之间发生一次 |
OnMouseCaptureChanged |
鼠标捕获变化,捕获发生一次,释放发生一次 |
4. 常见问题与解决方法
1) 如判断鼠标按下拖动
首先在鼠标的OnMouseMoveMove事件中添加如下判断:
if (e.Button == MouseButtons.Left)
{
//鼠标移动的过程中是否按下了左键
}
2) 如何避免鼠标按住旋转后划线后出现多条痕迹
在OnPaint事件中添加如下代码:
//划线之前先用背景色把原先的痕迹抹掉。
g.Clear(this.BackColor);
3) 鼠标的Capture事件
鼠标的捕获释放只能在一个控件中完成,前一个控件A捕获了鼠标后,不可能由下一个控件B捕获,必须是A释放了之后才能由B控件捕获。
假设在A控件上按住鼠标移动,鼠标移出A放在了B控件上。假设在B控件中的OnMouseHover中添加了代码弹出对话框,这样的对话框不会弹出,因为A捕获了鼠标,在A未释放之前,其他控件不可能激发鼠标相关的事件,除非其他控件捕获它之后,才可能激发它的事件。
附坐标变化程序代码:

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
namespace GDITransformApp
{
public partial class Transform1 : Form
{
public class MyMatrix
{
public float X
{
get;
set;
}
public float Y
{
get;
set;
}
public MyMatrix(float x, float y)
{
X = x;
Y = y;
}
}
#region Coordanate
//坐标轴X与控件边缘的距离
private const int xPad = 80;
//坐标轴Y与控件边缘的距离
private const int yPad = 60;
/// <summary>
/// X坐标标签间距
/// </summary>
private int coordinateLablePadX = 20;
public int CoordinateLablePadX
{
get
{
return coordinateLablePadX;
}
set
{
Invalidate();
coordinateLablePadX = value;
}
}
/// <summary>
/// Y坐标标签间距
/// </summary>
private int coordinateLablePadY = 30;
public int CoordinateLablePadY
{
get
{
return coordinateLablePadY;
}
set
{
Invalidate();
coordinateLablePadY = value;
}
}
/// <summary>
/// y坐标轴起点坐标
/// </summary>
public Point YCoordinateStartPoint
{
get
{
return new Point(xPad, this.Height - yPad);
}
}
/// <summary>
/// y坐标轴终点坐标
/// </summary>
public Point YCoordinateEndPoint
{
get
{
return new Point(xPad, yPad);
}
}
/// <summary>
/// x坐标轴起点坐标
/// </summary>
public Point XCoordinateStartPoint
{
get
{
return YCoordinateStartPoint;
}
}
/// <summary>
/// x坐标轴终点坐标
/// </summary>
public Point XCoordinateEndPoint
{
get
{
Point current = new Point();
current.X = Width - xPad;
current.Y = Height - yPad;
return current;
}
}
private void DrawCoordinate(PaintEventArgs e)
{
Pen currentPen = new Pen(Color.Black);
currentPen.EndCap = LineCap.ArrowAnchor;
//绘制Y轴
e.Graphics.DrawLine(
currentPen,
YCoordinateStartPoint,
YCoordinateEndPoint
);
//绘制Y轴
e.Graphics.DrawLine(
currentPen,
XCoordinateStartPoint,
XCoordinateEndPoint
);
currentPen.Dispose();
//绘制X,Y 标签
DrawCoordinateLabel(e.Graphics, YCoordinateStartPoint, YCoordinateEndPoint, XCoordinateStartPoint, XCoordinateEndPoint);
}
/// <summary>
/// 绘制坐标标记
/// </summary>
private void DrawCoordinateLabel(Graphics gp, Point startYPoint, Point endYPoint, Point startXPoint, Point endXPoint)
{
//int y = YCoordinateStartPoint .Y - YCoordinateEndPoint.Y;
int currentValue = -1;
float labelX = 0, labelY = 0;
int pad = 5;
//绘制Y轴
for (int current = YCoordinateStartPoint.Y; current > YCoordinateEndPoint.Y; current -= CoordinateLablePadY)
{
currentValue++;
SizeF textSize = gp.MeasureString(currentValue.ToString(), Font);
labelX = YCoordinateStartPoint.X - xPad / 2;
labelY = current - textSize.Height / 2;
//绘制label
gp.DrawString(currentValue.ToString(), Font, Brushes.Black,
new PointF(labelX, labelY)
);
//绘制|-
gp.DrawLine(Pens.Black, new Point(YCoordinateStartPoint.X, current), new Point(YCoordinateStartPoint.X + pad, current));
}
currentValue = -1;
//绘制X轴
for (int current = XCoordinateStartPoint.X; current < XCoordinateEndPoint.X; current += CoordinateLablePadX)
{
currentValue++;
SizeF textSize = gp.MeasureString(currentValue.ToString(), Font);
labelY = XCoordinateStartPoint.Y + yPad / 2;
labelX = current;
//绘制label
gp.DrawString(currentValue.ToString(), Font, Brushes.Black,
new PointF(labelX, labelY)
);
//绘制_|_
gp.DrawLine(Pens.Black,
new Point(current, XCoordinateStartPoint.Y),
new Point(current, XCoordinateStartPoint.Y - pad)
);
}
}
#endregion
float angle = 0f;
float scaleX = 1f;
float scaleY = 1f;
float translateX = 1f;
float translateY = 1f;
public Transform1()
{
InitializeComponent();
}
Matrix matrix = new Matrix();
List<MyMatrix> myList = new List<MyMatrix>();
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.Clear(this.BackColor);
DrawCoordinate(e);
DrawRectangle();
}
private void DrawRectangle()
{
using (Graphics gh = CreateGraphics())
{
Rectangle rect = new Rectangle(100, 100, 200, 200);
StringFormat sf=new StringFormat();
sf.Alignment=StringAlignment.Center ;
sf.LineAlignment=StringAlignment .Center ;
//平移
gh.TranslateTransform(translateX, translateY);
//旋转
gh.RotateTransform(angle);
//缩放
gh.ScaleTransform(scaleX, scaleY);
//设置gh的变换矩阵
gh.Transform = matrix;
gh.DrawRectangle(Pens.Red, rect);
gh.DrawString("AAAAAAAAA", this.Font, Brushes.Blue, rect, sf);
matrix = gh.Transform;
myList.Add(new MyMatrix(matrix.Elements[0], matrix.Elements[1]));
myList.Add(new MyMatrix(matrix.Elements[2], matrix.Elements[3]));
myList.Add(new MyMatrix(matrix.Elements[4], matrix.Elements[5]));
this.dgvMatrix.DataSource = myList;
}
}
private void button1_Click(object sender, EventArgs e)
{
angle += 10;
this.Invalidate();
}
private void btnScaleAdd_Click(object sender, EventArgs e)
{
scaleX += 1;
scaleY += 1;
this.Invalidate();
}
private void btnScaleSub_Click(object sender, EventArgs e)
{
scaleX -= 1;
scaleY -= 1;
this.Invalidate();
}
private void btnRolateSub_Click(object sender, EventArgs e)
{
angle -= 10;
this.Invalidate();
}
private void btnBack_Click(object sender, EventArgs e)
{
angle = 0f;
scaleX = 1f;
scaleY = 1f;
translateX = 0f;
translateY = 0f;
this.Invalidate();
}
private void btnTranslateAdd_Click(object sender, EventArgs e)
{
translateX += 3f;
translateY += 3f;
this.Invalidate();
}
private void btnTranslateSub_Click(object sender, EventArgs e)
{
translateX -= 5f;
translateY -= 5f;
this.Invalidate();
}
private void btnMatrixBack_Click(object sender, EventArgs e)
{
matrix = new Matrix
(
1,0,
0,1,
0,0
);
this.Invalidate();
}
private void button1_Click_1(object sender, EventArgs e)
{
matrix = new Matrix(
((MyMatrix)this.dgvMatrix.Rows[0].DataBoundItem).X, ((MyMatrix)this.dgvMatrix.Rows[0].DataBoundItem).Y ,
((MyMatrix)this.dgvMatrix.Rows[1].DataBoundItem).X, ((MyMatrix)this.dgvMatrix.Rows[1].DataBoundItem).Y ,
((MyMatrix)this.dgvMatrix.Rows[2].DataBoundItem).X, ((MyMatrix)this.dgvMatrix.Rows[2].DataBoundItem).Y
);
this.Invalidate();
}
}
}