GMap.NET开发技巧(三)-如何拖拽地图图元和图标

2012年10月7日 分类: GPS系统

GMap.NET上的地标图元的拖拽其实很简单,思路和正常的WInform控件拖拽是一样的,无非是在鼠标事件当中,记录下操作的状态,通过mapcontrol的Invalidate刷新重绘整个画布,造成一种拖拽的效果。

以下代码,以拖拽一个多边形Polygon图元为例。

增加一个变量IsMouseOverPolygon,表示鼠标经过多边形。

 

PointLatLng lastDragPolygon = PointLatLng.Empty; // 保存上一次鼠标的坐标位置。

Cursor cursorDragBefore = Cursors.Default;  //上一次鼠标的位置.

List<GMapPolygon> movingPolygons = new List<GMapPolygon>();

 

 

GMap.NET.WindowsForms.GMapControl.OnMouseDown:

 

protected override void OnMouseDown(MouseEventArgs e)
      {
         if(!IsMouseOverMarker && (!CanDragPolygon || !IsMouseOverPolygon))//如果不能拖拽图元,就拖拽整个地图,这样不会因为拖拽图元影响拖拽地图的操作。
         {
#if !PocketPC
            if(e.Button == DragButton && CanDragMap)
#else
            if (CanDragMap)
#endif
            {
#if !PocketPC
               Core.mouseDown = ApplyRotationInversion(e.X, e.Y);
#else
               Core.mouseDown = new GPoint(e.X, e.Y);
#endif
               this.Invalidate();
            }
            else if(!isSelected && !DisableSelectArea)
            {
               isSelected = true;
               SelectedArea = RectLatLng.Empty;
               selectionEnd = PointLatLng.Empty;
               selectionStart = FromLocalToLatLng(e.X, e.Y);
            }
         }
         else if ( CanDragPolygon && IsMouseOverPolygon )//确定可以拖拽的条件
         {
             lastDragPolygon = FromLocalToLatLng(e.X, e.Y);//标记开始拖拽的起始点

             cursorDragBefore = this.Cursor;//保存光标位置
             this.Cursor = Cursors.SizeAll;//改变形状

         }

         base.OnMouseDown(e);
      }
 

GMap.NET.WindowsForms.GMapControl.OnMouseUp:

 

protected override void OnMouseUp(MouseEventArgs e)
      {
         base.OnMouseUp(e);

         if(isSelected)
         {
            isSelected = false;
         }
         //clans every polygon used variable to maintain normal behaviour
         if ( !lastDragPolygon.IsEmpty )
         {
             lastDragPolygon = PointLatLng.Empty;

             this.Cursor = cursorDragBefore;

             movingPolygons.Clear();
         }

         if(Core.IsDragging)
         {
            if(isDragging)
            {
               isDragging = false;
               Debug.WriteLine("IsDragging = " + isDragging);
#if !PocketPC
               this.Cursor = cursorBefore;
               cursorBefore = null;
#endif
            }
            Core.EndDrag();

            if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
            {
               if(Core.LastLocationInBounds.HasValue)
               {
                  Position = Core.LastLocationInBounds.Value;
               }
            }
         }
         else
         {
#if !PocketPC
            if(e.Button == DragButton)
            {
               Core.mouseDown = GPoint.Empty;
            }

            if(!selectionEnd.IsEmpty && !selectionStart.IsEmpty)
            {
               if(!SelectedArea.IsEmpty && Form.ModifierKeys == Keys.Shift)
               {
                  SetZoomToFitRect(SelectedArea);
               }
            }
            else
            {
               Invalidate();
            }
#endif
         }
      }
 

GMap.NET.WindowsForms.GMapControl.OnMouseMove:

 

protected override void OnMouseMove(MouseEventArgs e)
      {
         if(!Core.IsDragging && !Core.mouseDown.IsEmpty && lastDragPolygon.IsEmpty) //let drag the map if the lastPolygon wasn't set
         {

                GPoint p = new GPoint(e.X, e.Y);
            if(Math.Abs(p.X - Core.mouseDown.X) * 2 >= DragSize.Width || Math.Abs(p.Y - Core.mouseDown.Y) * 2 >= DragSize.Height)
            {
               Core.BeginDrag(Core.mouseDown);
            }
         }
         else if ( !lastDragPolygon.IsEmpty )
         {
             //就开始添加鼠标经过的多边形
             if(movingPolygons.Count == 0)
             {
                  //
                  foreach (GMapOverlay layer in Overlays)
                  {
                      //and through the polygons
                      foreach ( GMapPolygon poly in layer.Polygons )
                      {
                          if ( poly.IsMouseOver )
                          {
                              movingPolygons.Add( poly );
                          }
                      }
                  }
             }
                       
             //
             PointLatLng mouse = FromLocalToLatLng( e.X, e.Y );
             List<PointLatLng> points;

             //循环要移动的多边形
             foreach ( GMapPolygon poly in movingPolygons )
             {
                 //保存多边形的坐标点
                 points = new List<PointLatLng>( poly.Points );
                 //clears the original, so we can put new values to them
                 poly.Points.Clear();

                 //and chage every point
                 foreach (PointLatLng point in points)
	             {
                     //移动图元到当前的位置
                     point.Offset( -(mouse.Lat - lastDragPolygon.Lat), mouse.Lng - lastDragPolygon.Lng );
                     poly.Points.Add( point );
	             }

                 //更新多边形的位置
                 this.UpdatePolygonLocalPosition( poly );
             }

             lastDragPolygon = mouse;

             base.Invalidate();
         }

         if(Core.IsDragging)
         {
            if(!isDragging)
            {
               isDragging = true;
               Debug.WriteLine("IsDragging = " + isDragging);

#if !PocketPC
               cursorBefore = this.Cursor;
               this.Cursor = Cursors.SizeAll;
#endif
            }

            if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
            {
               // ...
            }
            else
            {
#if !PocketPC
               Core.mouseCurrent = ApplyRotationInversion(e.X, e.Y);
#else
                    Core.mouseCurrent = new GPoint(e.X, e.Y);
#endif
               Core.Drag(Core.mouseCurrent);

#if !PocketPC
               if(MobileMode)
               {
                  ForceUpdateOverlays();
               }
#else
                    ForceUpdateOverlays();
#endif

               base.Invalidate();
            }
         }
         else
         {
#if !PocketPC
            if(isSelected && !selectionStart.IsEmpty && (Form.ModifierKeys == Keys.Alt || Form.ModifierKeys == Keys.Shift || DisableAltForSelection))
            {
               selectionEnd = FromLocalToLatLng(e.X, e.Y);
               {
                  GMap.NET.PointLatLng p1 = selectionStart;
                  GMap.NET.PointLatLng p2 = selectionEnd;

                  double x1 = Math.Min(p1.Lng, p2.Lng);
                  double y1 = Math.Max(p1.Lat, p2.Lat);
                  double x2 = Math.Max(p1.Lng, p2.Lng);
                  double y2 = Math.Min(p1.Lat, p2.Lat);

                  SelectedArea = new RectLatLng(y1, x1, x2 - x1, y1 - y2);
               }
            }
            else
#endif
               if(Core.mouseDown.IsEmpty)
               {
                  for(int i = Overlays.Count - 1; i >= 0; i--)
                  {
                     GMapOverlay o = Overlays[i];
                     if(o != null && o.IsVisibile)
                     {
                        foreach(GMapMarker m in o.Markers)
                        {
                           if(m.IsVisible && m.IsHitTestVisible)
                           {
                              #region -- check --
#if !PocketPC
                              if((MobileMode && m.LocalArea.Contains(e.X, e.Y)) || (!MobileMode && m.LocalAreaInControlSpace.Contains(e.X, e.Y)))
#else
                                    if (m.LocalArea.Contains(e.X, e.Y))
#endif
                              {
                                 if(!m.IsMouseOver)
                                 {
#if !PocketPC
                                    cursorBefore = this.Cursor;
                                    this.Cursor = Cursors.Hand;
#endif
                                    m.IsMouseOver = true;

                                    if(OnMarkerEnter != null)
                                    {
                                       OnMarkerEnter(m);
                                    }

                                    Invalidate();
                                 }
                              }
                              else if(m.IsMouseOver)
                              {
#if !PocketPC
                                 this.Cursor = this.cursorBefore;
                                 cursorBefore = null;
#endif
                                 m.IsMouseOver = false;

                                 if(OnMarkerLeave != null)
                                 {
                                    OnMarkerLeave(m);
                                 }

                                 Invalidate();
                              }
                              #endregion
                           }
                        }

#if !PocketPC
                        foreach(GMapRoute m in o.Routes)
                        {
                           if(m.IsVisible && m.IsHitTestVisible)
                           {
                              #region -- check --

                              GPoint rp = new GPoint(e.X, e.Y);
#if !PocketPC
                              if(!MobileMode)
                              {
                                 rp.OffsetNegative(Core.renderOffset);
                              }
#endif
                              if(m.IsInside((int)rp.X, (int)rp.Y))
                              {
                                 if(!m.IsMouseOver)
                                 {
#if !PocketPC
                                    cursorBefore = this.Cursor;
                                    this.Cursor = Cursors.Hand;
#endif
                                    m.IsMouseOver = true;

                                    if(OnRouteEnter != null)
                                    {
                                       OnRouteEnter(m);
                                    }

                                    Invalidate();
                                 }
                              }
                              else
                              {
                                 if(m.IsMouseOver)
                                 {
#if !PocketPC
                                    this.Cursor = this.cursorBefore;
                                    cursorBefore = null;
#endif
                                    m.IsMouseOver = false;

                                    if(OnRouteLeave != null)
                                    {
                                       OnRouteLeave(m);
                                    }

                                    Invalidate();
                                 }
                              }
                              #endregion
                           }
                        }
#endif
                        //移除踪迹
                        IsMouseOverPolygon = false;

                        foreach(GMapPolygon m in o.Polygons)
                        {
                           if(m.IsVisible && (m.IsHitTestVisible || CanDragPolygon)) //check when I can drag the polygon too
                           {
                              #region -- check --
                              if(m.IsInside(FromLocalToLatLng(e.X, e.Y)))
                              {
                                 //keep the value that there are polygons under mouse pointer
                                 IsMouseOverPolygon = true;
                                 if(!m.IsMouseOver)
                                 {
                                     m.IsMouseOver = true;
                                     if ( m.IsHitTestVisible ) //only fires event if it IsHitTestVisible
                                     {
#if !PocketPC
                                        cursorBefore = this.Cursor;
                                        this.Cursor = Cursors.Hand;
#endif

                                        if ( OnPolygonEnter != null )
                                        {
                                            OnPolygonEnter( m );
                                        }
                                    }
                                    Invalidate();
                                 }
                              }
                              else
                              {
                                 if(m.IsMouseOver)
                                 {
                                     m.IsMouseOver = false;
                                     if ( m.IsHitTestVisible ) //触发点击事件
                                     {
#if !PocketPC
                                         this.Cursor = this.cursorBefore;
                                         cursorBefore = null;
#endif
                                         if ( OnPolygonLeave != null )
                                         {
                                             OnPolygonLeave( m );
                                         }
                                     }
                                    Invalidate();
                                 }
                              }
                              #endregion
                           }
                        }
                     }
                  }
               }
         }
         base.OnMouseMove(e);
      }
 

(19107)

标签:

7 条评论 于 “GMap.NET开发技巧(三)-如何拖拽地图图元和图标”

  1. 猪猪
    2012年10月8日14:16
    1

    最近在做一个GPS监控程序,但是发现用了Gmap.net 控件后,出现了位置偏移,不知道怎么解决啊!拜托了,给个解决方案!!

    • admin
      2012年10月8日15:06
      2

      你使用的GPS设备的发送的坐标,需要对坐标通过算法做纠偏,最近正在做一个纠偏插件,过两天就在网站上发布出来。

  2. 猪猪
    2012年10月8日15:35
    3

    谢了,你的那套算法是不是还要调用google服务器啊?

  3. 猪猪
    2012年10月8日15:36
    4

    调用google的API啊,因为我是个C/s架构的程序,不能上外网啊

    • admin
      2012年10月8日17:46
      5

      不能上外网?那你怎么接收GPS数据?

  4. MJingle
    2013年12月10日08:55
    6

    how can I login in ? I need to load the source code .Thanks!

  5. 寂寞成双
    2014年4月28日09:20
    7

    这张图是我的项目中的,呵呵!
    我是同行,不过现在技术上做的少,事务上多了。看了你的网站,相当专业,相当有帮助,当时要是认识你,一起交流,开发就轻松多了。我当时搞服务器端和客户端也是从没搞过,从0开始的,后来全搞通了费了不少精力!

猪猪