关于绘制图形,吹一下小牛皮

你一看标题,肯定会想:靠!太菜了。是啊,很菜,简直菜歪歪了。自从被某些人封为“高手”起,我就丧失了当小白的机会,更别说当菜鸟了。其实,成为一名小白没有什么不好,是吧?无知无欲,人生更多欢乐,知得越多越痛苦,真的是这样,因为很多人总是知道他本不应该知道的东西,所以他们就活得很痛苦。

有一位挚友不知道做了什么春梦,突然找到我说,他要写一个绘图程序。我说:“拿系统的画图程序来玩就行了,不够爽的话,就玩PS嘛。”他眼睛睁大了三倍地叫着:“自己写出来才爽。”

是啊,其实他这句话灰常有道理。于是,他就开始扯了,说如何做到,鼠标,按下、拖动、弹起这一过程中在窗口上画出一个矩形。其实并不难吧,我相信很多人都会了。就是在鼠标按下的时候,记录其起点,然后鼠标移动,在鼠标弹起时记录终点,两个点,起点为左上角,终点为右下角,就能画出矩形了。

是的,这就成了,于是他就开始写程序,表面上是做到了,但是,如果用户在操作时,起点的坐标比终点的坐标的值要小,哈哈,就画不出来了。按照他的逻辑,通常终点应当位于起点的右下角,所以他就这样做了,但是,他并没有考虑到,我在鼠标操作的时候,并不一定是往右下方移动鼠标,我有可能是从右下角往左上方移动鼠标,这时候你得考虑矩形的左上顶点和右下顶点应该取哪些坐标了。

情况有四种——终点在起点右下方,这是最好处理的;终点在起点的右上方;终点在起点的左上方;终点在起点的左下方。

         

 

           

 

再看看椭圆。

            

 

             

 

通过以上的“看图识字”,挚友忽然有所悟。是的,别小看实现用鼠标画矩形这一功能,其中还有不少学问,另外我们还要考虑鼠标坐标的起点和终点相同的情况,因为我们是不能画出长和宽都等于0的矩形。矩形的问题如果解决了,那么,画椭圆也可以解决了,原理是一样的。

于是,我这个演示代码中用一个变量来表示绘图类型,0表示画矩形,1表示画椭圆,2表示画扇形。

[csharp]  view plain  copy
 
  1. public partial class Form1 : Form  
  2. {  
  3.     bool isDown = false;  
  4.     Point startPoint;  
  5.     Rectangle rect;  
  6.   
  7.     // 绘制类型,0表示画矩形,1表示画椭圆,2表示扇形  
  8.     byte DrawType = 0;  


isDown指示鼠标左键是否按下,在鼠标的Down和Up事件中分别设置它的值。在鼠标的Move事件中确定矩形的左上顶点和右下顶点。

[csharp]  view plain  copy
 
  1. void Form1_MouseMove(object sender, MouseEventArgs e)  
  2. {  
  3.     if (isDown == false) return;  
  4.     Point tmpPt = new Point(e.X, e.Y);  
  5.     Point TopLeftPoint, BottomRightPoint;  
  6.     if (tmpPt.X > startPoint.X && tmpPt.Y > startPoint.Y)//终点在起点的右下角  
  7.     {  
  8.         TopLeftPoint = new Point(startPoint.X, startPoint.Y);  
  9.         BottomRightPoint = new Point(tmpPt.X, tmpPt.Y);  
  10.     }  
  11.     else if (tmpPt.X > startPoint.X && tmpPt.Y < startPoint.Y)//终点在起点的右上角  
  12.     {  
  13.         TopLeftPoint = new Point(startPoint.X, tmpPt.Y);  
  14.         BottomRightPoint = new Point(tmpPt.X, startPoint.Y);  
  15.     }  
  16.     else if (tmpPt.X < startPoint.X && tmpPt.Y < startPoint.Y)//终点在起点的左上角  
  17.     {  
  18.         TopLeftPoint = new Point(tmpPt.X, tmpPt.Y);  
  19.         BottomRightPoint = new Point(startPoint.X, startPoint.Y);  
  20.     }  
  21.     else if (tmpPt.X < startPoint.X && tmpPt.Y > startPoint.Y)//终点在起点的左下角  
  22.     {  
  23.         TopLeftPoint = new Point(tmpPt.X, startPoint.Y);  
  24.         BottomRightPoint = new Point(startPoint.X, tmpPt.Y);  
  25.     }  
  26.     else  
  27.     {  
  28.         TopLeftPoint = startPoint;  
  29.         BottomRightPoint = new Point(TopLeftPoint.X + 1, TopLeftPoint.Y + 1);  
  30.     }  
  31.     rect = new Rectangle(TopLeftPoint.X, TopLeftPoint.Y, BottomRightPoint.X - TopLeftPoint.X, BottomRightPoint.Y - TopLeftPoint.Y);  
  32.     this.Invalidate();  
  33. }  
  34.   
  35. void Form1_MouseUp(object sender, MouseEventArgs e)  
  36. {  
  37.     if (e.Button == System.Windows.Forms.MouseButtons.Left)  
  38.     {  
  39.         isDown = false;  
  40.         this.Invalidate();  
  41.     }  
  42. }  
  43.   
  44. void Form1_MouseDown(object sender, MouseEventArgs e)  
  45. {  
  46.     if (e.Button == System.Windows.Forms.MouseButtons.Left)  
  47.     {  
  48.         isDown = true;  
  49.         startPoint = new Point(e.X, e.Y);  
  50.     }  
  51. }  


this.Invalidate方法调用强制窗口发生重绘,为了能够随着鼠标移动而动态显示图形,所以在坐标点变化后要刷新窗口,除了Invalidate方法外,还可以用Refresh方法。

最后就是Paint事件,要根据左上点和右下点进行绘制。

[csharp]  view plain  copy
 
  1. private void Form1_Paint(object sender, PaintEventArgs e)  
  2. {  
  3.     Graphics g = e.Graphics;  
  4.     g.Clear(SystemColors.Control);  
  5.     Pen myPen = new Pen(Color.Red, 2f);  
  6.     switch (DrawType)  
  7.     {  
  8.         case 0:  
  9.             g.DrawRectangle(myPen, rect);  
  10.             break;  
  11.         case 1:  
  12.             g.DrawEllipse(myPen, rect);  
  13.             break;  
  14.         case 2:  
  15.             g.DrawPie(myPen, rect, 0f, 90f);  
  16.             break;  
  17.     }  
  18.     myPen.Dispose();  
  19. }  


转载于:https://www.cnblogs.com/weekbo/p/8682053.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值