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

  参考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(, -); public PointF PanOffset
{
get { return m_panOffset; }
set { m_panOffset = value; }
}
private PointF m_dragOffset = new PointF(, ); 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(, , );
PointF nullPoint = Transform.ToScreen(rCenterPoint, this);
BitMapGc.DrawLine(Pens.Blue, nullPoint.X - , nullPoint.Y, nullPoint.X + , nullPoint.Y);
BitMapGc.DrawLine(Pens.Blue, nullPoint.X, nullPoint.Y - , nullPoint.X, nullPoint.Y + );
if (m_staticDirty)
{
m_staticDirty = false; List<ILayer> layers = mMap.Layers;
for (int layerindex = layers.Count - ; layerindex >= ; 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 != )
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 / ;
m_panOffset.X += centerX - screenPoint.X; float centerY = ClientRectangle.Height / ;
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(, ), this);
RPoint p2 = Transform.ToUnit(new PointF(this.ClientRectangle.Width, this.ClientRectangle.Height), this);
RPoint center = new RPoint();
center.X = (p1.X + p2.X) / ;
center.Y = (p1.Y + p2.Y) / ;
return center;
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e); }
int n = ;
PointF p1;
PointF TempPoint2;//缓存移动过程中产生的第二个点,上一移动过程中
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e); Rectangle invalidaterect = Rectangle.Empty;
if (n < )
{ }
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(, ); 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 <= )
{
//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 < ) r.X = ;
if (r.X > m_staticImage.Width) r.X = ;
if (r.Y < ) r.Y = ;
if (r.Y > m_staticImage.Height) r.Y = ; if (r.Width > m_staticImage.Width || r.Width < )
r.Width = m_staticImage.Width;
if (r.Height > m_staticImage.Height || r.Height < )
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

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

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

DIY自己的GIS程序(2)——局部刷新的更多相关文章

  1. DIY自己的GIS程序(1)——起航

    一个GIS系统最重要的功能是绘制图形和关联属性,这里研究二维点线面的绘制过程: 对于一个绘图系统设计,图形的绘制涉及两个重要的方面. 1.一个是绘制或者重新绘制,重绘过程出现在下面情况: a 界面初始 ...

  2. 微信小程序setData局部刷新列表

    利用setData局部刷新列表 当列表管理加载到第几页时,这个list的数据有十几条的,如果重新setData的话就要重新刷新和渲染列表, 这是个比较麻烦的事,当数据量大时,就会造成白屏, 这时就要局 ...

  3. ArcGIS engine中Display类库 (局部刷新)

    转自原文 ArcGIS engine中Display类库 (局部刷新) Display类库包括了用于显示GIS数据的对象.除了负责实际输出图像的主要显示对象(display object)外,这个类库 ...

  4. MVC无刷新分页(即局部刷新,带搜索,页数选择,排序功能)

    我查看了很多网站,大部分评论分页都是局部刷新的,可大部分电商商品展示分页都是有刷新页面的,于是我便做了一个商品展示无刷新分页的例子.接下来我就将做一个模仿淘宝已买到的宝贝功能,不过我的是无刷新分页的. ...

  5. android:ListView的局部刷新

    1.简介 对于android中的ListView刷新机制,大多数的程序员都是很熟悉的,修改或者添加adapter中的数据源之后,然后调用notifyDataSetChanged()刷新ListView ...

  6. Android 结合实际项目学会ListView局部刷新和相关知识《一》

    转载本专栏博客,请注明出处:道龙的博客 最近在公司参与的项目中有一个界面需要做局部UI更新处理,把其化烦为简为Demoi形式写在这里.我们还是运行该Demo,知道ListView局部刷新的使用场景:( ...

  7. .net updatePannel 局部刷新效果实现后,但是仍是全部刷新的修改方法

    最近做了一个小例子,就是晚上都有的那种小的updatepannel的局部刷新的小例子,但是发现按照那个例子虽然能够实现label2的局部刷新,但是看上去效果确实整个页面都在刷新,这让人很头疼,所以我在 ...

  8. 转:android listview局部刷新和模拟应用下载

    在 android开发中,listview是比较常用的一个组件,在listview的数据需要更新的时候,一般会用 notifyDataSetChanged()这个函数,但是它会更新listview中所 ...

  9. 安卓易学,爬坑不易——腾讯老司机的RecyclerView局部刷新爬坑之路

    针对手游的性能优化,腾讯WeTest平台的Cube工具提供了基本所有相关指标的检测,为手游进行最高效和准确的测试服务,不断改善玩家的体验.目前功能还在免费开放中. 点击地址:http://wetest ...

随机推荐

  1. 学习 TList 类的实现[1]

    最近整理了一些函数列表, 算是一个宏观的安排; 等以后再碰到一些函数时就可以放置的更有次序一些. 我对函数与类的理解是: 函数是一个功能模块, 类是一个更强大的功能模块; Delphi 已经提供了很多 ...

  2. Oracle 11gR2 11.2.0.1 ( 11.2.0.1的BUG?):ohasd不能正常启动:ioctl操作:npohasd的问题:【chmod a+wr /var/tmp/.oracle/npohasd】

    问题1:执行安装,编译成功后,执行asmca时,失败,无法成功创建后台相关服务 问题2:os系统重启后,ohasd无法正常启动,css服务失败 原因:11.2.0.1的BUG:/var/tmp/.or ...

  3. 使用matlab批量处理图像后在指定文件夹存储

    使用matlab批量处理图像后在指定文件夹存储 clear;clc;close all; Files=dir('D:\文件及下载相关\文档\MATLAB\postgraduate\Kodak\*.jp ...

  4. CSS定位背景图片 background-position

    网站的样式的时候经常会发现一种情况,就是在很多background属性里都调用同一张图片,来满足网页各个部分的使用.打开这种图片看一下,会发现这张图片上包含了很多小图片; 又如: 这些小图片就是整图分 ...

  5. module、applet

    Each Module is developed as a standalone Windows DLL.Each module can contain one or more applets, an ...

  6. Appium - WebView測试(Android)

    Appium - WebView測试 作者: Max.Bai 时间: 2015/07 Appium - WebView測试(Android) 如今App都是混合型的.有原生的也包括WebView的,a ...

  7. 如何根据select选择的值反查option的属性

    有时候select已经被选中了,想知道这个选中option的属性又该如何处理呢? 我这里提供一种粗暴的方式 <!DOCTYPE HTML> <html lang="en-U ...

  8. python2.0_day18_django_admin

    Django admin的个性化定制首先我们看下,前面章节中定义的models在admin后台管理界面的样子: 然后我们看下老男孩教育点名平台的admin管理表的后台界面样子: admin管理后台常用 ...

  9. python2.0 s12 day3

    s12 day3 视频每节的内容 03 python s12 day3 本节内容概要 第三天的主要内容 上节没讲完的: 6.集合 7.collections 1)计数器 2)有序字典 3)默认字典 4 ...

  10. Python2 与 Python3 区别

    print 用法不同:在 Python2 中,print 用法为 print "Hello World"在 Python3 中,print 用法为 print("Hell ...