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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值