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的图,放大或缩小一次要好久,不能忍受,用虚拟画布有什么好处啊?

解决方案 »

  1.   


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

  2.   

    //base.OnPaint(e);//这句屏蔽看看
    已经屏蔽,无效用双缓冲
    form_load中
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
    没有作用,还需要做什么设置吗?
      

  3.   

    只有窗体在重新绘制的时候才会调用OnPaint方法里的代码来绘制,如果当前没有任何一个消息能引发Paint的消息,那么OnPaint方法是不会执行的,当鼠标移动的时候可能会引发重绘的消息,所以才被重绘了.你可以通过Invalidate方法来立刻要求窗体绘制而不用等鼠标事件.
      

  4.   

    当鼠标移动的时候可能会引发重绘的消息
    _______________________________________
    我把地图放大,然后用一个窗体a挡住它,再移开a,这个时候应该引发Paint了吧,可现象依旧.
    图大的话,应该创建缩略图
    __________________________
    我现在是在窗体上放了一个picturebox,image指向地图,sizemode设置为stretchimage,还需要创建缩略图吗?多次测试后发现,窗体改变大小后,先是显示正确的放大倍数,然后变成初始大小,我鼠标移动一下又变成正确的放大倍数.是不是我在设计阶段将picturebox的sizemode设置为stretchimage,所以他强制将其恢复成初始大小?
      

  5.   

    我刚才新建了一个项目,在窗体上加了个picturebox ,什么都没设置
    代码中
    private void Form1_Paint(object sender, PaintEventArgs e)
            {
                Graphics g = pictureBox1.CreateGraphics();
                Image  bmp = Image.FromFile(@"G:\地图处理\地图缩放\bin\Debug\map\ditu.jpg");
                g.DrawImage(bmp, 0, 0, pictureBox1.Width, pictureBox1.Height);
                g.Dispose();        }
    运行程序后一开始有图片,很快就消失了,将代码放在重载的OnPaint中也是一样的,跟我的问题现象中的前半部分一样
      

  6.   

    看过一个例子,是在内存上创建graphics对象,但那个例子没看懂,也没调试成功,如果在内存中创建是否能解决我的问题?速度是否能提高?
      

  7.   

    to Ctoyun
    你可能还没搞懂csdn的分数机制,专家分和可用分不是一回事
      

  8.   

    问题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);
      

  9.   

    谢谢coollzt
    图片的大小问题已经解决了,的确是要放在pictureBox1_Paint中,而且我的g定义的也有问题.另外还想请教一下,在放大状态下,我在地图上单击一下,获得放大后图片左上角的坐标以及图片大小,我应该在mousedown中执行                           
    g.DrawImage(bmp, xx, yy, pictureBox1.Width * (currentZoom + ZoomRate), pictureBox1.Height * (currentZoom + ZoomRate));
    还是直接 pictureBox1.Refresh();让控件重画?那种效率高一点?
      

  10.   

    用直接 pictureBox1.Refresh();因为用mousedown可以会刷两次