局部刷新

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

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

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

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

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

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using RGeos.Geometry;
using System.Drawing.Imaging;

namespace RGeos.PluginEngine
{
    public partial class UcMapControl2 : UserControl, IRMapControl
    {
        private ITool mCurrentTool = null;

        public ITool CurrentTool
        {
            get { return mCurrentTool; }
            set { mCurrentTool = value; }
        }
        public REnvelope mExtent { get; set; }
        public Map mMap { get; set; }

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

        public PointF PanOffset
        {
            get { return m_panOffset; }
            set { m_panOffset = value; }
        }
        private PointF m_dragOffset = new PointF(0, 0);

        public PointF DragOffset
        {
            get { return m_dragOffset; }
            set { m_dragOffset = value; }
        }
        public UcMapControl2()
        {
            InitializeComponent();
            mMap = new Map();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
        }

        bool m_staticDirty = true;
        //缓存图片?
        Bitmap m_staticImage = null;
        System.Drawing.Drawing2D.SmoothingMode m_smoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;
        protected override void OnPaint(PaintEventArgs e)
        {
            Tracing.StartTrack(Program.TracePaint);
            #region old
            e.Graphics.SmoothingMode = m_smoothingMode;
            Rectangle cliprectangle = e.ClipRectangle;
            if (m_staticImage == null)
            {
                cliprectangle = ClientRectangle;
                m_staticImage = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
                //m_staticImage.Save("D:\\a.png", ImageFormat.Png);
                m_staticDirty = true;
            }
            //绘制在背景图片上
            Graphics BitMapGc = Graphics.FromImage(m_staticImage);
            BitMapGc.SmoothingMode = m_smoothingMode;
            //绘制背景,注意如果不设将为透明色
            BitMapGc.Clear(Color.White);
            //this.BackgroundLayer.Draw(dcStatic, r);
            //if (m_model.GridLayer.Enabled)
            //    m_model.GridLayer.Draw(dcStatic, r);
            //绘制十字丝
            RPoint rCenterPoint = new RPoint(0, 0, 0);
            PointF nullPoint = Transform.ToScreen(rCenterPoint, this);
            BitMapGc.DrawLine(Pens.Blue, nullPoint.X - 10, nullPoint.Y, nullPoint.X + 10, nullPoint.Y);
            BitMapGc.DrawLine(Pens.Blue, nullPoint.X, nullPoint.Y - 10, nullPoint.X, nullPoint.Y + 10);
            if (m_staticDirty)
            {
                m_staticDirty = false;

                List<ILayer> layers = mMap.Layers;
                for (int layerindex = layers.Count - 1; layerindex >= 0; layerindex--)
                {
                    //if (layers[layerindex].Visible)
                    //layers[layerindex].Draw();
                }
                BitMapGc.Dispose();
            }
            //绘制背景图片
            e.Graphics.DrawImage(m_staticImage, cliprectangle, cliprectangle, GraphicsUnit.Pixel);
            //绘制新建对象
            //if (m_newObject != null)
            //    m_newObject.Draw(dc, r);
            #endregion
            Tracing.EndTrack(Program.TracePaint, "OnPaint complete");

        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            if (m_lastCenterPoint != null && Width != 0)
                SetCenterScreen(Transform.ToScreen(m_lastCenterPoint, this), false);
            m_lastCenterPoint = CenterPointUnit();
            m_staticImage = null;
            Invalidate();
        }
        RPoint m_lastCenterPoint;
        /// <summary>
        /// 设置画布到屏幕的中心
        /// </summary>
        /// <param name="rPoint">直角坐标系坐标</param>
        public void SetCenter(RPoint unitPoint)
        {
            PointF point = Transform.ToScreen(unitPoint, this);
            m_lastCenterPoint = unitPoint;
            SetCenterScreen(point, false);
        }

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

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

            if (setCursor)
                Cursor.Position = this.PointToScreen(new Point((int)centerX, (int)centerY));
            Invalidate();
        }
        public RPoint CenterPointUnit()
        {
            RPoint p1 = Transform.ToUnit(new PointF(0, 0), this);
            RPoint p2 = Transform.ToUnit(new PointF(this.ClientRectangle.Width, this.ClientRectangle.Height), this);
            RPoint center = new RPoint();
            center.X = (p1.X + p2.X) / 2;
            center.Y = (p1.Y + p2.Y) / 2;
            return center;
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

        }
        int n = 0;
        PointF p1;
        PointF TempPoint2;//缓存移动过程中产生的第二个点,上一移动过程中
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            Rectangle invalidaterect = Rectangle.Empty;
            if (n < 1)
            {

            }
            else
            {
                //REnvelope env = mNewLine.GetBoundingBox();
                //mNewLine.P1 = new RPoint(e.X, e.Y, 0);

                double xmin = Math.Min(p1.X, TempPoint2.X);
                double ymin = Math.Min(p1.Y, TempPoint2.Y);
                double w = Math.Abs(p1.X - TempPoint2.X);
                double h = Math.Abs(p1.Y - TempPoint2.Y);
                invalidaterect = new Rectangle((int)xmin, (int)ymin, (int)w, (int)h);
                invalidaterect.Inflate(2, 2);

                Pen pen = new Pen(Color.Red);
                //擦除上次移动绘制的线,通过重绘上次移动范围区域的缓存图片实现
                RepaintStatic(invalidaterect);
                //Bitmap m_staticImage2 = new Bitmap(invalidaterect.Width, invalidaterect.Height);
                //m_staticImage2.Save("D:\\adfghj.png", ImageFormat.Png);
                pen.EndCap = System.Drawing.Drawing2D.LineCap.Round;
                pen.StartCap = System.Drawing.Drawing2D.LineCap.Round;
                Graphics dc = Graphics.FromHwnd(Handle);
                dc.SmoothingMode = m_smoothingMode;
                Point p2 = new Point(e.X, e.Y);
                dc.DrawLine(pen, p1, p2);
                dc.Dispose();
                TempPoint2 = p2;
                //Invalidate();
                //DoInvalidate(false, invalidaterect);

            }
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            n++;
            if (n <= 1)
            {
                //mNewLine = new RSegment();
                //mNewLine.P0 = new RPoint(e.X, e.Y, 0);
                //mNewLine.P1 = new RPoint();
                //初始化两个点,注意此处两点相同。
                p1 = new PointF(e.X, e.Y);
                TempPoint2 = new Point(e.X, e.Y);
                Invalidate(true);
            }
            base.OnMouseDown(e);
        }
        public void DoInvalidate(bool dostatic, Rectangle rect)
        {
            if (dostatic)
                m_staticDirty = true;
            Invalidate(rect);
        }
        /// <summary>
        /// 局部刷新,重新绘制图片Bitmap无效区域
        /// </summary>
        /// <param name="r"></param>
        public void RepaintStatic(Rectangle r)
        {
            if (m_staticImage == null)
                return;
            Graphics dc = Graphics.FromHwnd(Handle);
            if (r.X < 0) r.X = 0;
            if (r.X > m_staticImage.Width) r.X = 0;
            if (r.Y < 0) r.Y = 0;
            if (r.Y > m_staticImage.Height) r.Y = 0;

            if (r.Width > m_staticImage.Width || r.Width < 0)
                r.Width = m_staticImage.Width;
            if (r.Height > m_staticImage.Height || r.Height < 0)
                r.Height = m_staticImage.Height;
            dc.DrawImage(m_staticImage, r, r, GraphicsUnit.Pixel);
            Image temp = new Bitmap(m_staticImage);
            Graphics gc = Graphics.FromImage(temp);
            gc.DrawLine(Pens.Blue, r.Location, new Point(r.Location.X + r.Width, r.Location.Y + r.Height));
            gc.Dispose();
            temp.Save("d:\\AAAA.png", ImageFormat.Png);
            m_staticImage.Save("d:\\BBBB.png", ImageFormat.Png);
            dc.Dispose();
        }
        public float ScreenHeight()
        {
            return (float)(Transform.ToUnit(this.ClientRectangle.Height, this as IRMapControl));
        }
        private float mZoom = 1.0f;
        public float Zoom
        {
            get
            {
                return mZoom;
            }
            set
            {
                mZoom = value;
            }
        }
    }
}

UcMapControl2


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太一吾鱼水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值