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;
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+ 绘图相关推荐

  1. C# Winform GDI+ 绘图

    目录 一.概述 二.绘图 1.画直线 2.画矩形 3.画圆.圆弧 4.画扇形 5.画多边形 6.绘制字符串 7.填充图形 结束 一.概述 Graphics类是GDI+技术的一个基本类.GDI+(Gra ...

  2. Winform GDI+

    什么是GDI+ GDI (Graphics Device Interface), 是属于绘图方面的 API (Application Programming Interface). 因为应用程序不能直 ...

  3. GDI+绘图基础,绘制表格

    GDI+绘图基础 编写图形程序时需要使用GDI(图形设备接口Graphics Device Interface),从程序设计的角度看,GDI包括两个部分:GDI对象和GDI函数. GDI对象定义了GD ...

  4. GDI+绘图轻松入门[5]-绘图坐标的理解和应用

    我们都知道,有大约五种方式可以获得一个坐标位置,他们分别是new point.PointToClient.PointToScreen,Location及控件鼠标事件传递的坐标.为了了解绘图坐标,我们事 ...

  5. 使用bitblt提高GDI+绘图的效率(转)

    最近在做使用GDI+绘制K线界面发现传统的GDI+绘制方式效率比较低,根本无法满足K线界面及时刷新的速度要求. 所以做了个GDI+绘制图形界面的试验,改试验主要在一个600×600的区域内每隔10MS ...

  6. cimage和gdi绘图效率比较_GDI+和GDI绘图性能对比实验

    龙源期刊网 http://www.qikan.com.cn GDI+ 和 GDI 绘图性能对比实验 作者:王克茹 来源:<科技创新与应用> 2013 年第 25 期 摘 要:本文通过完全相 ...

  7. MFC中的GDI绘图

    MFC中的GDI绘图 目录(?)[+] 什么是GDI 什么是DC MFC中与GDI有关的类 获取设备环境 设置坐标映射 创建绘图工具并选入DC 调用DC绘图函数绘图 三坐标映射实例 一.关于GDI的基 ...

  8. GDIDrawing3——GDI+绘图(三)

     1using System;  2using System.Drawing;  3using System.Collections;  4using System.ComponentModel;   ...

  9. MFC GDI绘图基础

    一.关于GDI的基本概念 什么是GDI? Windows绘图的实质就是利用Windows提供的图形设备接口GDI(Graphics Device Interface)将图形绘制在显示器上. 在Wind ...

最新文章

  1. 零基础掌握极大似然估计
  2. Http协议中的数据传送之多重表单提交--multipart/form-data
  3. ElementUI中的el-form怎样格式化显示1和0为是和否
  4. 完美完全卸载Oracle 11g数据库
  5. mpu 配置内存空间_PCIE的内存地址空间、I/O地址空间和配置地址空间
  6. mysql与文件_MySQL——文件
  7. 程序员,互联网创业者,忠言逆耳,希望创业者们慎重,三思而后行。
  8. centos 6.5 yum mysql 5.6_centos 6.5 yum安装 mysql 5.6
  9. 用Python写脚本:通过ssh在Windows下批量管理Linux
  10. http报文格式_(一)深入浅出TCPIP之理解TCP报文格式和交互流程
  11. MATLAB卷积运算(conv)
  12. 神州数码交换机CS6200命令(信息安全管理与评估赛项)
  13. C++图像缩放(StretchBlt,StretchDIBits,双线性内插法)
  14. 【可穿戴技术】相关资料
  15. 【观察】打造智能决策“新引擎”,杉数科技勇闯“无人区”
  16. Web应用程序测试工具Top20
  17. C#常见错误—未将对象引用设置到对象的实例
  18. 写给女朋友的3D旋转相册
  19. 无线传感器网络:定位、安全与同步
  20. Java-01_语言概述

热门文章

  1. pads元件类型如何修改_pads logic元件库修改了,怎样更新到原理图
  2. 程序员curd编程是什么_为什么许多程序员讨厌结对编程?
  3. mysql新建用户只能查看试图_Sql Server:创建用户并指定该用户只能看指定的视图,除此之外的都不让查看。...
  4. 爬虫-通过正则表达式爬取学校选课网站的课程
  5. 2020护网参考学习 关于护网行动的总结
  6. 渗透测试入门26之给你一个网站你是如何来渗透测试的?
  7. linux mysql temp 设置_linux怎么修改mysql数据库临时表空间大小
  8. 小汤学编程之JavaEE学习day05——会话管理、文件上传与下载、Ajax
  9. Swift编码总结8
  10. 杭电 1248 寒冰王座(全然背包)