DIY自己的GIS程序(2)——局部刷新

  • 绘制线过移动鼠标程中绘制临时线段防闪烁

  参考OpenS-CAD想实现绘制线的功能。希望实现绘制线的过程,在移动线的时候没有闪烁和花屏。但是出现了问题,困扰了2天,前天熬的太晚,搞得现在精力都没有恢复。现在终于把问题搞清楚了:

  第一个问题:没有给背景图片赋颜色,此时相当于透明。所以每次将图片局部范围重绘产生严重的花屏,绘制的线段残留在屏幕上,将透明的东西绘制是不可能将移动过程中产生的临时线段擦除的。

  第二个问题:用当前移动产生的线段包围盒来重绘,其实在本次鼠标移动过程中,应该将上次产生的残留擦除,用上次的包围盒局部重绘。

  以下是自己写的一个控件的雏形:

 1 using System;  2 using System.Collections.Generic;  3 using System.Drawing;  4 using System.Windows.Forms;  5 using RGeos.Geometry;  6 using System.Drawing.Imaging;  7 

 8 namespace RGeos.PluginEngine  9 {  10     public partial class UcMapControl2 : UserControl, IRMapControl  11  {  12         private ITool mCurrentTool = null;  13 

 14         public ITool CurrentTool  15  {  16             get { return mCurrentTool; }  17             set { mCurrentTool = value; }  18  }  19         public REnvelope mExtent { get; set; }  20         public Map mMap { get; set; }  21 

 22         private PointF m_panOffset = new PointF(25, -25);  23 

 24         public PointF PanOffset  25  {  26             get { return m_panOffset; }  27             set { m_panOffset = value; }  28  }  29         private PointF m_dragOffset = new PointF(0, 0);  30 

 31         public PointF DragOffset  32  {  33             get { return m_dragOffset; }  34             set { m_dragOffset = value; }  35  }  36         public UcMapControl2()  37  {  38  InitializeComponent();  39             mMap = new Map();  40             this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);  41             this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);  42  }  43 

 44         bool m_staticDirty = true;  45         //缓存图片?

 46         Bitmap m_staticImage = null;  47         System.Drawing.Drawing2D.SmoothingMode m_smoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;  48         protected override void OnPaint(PaintEventArgs e)  49  {  50  Tracing.StartTrack(Program.TracePaint);  51             #region old

 52             e.Graphics.SmoothingMode = m_smoothingMode;  53             Rectangle cliprectangle = e.ClipRectangle;  54             if (m_staticImage == null)  55  {  56                 cliprectangle = ClientRectangle;  57                 m_staticImage = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);  58                 //m_staticImage.Save("D:\\a.png", ImageFormat.Png);

 59                 m_staticDirty = true;  60  }  61             //绘制在背景图片上

 62             Graphics BitMapGc = Graphics.FromImage(m_staticImage);  63             BitMapGc.SmoothingMode = m_smoothingMode;  64             //绘制背景,注意如果不设将为透明色

 65  BitMapGc.Clear(Color.White);  66             //this.BackgroundLayer.Draw(dcStatic, r);  67             //if (m_model.GridLayer.Enabled)  68             // m_model.GridLayer.Draw(dcStatic, r);  69             //绘制十字丝

 70             RPoint rCenterPoint = new RPoint(0, 0, 0);  71             PointF nullPoint = Transform.ToScreen(rCenterPoint, this);  72             BitMapGc.DrawLine(Pens.Blue, nullPoint.X - 10, nullPoint.Y, nullPoint.X + 10, nullPoint.Y);  73             BitMapGc.DrawLine(Pens.Blue, nullPoint.X, nullPoint.Y - 10, nullPoint.X, nullPoint.Y + 10);  74             if (m_staticDirty)  75  {  76                 m_staticDirty = false;  77 

 78                 List<ILayer> layers = mMap.Layers;  79                 for (int layerindex = layers.Count - 1; layerindex >= 0; layerindex--)  80  {  81                     //if (layers[layerindex].Visible)  82                     //layers[layerindex].Draw();

 83  }  84  BitMapGc.Dispose();  85  }  86             //绘制背景图片

 87  e.Graphics.DrawImage(m_staticImage, cliprectangle, cliprectangle, GraphicsUnit.Pixel);  88             //绘制新建对象  89             //if (m_newObject != null)  90             // m_newObject.Draw(dc, r);

 91             #endregion

 92             Tracing.EndTrack(Program.TracePaint, "OnPaint complete");  93 

 94  }  95 

 96         protected override void OnResize(EventArgs e)  97  {  98             base.OnResize(e);  99             if (m_lastCenterPoint != null && Width != 0) 100                 SetCenterScreen(Transform.ToScreen(m_lastCenterPoint, this), false); 101             m_lastCenterPoint = CenterPointUnit(); 102             m_staticImage = null; 103  Invalidate(); 104  } 105  RPoint m_lastCenterPoint; 106         /// <summary>

107         /// 设置画布到屏幕的中心 108         /// </summary>

109         /// <param name="rPoint">直角坐标系坐标</param>

110         public void SetCenter(RPoint unitPoint) 111  { 112             PointF point = Transform.ToScreen(unitPoint, this); 113             m_lastCenterPoint = unitPoint; 114             SetCenterScreen(point, false); 115  } 116 

117         protected void SetCenterScreen(PointF screenPoint, bool setCursor) 118  { 119             float centerX = ClientRectangle.Width / 2; 120             m_panOffset.X += centerX - screenPoint.X; 121 

122             float centerY = ClientRectangle.Height / 2; 123             m_panOffset.Y += centerY - screenPoint.Y; 124 

125             if (setCursor) 126                 Cursor.Position = this.PointToScreen(new Point((int)centerX, (int)centerY)); 127  Invalidate(); 128  } 129         public RPoint CenterPointUnit() 130  { 131             RPoint p1 = Transform.ToUnit(new PointF(0, 0), this); 132             RPoint p2 = Transform.ToUnit(new PointF(this.ClientRectangle.Width, this.ClientRectangle.Height), this); 133             RPoint center = new RPoint(); 134             center.X = (p1.X + p2.X) / 2; 135             center.Y = (p1.Y + p2.Y) / 2; 136             return center; 137  } 138         protected override void OnMouseUp(MouseEventArgs e) 139  { 140             base.OnMouseUp(e); 141 

142  } 143         int n = 0; 144  PointF p1; 145         PointF TempPoint2;//缓存移动过程中产生的第二个点,上一移动过程中

146         protected override void OnMouseMove(MouseEventArgs e) 147  { 148             base.OnMouseMove(e); 149 

150             Rectangle invalidaterect = Rectangle.Empty; 151             if (n < 1) 152  { 153 

154  } 155             else

156  { 157                 //REnvelope env = mNewLine.GetBoundingBox(); 158                 //mNewLine.P1 = new RPoint(e.X, e.Y, 0);

159 

160                 double xmin = Math.Min(p1.X, TempPoint2.X); 161                 double ymin = Math.Min(p1.Y, TempPoint2.Y); 162                 double w = Math.Abs(p1.X - TempPoint2.X); 163                 double h = Math.Abs(p1.Y - TempPoint2.Y); 164                 invalidaterect = new Rectangle((int)xmin, (int)ymin, (int)w, (int)h); 165                 invalidaterect.Inflate(2, 2); 166 

167                 Pen pen = new Pen(Color.Red); 168                 //擦除上次移动绘制的线,通过重绘上次移动范围区域的缓存图片实现

169  RepaintStatic(invalidaterect); 170                 //Bitmap m_staticImage2 = new Bitmap(invalidaterect.Width, invalidaterect.Height); 171                 //m_staticImage2.Save("D:\\adfghj.png", ImageFormat.Png);

172                 pen.EndCap = System.Drawing.Drawing2D.LineCap.Round; 173                 pen.StartCap = System.Drawing.Drawing2D.LineCap.Round; 174                 Graphics dc = Graphics.FromHwnd(Handle); 175                 dc.SmoothingMode = m_smoothingMode; 176                 Point p2 = new Point(e.X, e.Y); 177  dc.DrawLine(pen, p1, p2); 178  dc.Dispose(); 179                 TempPoint2 = p2; 180                 //Invalidate(); 181                 //DoInvalidate(false, invalidaterect);

182 

183  } 184  } 185         protected override void OnMouseDown(MouseEventArgs e) 186  { 187             n++; 188             if (n <= 1) 189  { 190                 //mNewLine = new RSegment(); 191                 //mNewLine.P0 = new RPoint(e.X, e.Y, 0); 192                 //mNewLine.P1 = new RPoint(); 193                 //初始化两个点,注意此处两点相同。

194                 p1 = new PointF(e.X, e.Y); 195                 TempPoint2 = new Point(e.X, e.Y); 196                 Invalidate(true); 197  } 198             base.OnMouseDown(e); 199  } 200         public void DoInvalidate(bool dostatic, Rectangle rect) 201  { 202             if (dostatic) 203                 m_staticDirty = true; 204  Invalidate(rect); 205  } 206         /// <summary>

207         /// 局部刷新,重新绘制图片Bitmap无效区域 208         /// </summary>

209         /// <param name="r"></param>

210         public void RepaintStatic(Rectangle r) 211  { 212             if (m_staticImage == null) 213                 return; 214             Graphics dc = Graphics.FromHwnd(Handle); 215             if (r.X < 0) r.X = 0; 216             if (r.X > m_staticImage.Width) r.X = 0; 217             if (r.Y < 0) r.Y = 0; 218             if (r.Y > m_staticImage.Height) r.Y = 0; 219 

220             if (r.Width > m_staticImage.Width || r.Width < 0) 221                 r.Width = m_staticImage.Width; 222             if (r.Height > m_staticImage.Height || r.Height < 0) 223                 r.Height = m_staticImage.Height; 224  dc.DrawImage(m_staticImage, r, r, GraphicsUnit.Pixel); 225             Image temp = new Bitmap(m_staticImage); 226             Graphics gc = Graphics.FromImage(temp); 227             gc.DrawLine(Pens.Blue, r.Location, new Point(r.Location.X + r.Width, r.Location.Y + r.Height)); 228  gc.Dispose(); 229             temp.Save("d:\\AAAA.png", ImageFormat.Png); 230             m_staticImage.Save("d:\\BBBB.png", ImageFormat.Png); 231  dc.Dispose(); 232  } 233         public float ScreenHeight() 234  { 235             return (float)(Transform.ToUnit(this.ClientRectangle.Height, this as IRMapControl)); 236  } 237         private float mZoom = 1.0f; 238         public float Zoom 239  { 240             get

241  { 242                 return mZoom; 243  } 244             set

245  { 246                 mZoom = value; 247  } 248  } 249  } 250 }
UcMapControl2

   今年的一个目标:完成一个开源项目

  参考:http://www.codeproject.com/Articles/6238/Canvas-implementation-for-C

你可能感兴趣的:(局部刷新)