如何在VB.NET中使用滚轮放大Picturebox

9
我正在使用一组图形叠加层来在图片框控件中使用图形对象绘制图像。我已经将Picturebox放置在一个Panel中并设置Panel为自动滚动。现在我需要知道如何使用鼠标滚轮以小增量方式扩大图片的大小,同时保持所绘制图像的质量。有人知道怎么做吗?
当我使用Abdias Software代码进行更新时,当Sizemode属性设置为StretchImage时,图片开始变小。我有一个带有鼠标的平移功能,可能会干扰这段代码的正常工作。任何想法?是什么阻止了它的正常工作?
解决方案:
这段代码对我比下面的两个都好用多了。
Private Sub PictureBox_MouseWheel(sender As System.Object,
                             e As MouseEventArgs) Handles PictureBox1.MouseWheel
    If e.Delta <> 0 Then
        If e.Delta <= 0 Then
            If PictureBox1.Width < 500 Then Exit Sub 'minimum 500?
        Else
            If PictureBox1.Width > 2000 Then Exit Sub 'maximum 2000?
        End If

        PictureBox1.Width += CInt(PictureBox1.Width * e.Delta / 1000)
        PictureBox1.Height += CInt(PictureBox1.Height * e.Delta / 1000)
    End If

End Sub

我添加了你的代码,移动功能按预期启用,缩放也正常工作。这些事件是独立的,不应该互相干扰。SizeMode将强制图像大小与控件大小相同,因此如果控件大小小于图像,则图像将缩小。您可以在加载事件(或设置图像的方法)中设置PictureBox1.Size = New Size(bmp.Width, bmp.Height)(同时使用相同的方式更新_originalSize)。除此之外,在没有看到更多代码的情况下,我无法看到任何潜在问题。 - user1693593
我使用了你的所有代码,只是换了不同的图片,但仍然有效。 (顺便说一句:我不确定为什么你在那里放置了SetStyle()。它们是用于用户控件的,此时在代码中不会有太大作用)。除此之外,一切都按预期工作(即使启用了setstyles)。这有点神秘。我在XP上。我不认为这很重要,但值得检查并希望消除如果你在其他win版本上。 - user1693593
我正在使用Windows 7和Visual Studio Express 2012。你认为这可能是他们尚未修复的错误吗?我不想把所有的代码都移到Visual Basic Express 2010并重新绘制一切。唉!如果你不介意我问一下,你的PictureBox控件和Panel控件的属性设置是什么?不知道是否像那样简单。但谁知道,也许我的设置有问题。 - Greg Willard
这是我的所有设置:http://pastebin.com/FnAzVKzF。可能是VS2012的一个bug,看来是这样的。不过只有一种方法可以找出来.. :) - user1693593
3个回答

8
您可以尝试这段代码。它假设在表单上存在一个名为Panel1PictureBox1的控件(PictureBox1位于Panel1内,且Panel1.AutoScroll = True),并且在PictureBox上设置了一张图片。
该代码不会计算缩放的中心点,但您可以使用e.Location(或e.X / e.Y)来实现。
更新 - 这里是新代码,应该比以前更加健壮(请参见底部):
Public Class Form1

    Private _originalSize As Size = Nothing
    Private _scale As Single = 1
    Private _scaleDelta As Single = 0.0005

    Private Sub Form_MouseWheel(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel

        'if very sensitive mouse, change 0.00005 to something even smaller   
        _scaleDelta = Math.Sqrt(PictureBox1.Width * PictureBox1.Height) * 0.00005

        If e.Delta < 0 Then
            _scale -= _scaleDelta
        ElseIf e.Delta > 0 Then
            _scale += _scaleDelta
        End If

        If e.Delta <> 0 Then _
        PictureBox1.Size = New Size(CInt(Math.Round(_originalSize.Width * _scale)), _
                                    CInt(Math.Round(_originalSize.Height * _scale)))

    End Sub

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

        'init this from here or a method depending on your needs
        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Size = Panel1.Size
            _originalSize = Panel1.Size
        End If

    End Sub

End Class

旧代码 - 可以工作,但在大的更改时不稳定,可能是由于Scale()中的舍入误差:

Public Class Form1

    Private _scale As New SizeF(1, 1)
    Private _scaleDelta As New SizeF(0.01, 0.01) '1% for each wheel tick

    Private Sub Form_MouseWheel(sender As System.Object, 
                                e As MouseEventArgs) Handles Me.MouseWheel
'count incrementally 
        _scale.Height = 1
        _scale.Width = 1

        If e.Delta < 0 Then
            _scale += _scaleDelta
        ElseIf e.Delta > 0 Then
            _scale -= _scaleDelta
        End If

        If e.Delta <> 0 Then _
        PictureBox1.Scale(_scale)

    End Sub

    Private Sub Form1_Load(sender As System.Object, 
                           e As EventArgs) Handles MyBase.Load

        PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

        'init picturebox size = image size
        If PictureBox1.Image IsNot Nothing Then
            PictureBox1.Scale(New SizeF(1, 1))
            PictureBox1.Size = PictureBox1.Image.Size
        End If

    End Sub

End Class

我尝试了这段代码,它运行良好,但似乎存在一个重大问题。当我启动程序时,图片框自动将原本全尺寸的图片缩小了,而在添加代码之前它是完整的。当我使用滚轮时,它会变得更小,而当我向另一侧滚动时,它会变得更大,直到只剩下一半的图片大小。你知道是什么原因吗? - Greg Willard
我在窗体的加载事件中添加了一小段代码片段,以将pbox的大小调整为其上设置的图像大小。如果图像是从其他地方设置的,则将代码移动到那里即可。 - user1693593
@GregWillard 我可能会成为一个舍入误差问题。另一种方法是,不使用Scale(),而是直接使用变量计算Size。我会进行测试以确认,并在需要时更新我的答案来包含该代码。 - user1693593
我无法重现这个问题。你可以禁用自定义图像绘制,只需使用简单的图片测试picturebox,看看问题是否仍然存在。如果没有,则说明问题需要在其他地方解决。我认为问题不是不同的大小,因为设置Image属性会删除旧的并在内部更新新的大小(但如果大小模式设置为stretch等,则不会显示)。 - user1693593
在我看来,Handles PictureBox1.MouseWheel 比 Handles Form1.MouseWheel 更好。 - JDPeckham
显示剩余5条评论

0
我注意到使用StretchImage SizeMode 会忽略图像比例,导致不良影响。因此,我在“缩放”算法中添加了宽度和高度比例变量。请参见下面代码中的_ratWidth_ratHeight
Public Class Form1

Private _originalSize As Size = Nothing
Private _scale As Single = 1
Private _scaleDelta As Single = 0.0005
Private _ratWidth, _ratHeight As Double

Private Sub Form_MouseWheel(sender As System.Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel

    'if very sensitive mouse, change 0.00005 to something even smaller   
    _scaleDelta = Math.Sqrt(PictureBox1.Width * PictureBox1.Height) * 0.00005

    If e.Delta < 0 Then
        _scale -= _scaleDelta
    ElseIf e.Delta > 0 Then
        _scale += _scaleDelta
    End If

    If e.Delta <> 0 Then _
    PictureBox1.Size = New Size(CInt(Math.Round((_originalSize.Width * _ratWidth) * _scale)), _
                                CInt(Math.Round((_originalSize.Height * _ratHeight) * _scale)))

End Sub

Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    PictureBox1.SizeMode = PictureBoxSizeMode.StretchImage

    'init this from here or a method depending on your needs
    If PictureBox1.Image IsNot Nothing Then
        _ratWidth = PictureBox1.Image.Width / PictureBox1.Image.Height
        _ratHeight = PirctureBox1.Image.Height / PictureBox1.Image.Width
        PictureBox1.Size = Panel1.Size
        _originalSize = Panel1.Size
    End If
End Sub
End Class

0

谢谢回复,但我希望在VB.NET中实现这个功能,而且不使用第三方控件。 - Greg Willard
请检查第二个链接,它包含C#和VB代码。它是针对PictureBox的,但我以前没有尝试过。 - urlreader
我看到了,这是一个很好的例子,但是我正在寻找一个使用鼠标滚轮而不是缩放滑块的例子。谢谢! - Greg Willard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接