1. 程式人生 > >關於繪制圖形,吹一下小牛皮

關於繪制圖形,吹一下小牛皮

ews 分享圖片 eve send 小白 自己 mda tails .net

你一看標題,肯定會想:靠!太菜了。是啊,很菜,簡直菜歪歪了。自從被某些人封為“高手”起,我就喪失了當小白的機會,更別說當菜鳥了。其實,成為一名小白沒有什麽不好,是吧?無知無欲,人生更多歡樂,知得越多越痛苦,真的是這樣,因為很多人總是知道他本不應該知道的東西,所以他們就活得很痛苦。

有一位摯友不知道做了什麽春夢,突然找到我說,他要寫一個繪圖程序。我說:“拿系統的畫圖程序來玩就行了,不夠爽的話,就玩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. // 繪制類型,0表示畫矩形,1表示畫橢圓,2表示扇形
  7. 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. void Form1_MouseUp(object sender, MouseEventArgs e)
  35. {
  36. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  37. {
  38. isDown = false;
  39. this.Invalidate();
  40. }
  41. }
  42. void Form1_MouseDown(object sender, MouseEventArgs e)
  43. {
  44. if (e.Button == System.Windows.Forms.MouseButtons.Left)
  45. {
  46. isDown = true;
  47. startPoint = new Point(e.X, e.Y);
  48. }
  49. }


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. }


技術分享圖片

關於繪制圖形,吹一下小牛皮