日期:2014-05-19  浏览次数:21540 次

C#画图,用虚拟画布太慢,用onPaint重绘时不正常
picturebox加载图片作为地图,图片比较大,目前使用的是1M左右的图.
用   DrawImage已经实现了放大缩小功能,但每次放大或者缩小后,一改变窗体大小,图片就恢复成初始大小了,我重载了onpaint
      protected   override   void   OnPaint(PaintEventArgs   e)
                {
                        g.DrawImage(pictureBox1.Image,   p1,   p2,   p3,   p4);
                        base.OnPaint(e);
                }
可每次重绘后还是初始大小,需要移动一下鼠标才能正常

看资料g.DrawImage后需要g.dispose();
可我dispose后在onpaint中就出问题了,必须重新实例化一下g
  g   =   pictureBox1.CreateGraphics();
每次都要实例化g吗?

试过用虚拟画布,窗体改变大小时到是可以重绘,但实在是太慢了,我内存比较小,256的,处理1M的图,放大或缩小一次要好久,不能忍受,用虚拟画布有什么好处啊?



------解决方案--------------------

protected override void OnPaint(PaintEventArgs e)
{
g.DrawImage(pictureBox1.Image, p1, p2, p3, p4);
//base.OnPaint(e);//这句屏蔽看看
}

------解决方案--------------------
因为你的图片太大,所以应该用双缓冲
------解决方案--------------------
只有窗体在重新绘制的时候才会调用OnPaint方法里的代码来绘制,

如果当前没有任何一个消息能引发Paint的消息,那么OnPaint方法是不会执行的,

当鼠标移动的时候可能会引发重绘的消息,所以才被重绘了.

你可以通过Invalidate方法来立刻要求窗体绘制而不用等鼠标事件.

------解决方案--------------------
我虽然没有回答您的问题,但也帮您顶了下,求您给小女几分好吗?我非专业,但需要点分提问啊!
呵呵,谢谢!!
------解决方案--------------------
问题1:可每次重绘后还是初始大小,需要移动一下鼠标才能正常这个问题应该是没有使用
    SizeChange这个事件。 应该在这个事件加入重绘事件。加上
    SetStyle(ControlStyles.ResizeRedraw, true);或 SizeChanged+=delegate
    {Invalidate();}
问题2:这个感觉你说的不是很清楚。 不知道你这个Form与 Picture之间是什么关系。
    如果Picture.Dock==DockStyle.Fill. 你根本不用重写Form1的OnPaint属性。
    只要添加pictureBox1_Paint事件这可以了。
    Image bmp = Image.FromFile(@ "G:\地图处理\地图缩放
    \bin\Debug\map\ditu.jpg ");
    这句不能加在pictureBox1_Paint这个事件里, 因为它只要程序启动时读一次就行
    了。而pictureBox1_Paint 这个事件是要经常被调用的。
    Bitmap bmp=null;
     private void Form1_Load(object sender, EventArgs e)
{

       bmp = Image.FromFile(@ "G:\地图处理\地图缩放\bin\Debug\map\ditu.jpg ");
}

     private void pictureBox1_Paint(object sender, PaintEventArgs e)
{

       Graphics g = e.Graphics;
       g.DrawImage(bmp, 0, 0, pictureBox1.Width, pictureBox1.Height);
}
问题3:虚拟画布的问题。虚拟画布是指在内存中定义好一个位图,图形做什么操作先在虚拟画    布上进行,最后再一次性地DrawImage, 它更适合有变化频繁的图形的程序, 而且    这个图形都是很小的, 至少在你的这个项目中,它 并不适用, 反而会影响图形显
    示的速度。
建议 :使用双缓冲。在构造函数中加入
SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true);
------解决方案--------------------
用直接 pictureBox1.Refresh();因为用mousedown可以会刷两次
------解决方案--------------------
双缓冲是最好的方法,以前做的东西也是用双缓冲解决这个问题的
序列化可以直接以二进制实现绘图,而且是可以是 矢量图,是个好方法
不过我没有做成过,所以惭愧下。