快速移动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值
三、只绘制图片框大小的内容,其余多出的部分不管
应该能够实现