ArcGis+C#重写鼠标滚轮事件

ArcGis+C#二次开发过程中重写鼠标滚轮事件,实现地图缩放功能,但在缩小的时候会出现地图闪烁的情况不知道怎么解决

private void axMapControl_OnMouseWheel(object sender, MouseEventArgs e)
        {
            double scale = axMapControl.MapScale;
            IEnvelope mEnvelope = null;
            IPoint mPoint = new PointClass();
            //IPoint mousePoint = null;
            mEnvelope = axMapControl.ActiveView.Extent;
            mPoint.X = (mEnvelope.XMax + mEnvelope.XMin) / 2;
            mPoint.Y = (mEnvelope.YMax + mEnvelope.YMin) / 2;
            mousePoint = axMapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.X, e.Y);
            double moveDisX = mousePoint.X - (mEnvelope.XMax + mEnvelope.XMin) / 2;
            double moveDisY = mousePoint.Y - (mEnvelope.YMax + mEnvelope.YMin) / 2;
            mEnvelope.CenterAt(mousePoint);
            if (e.Delta > 0)
            {
                mEnvelope.Width = mEnvelope.Width * 0.8;
                mEnvelope.Height = mEnvelope.Height * 0.8;
                mPoint.X = mousePoint.X - moveDisX * 0.8;
                mPoint.Y = mousePoint.Y - moveDisY * 0.8;

                mEnvelope.CenterAt(mPoint);
                axMapControl.ActiveView.Extent = mEnvelope;
                axMapControl.ActiveView.Refresh();
            }
            else if (e.Delta < 0)
            {
                //if(scale>=SystemConfig.DefaultBMapScale)
                if(scale>=SystemConfig.DefaultTMapScale)
                //if (scale >= 1900000)
                {
                    mPoint.X = mousePoint.X - moveDisX;
                    mPoint.Y = mousePoint.Y - moveDisY;
                    //MapMouseUp();
                }
                else
                {
                    mEnvelope.Width = mEnvelope.Width * 1.25;
                    mEnvelope.Height = mEnvelope.Height * 1.25;
                    mPoint.X = mousePoint.X - moveDisX * 1.25;
                    mPoint.Y = mousePoint.Y - moveDisY * 1.25;

                    //mEnvelope.CenterAt(mPoint);
                    axMapControl.ActiveView.Extent = mEnvelope;
                    //axMapControl.ActiveView.Refresh();
                }
                MapMouseUp();
            }
        }

在代码中,地图闪烁的情况可能是因为在执行缩小操作时,地图的刷新不够及时,导致视觉效果出现了不连续的情况。为了解决这个问题,可以尝试对代码进行改进,如下所示:

  1. 在进行缩小操作时,先将地图的可见范围保存下来。

  2. 对地图进行缩放操作之前,调用 IMapControl2.SuppressResizeDrawing 方法,暂时禁止地图控件的绘制。

  3. 对地图进行缩放操作之后,调用 IMapControl2.Refresh 方法,手动刷新地图控件。

以下是修改后的代码:

private void axMapControl_OnMouseWheel(object sender, MouseEventArgs e)
{
    double scale = axMapControl.MapScale;
    IEnvelope mEnvelope = null;
    IPoint mPoint = new PointClass();
    mEnvelope = axMapControl.ActiveView.Extent;
    mPoint.X = (mEnvelope.XMax + mEnvelope.XMin) / 2;
    mPoint.Y = (mEnvelope.YMax + mEnvelope.YMin) / 2;
    IPoint mousePoint = axMapControl.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(e.X, e.Y);
    double moveDisX = mousePoint.X - (mEnvelope.XMax + mEnvelope.XMin) / 2;
    double moveDisY = mousePoint.Y - (mEnvelope.YMax + mEnvelope.YMin) / 2;
    mEnvelope.CenterAt(mousePoint);
    if (e.Delta > 0)
    {
        mEnvelope.Width = mEnvelope.Width * 0.8;
        mEnvelope.Height = mEnvelope.Height * 0.8;
        mPoint.X = mousePoint.X - moveDisX * 0.8;
        mPoint.Y = mousePoint.Y - moveDisY * 0.8;
        mEnvelope.CenterAt(mPoint);
    }
    else if (e.Delta < 0)
    {
        if(scale >= SystemConfig.DefaultTMapScale)
        {
            mPoint.X = mousePoint.X - moveDisX;
            mPoint.Y = mousePoint.Y - moveDisY;
        }
        else
        {
            mEnvelope.Width = mEnvelope.Width * 1.25;
            mEnvelope.Height = mEnvelope.Height * 1.25;
            mPoint.X = mousePoint.X - moveDisX * 1.25;
            mPoint.Y = mousePoint.Y - moveDisY * 1.25;
        }
    }

    // 调用 IMapControl2 接口实现缩放操作
    IMapControl2 mapControl2 = (IMapControl2)axMapControl.Object;
    mapControl2.SuppressResizeDrawing(true);  // 禁止绘制
    axMapControl.ActiveView.Extent = mEnvelope;  // 进行缩放操作
    mapControl2.SuppressResizeDrawing(false);  // 恢复绘制
    axMapControl.ActiveView.Refresh();  // 手动刷新
}

在修改后的代码中,我们使用了 IMapControl2 接口的 SuppressResizeDrawing 方法来实现暂时禁止绘制和恢复绘制的功能。在进行缩放操作时,首先调用 SuppressResizeDrawing 方法禁止绘制,然后进行缩放操作,最后再调用 Refresh 方法手动刷新地图控件。这样就可以避免在缩小操作时出现地图闪烁的情况。

这种地图闪烁的现象通常是由于多次刷新地图导致的。可以尝试将地图的显示模式设置为双缓冲模式,并且在缩小地图的代码块中屏蔽掉一些不必要的刷新操作,以减少地图闪烁的问题。

具体的步骤如下:

  1. 在axMapControl_OnMouseDown中添加以下代码:

     //启用地图双缓冲模式
     ((IMapControl4)axMapControl.Object).UseBufferedDisplay = true;
     //开始缓存地图刷新操作
     axMapControl.ActiveView.ScreenDisplay.StartDrawing(0, (short)esriScreenCache.esriNoScreenCache);
    
  2. 在axMapControl_OnMouseWheel事件的else if (e.Delta < 0)代码块中将地图刷新操作注释掉,只在需要刷新的时候刷新:

     if(scale>=SystemConfig.DefaultTMapScale)
     {
         // do nothing
     }
     else
     {
         mEnvelope.Width = mEnvelope.Width * 1.25;
         mEnvelope.Height = mEnvelope.Height * 1.25;
         mPoint.X = mousePoint.X - moveDisX * 1.25;
         mPoint.Y = mousePoint.Y - moveDisY * 1.25;
         axMapControl.ActiveView.Extent = mEnvelope;
             
         //仅在需要刷新的时候刷新
         if (this.isNeedRefresh == true)
         {
             this.isNeedRefresh = false;
             axMapControl.ActiveView.Refresh();
         }
     }
    
  3. 在axMapControl_OnMouseWheel事件的code block之后增加如下代码:

     //停止地图缓存刷新操作
     axMapControl.ActiveView.ScreenDisplay.FinishDrawing();
    

这样做可以避免多余的地图重绘,提高地图显示效率,同时降低地图刷新导致的闪烁现象。

Form的构造函数里加上这段就行了

            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.DoubleBuffer, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            base.DoubleBuffered = true;
            UpdateStyles();