首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > VB Dotnet >

快速移动Picturebox中的大图像,该怎么解决

2012-02-22 
快速移动Picturebox中的大图像PictureBox.Image加载的图像比较大(有好几兆呢),现在我想通过使用鼠标在Pict

快速移动Picturebox中的大图像
PictureBox.Image加载的图像比较大(有好几兆呢),现在我想通过使用鼠标在Picturebox.MouseMove中移动该图像,使之显示我要看到的部分,该如何实现呢?

以下是我的方法,但是移动起来没有平滑的效果。

Public   Class   Form1

        Dim   offset   As   Size
        Dim   MousePressPoint   As   Point
        Dim   bmp   As   Image   =   Image.FromFile( "C:\Documents   and   Settings\Administrator\桌面\Test\route.gif ")

        Private   Sub   PictureBox1_MouseDown(ByVal   sender   As   Object,   ByVal   e   As   System.Windows.Forms.MouseEventArgs)   Handles   PictureBox1.MouseDown
                MousePressPoint   =   e.Location
        End   Sub

        Private   Sub   PictureBox1_MouseMove(ByVal   sender   As   Object,   ByVal   e   As   System.Windows.Forms.MouseEventArgs)   Handles   PictureBox1.MouseMove
                If   e.Button   =   Windows.Forms.MouseButtons.Left   Then
                        Windows.Forms.Cursor.Current   =   Cursors.Hand

                        offset.Width   +=   e.X   -   MousePressPoint.X
                        offset.Height   +=   e.Y   -   MousePressPoint.Y

                        MousePressPoint   =   e.Location

                        PictureBox1.Refresh()
                End   If
        End   Sub

        Private   Sub   PictureBox1_Paint(ByVal   sender   As   Object,   ByVal   e   As   System.Windows.Forms.PaintEventArgs)   Handles   PictureBox1.Paint
                e.Graphics.DrawImage(bmp,   PictureBox1.ClientRectangle,   -offset.Width,   -offset.Height,   PictureBox1.ClientSize.Width,   PictureBox1.ClientSize.Height,   GraphicsUnit.Pixel)
        End   Sub
End   Class


[解决办法]
不使用PictureBox显示图片,而使用可以滚动的控件,比如Panel,有代码参考如下:

(我的意思是说使用滚动条来滚动图像而暂不使用鼠标移动)
Image img = Image.FromFile(fileName);

private void button1_Click(object sender, EventArgs e)
{
this.panel1.AutoScrollMinSize = img.Size;
this.panel1.Paint += new PaintEventHandler(panel1_Paint);
this.panel1.Invalidate();
}

void panel1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(img, this.panel1.AutoScrollPosition.X, this.panel1.AutoScrollPosition.Y, this.panel1.AutoScrollMinSize.Width, this.panel1.AutoScrollMinSize.Height);
}

[解决办法]
放一个Panel,里面放一个PictureBox,PictureBox设置图片,设置显示模式是AutoSize这样Picture就很大了。这个控件大,Panel设置AutoScroll等于true。试试这样?
[解决办法]
using System;
using System.Collections.Generic;
using System.ComponentModel;


using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication6
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.pictureBox1.Left += e.X - x;
this.pictureBox1.Top += e.Y - y;

}
}

private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{

}
private int x = 0;
private int y = 0;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
x = e.X;
y = e.Y;
}
}
}


我觉得速度还是能接受的啊。没有像楼主说的那么慢。
[解决办法]
不可以先把图像加载到内存中,再从内存中把图片放到PICTUREBOX中,每次移到都只对内存中的图像进行移到.移到过后再放到PICTUREBOX中.应该就不会有所谓的闪烁了吧
[解决办法]
整理过的代码:

Dim bmp As Bitmap
Dim bmpg As Graphics
Dim IsDown As Boolean
Dim xStartPos As Integer
Dim yStartPos As Integer
Dim xEndPos As Integer
Dim yEndPos As Integer
Dim xtran As Integer
Dim ytran As Integer
Dim old_xtran As Integer
Dim old_ytran As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
bmp = New Bitmap(Image.FromFile(( "D:\My_Picture\111\1422929138.jpg ")))
bmpg = Graphics.FromImage(bmp)
End Sub

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
e.Graphics.DrawImage(bmp, xtran, ytran)
End Sub

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
IsDown = True
xStartPos = Me.MousePosition.X
yStartPos = Me.MousePosition.Y
Me.PictureBox1.Cursor = Cursors.Hand
End Sub

Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
If IsDown Then
xEndPos = Me.MousePosition.X
yEndPos = Me.MousePosition.Y

xtran = xEndPos - xStartPos + old_xtran
ytran = yEndPos - yStartPos + old_ytran

bmpg.TranslateTransform(xtran, ytran)

Me.PictureBox1.Invalidate()
End If
End Sub

Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp

old_xtran = xtran
old_ytran = ytran
IsDown = False
Me.PictureBox1.Cursor = Cursors.Default
End Sub
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TextBox1.TextChanged
If System.Windows.Forms.Control.MouseButtons = MouseButtons.Left Then
MessageBox.Show( "Left ")
End If
End Sub
[解决办法]
那我还是建议楼使用我说的那个思路,然后再添加两个事件处理就可以了:

Private lastPoint As Point

Private Sub panel1_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)


Dim tmp As Point = e.Location
tmp.Offset(-Me.panel1.AutoScrollPosition.X, -Me.panel1.AutoScrollPosition.Y)
Me.lastPoint = tmp
End Sub

Private Sub panel1_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
If (e.Button = MouseButtons.Left) Then
Me.panel1.AutoScrollPosition = New Point(Me.lastPoint.X - e.X, Me.lastPoint.Y - e.Y)
End If
End Sub

[解决办法]
首先说Sorry吧,呵呵呵

我知道怎么回事了,你和我的情况不一样,不过你可以参考如下的代码来做,如下的代码是一个控件类,你可以在窗体界面上使用这个控件类来显示图片,当然我这里只是一个参考,具体的你可以跟据你的情况来修改,这样做后你的程序就不会出现闪的情况了,而是很平和的显示了:

class ImageCtr:Control
{
private Point m_Start;
private Point lastPoint;

public ImageCtr()
{
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
}

protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//下面的这个图,你可以使用属性来在控件使用的时候传入,这里只是示例
Image img = Properties.Resources.Winter;
e.Graphics.DrawImage(img, this.m_Start.X, this.m_Start.Y);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
Point tmp = e.Location;
tmp.Offset(-this.m_Start.X, -this.m_Start.Y);
lastPoint = tmp;
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (e.Button == MouseButtons.Left)
{
this.m_Start = new Point(e.X - lastPoint.X, e.Y - lastPoint.Y);
this.Invalidate();
}
}
}

[解决办法]
VB.NET的参考如下:

Public Class PanelEx
Inherits Control

Private lastPoint As Point
Private m_Start As Point

Public Sub New()
MyBase.SetStyle((ControlStyles.OptimizedDoubleBuffer Or (ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint)), True)
End Sub

Protected Overrides Sub OnMouseDown(ByVal e As MouseEventArgs)
MyBase.OnMouseDown(e)
Dim tmp As Point = e.Location
tmp.Offset(-Me.m_Start.X, -Me.m_Start.Y)
Me.lastPoint = tmp
End Sub


Protected Overrides Sub OnMouseMove(ByVal e As MouseEventArgs)
MyBase.OnMouseMove(e)
If (e.Button = MouseButtons.Left) Then
Me.m_Start = New Point((e.X - Me.lastPoint.X), (e.Y - Me.lastPoint.Y))
MyBase.Invalidate
End If
End Sub

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
MyBase.OnPaint(e)
Dim img As Image = Resources.Winter
e.Graphics.DrawImage(img, Me.m_Start.X, Me.m_Start.Y)
End Sub
End Class

[解决办法]
使用二次缓冲 + GDI中的Bitblt()块移可以解决平滑移动.
[解决办法]
openGL或direct X显示在一个矩形上?然后鼠标响应 移动它,1MB的GIF,14MB的位图确实很大,我也不知道效果会如何。暑假在家暂时手边没相应东西。。想非openGL,D3D的程序如果没采用特殊的读取显示方法的话,应该会比这个慢,毕竟这个是硬件级的指令负责显示,应该会快很多。LZ试试。
[解决办法]
思路:
一、记住图片框宽度和高度
二、记住图片相对于图片框的位置Left和Top值
三、只绘制图片框大小的内容,其余多出的部分不管

应该能够实现

热点排行