Winform GDI+ 绘图
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();
}
}
}
转载于:https://www.cnblogs.com/hbb0b0/archive/2011/01/07/1929880.html
Winform GDI+ 绘图相关推荐
- C# Winform GDI+ 绘图
目录 一.概述 二.绘图 1.画直线 2.画矩形 3.画圆.圆弧 4.画扇形 5.画多边形 6.绘制字符串 7.填充图形 结束 一.概述 Graphics类是GDI+技术的一个基本类.GDI+(Gra ...
- Winform GDI+
什么是GDI+ GDI (Graphics Device Interface), 是属于绘图方面的 API (Application Programming Interface). 因为应用程序不能直 ...
- GDI+绘图基础,绘制表格
GDI+绘图基础 编写图形程序时需要使用GDI(图形设备接口Graphics Device Interface),从程序设计的角度看,GDI包括两个部分:GDI对象和GDI函数. GDI对象定义了GD ...
- GDI+绘图轻松入门[5]-绘图坐标的理解和应用
我们都知道,有大约五种方式可以获得一个坐标位置,他们分别是new point.PointToClient.PointToScreen,Location及控件鼠标事件传递的坐标.为了了解绘图坐标,我们事 ...
- 使用bitblt提高GDI+绘图的效率(转)
最近在做使用GDI+绘制K线界面发现传统的GDI+绘制方式效率比较低,根本无法满足K线界面及时刷新的速度要求. 所以做了个GDI+绘制图形界面的试验,改试验主要在一个600×600的区域内每隔10MS ...
- cimage和gdi绘图效率比较_GDI+和GDI绘图性能对比实验
龙源期刊网 http://www.qikan.com.cn GDI+ 和 GDI 绘图性能对比实验 作者:王克茹 来源:<科技创新与应用> 2013 年第 25 期 摘 要:本文通过完全相 ...
- MFC中的GDI绘图
MFC中的GDI绘图 目录(?)[+] 什么是GDI 什么是DC MFC中与GDI有关的类 获取设备环境 设置坐标映射 创建绘图工具并选入DC 调用DC绘图函数绘图 三坐标映射实例 一.关于GDI的基 ...
- GDIDrawing3——GDI+绘图(三)
1using System; 2using System.Drawing; 3using System.Collections; 4using System.ComponentModel; ...
- MFC GDI绘图基础
一.关于GDI的基本概念 什么是GDI? Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上. 在Wind ...
最新文章
- 零基础掌握极大似然估计
- Http协议中的数据传送之多重表单提交--multipart/form-data
- ElementUI中的el-form怎样格式化显示1和0为是和否
- 完美完全卸载Oracle 11g数据库
- mpu 配置内存空间_PCIE的内存地址空间、I/O地址空间和配置地址空间
- mysql与文件_MySQL——文件
- 程序员,互联网创业者,忠言逆耳,希望创业者们慎重,三思而后行。
- centos 6.5 yum mysql 5.6_centos 6.5 yum安装 mysql 5.6
- 用Python写脚本:通过ssh在Windows下批量管理Linux
- http报文格式_(一)深入浅出TCPIP之理解TCP报文格式和交互流程
- MATLAB卷积运算(conv)
- 神州数码交换机CS6200命令(信息安全管理与评估赛项)
- C++图像缩放(StretchBlt,StretchDIBits,双线性内插法)
- 【可穿戴技术】相关资料
- 【观察】打造智能决策“新引擎”,杉数科技勇闯“无人区”
- Web应用程序测试工具Top20
- C#常见错误—未将对象引用设置到对象的实例
- 写给女朋友的3D旋转相册
- 无线传感器网络:定位、安全与同步
- Java-01_语言概述
热门文章
- pads元件类型如何修改_pads logic元件库修改了,怎样更新到原理图
- 程序员curd编程是什么_为什么许多程序员讨厌结对编程?
- mysql新建用户只能查看试图_Sql Server:创建用户并指定该用户只能看指定的视图,除此之外的都不让查看。...
- 爬虫-通过正则表达式爬取学校选课网站的课程
- 2020护网参考学习 关于护网行动的总结
- 渗透测试入门26之给你一个网站你是如何来渗透测试的?
- linux mysql temp 设置_linux怎么修改mysql数据库临时表空间大小
- 小汤学编程之JavaEE学习day05——会话管理、文件上传与下载、Ajax
- Swift编码总结8
- 杭电 1248 寒冰王座(全然背包)