【问题标题】:Download Image under the Mouse pointer via WebBrowser通过 WebBrowser 下载鼠标指针下的图像
【发布时间】:2019-05-16 10:27:36
【问题描述】:

我正在使用 WebBrowser 控件导航到 Google 图片。目的是能够右键单击任何图像并下载并填充 PictureBox 背景。

我有自己的ContextMenuStrip,上面有复制,并且禁用了内置的上下文菜单。

我遇到的问题是从CurrentDocument.MouseMove 返回的坐标总是相对于第一张(左上角)图像。
因此,如果我想要的图像是页面上的第一个图像,我的代码可以正常工作,但是单击任何其他图像总是返回第一个图像的坐标。

看起来坐标是相对于每个图像而不是页面的。

Private WithEvents CurrentDocument As HtmlDocument
Dim MousePoint As Point
Dim Ele As HtmlElement

Private Sub Google_covers_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    WebBrowser1.IsWebBrowserContextMenuEnabled = False
    WebBrowser1.ContextMenuStrip = ContextMenuStrip1
End Sub

Private Sub WebBrowser1_Navigated(sender As Object, e As WebBrowserNavigatedEventArgs) Handles WebBrowser1.Navigated
    CurrentDocument = WebBrowser1.Document

End Sub
Private Sub CurrentDocument_MouseMove(sender As Object, e As HtmlElementEventArgs) Handles CurrentDocument.MouseMove
    MousePoint = New Point(e.MousePosition.X, e.MousePosition.Y)
    Me.Text = e.MousePosition.X & " | " & e.MousePosition.Y
End Sub

Private Sub ContextMenuStrip1_Opening(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles ContextMenuStrip1.Opening
    Ele = CurrentDocument.GetElementFromPoint(MousePoint)
    If Ele.TagName = "IMG" Then
        CopyToolStripMenuItem.Visible = True
    Else
        CopyToolStripMenuItem.Visible = False
    End If
End Sub

Private Sub CopyToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles CopyToolStripMenuItem.Click
    Dim ToImg = Ele.GetAttribute("src")
    mp3_row_edit.PictureBox1.BackgroundImage = New System.Drawing.Bitmap(New IO.MemoryStream(New System.Net.WebClient().DownloadData(ToImg)))
    ToImg = Nothing
End Sub

【问题讨论】:

  • 谢谢,但即使使用他们的代码,它的行为仍然相同,这与谷歌图像搜索如何显示它的结果有关,在其他页面上也能正常工作。还在寻找
  • 完美运行。您可能没有算到的是,图像是使用 Base64 字符串直接插入到 HTML 文档中的。没有source。您必须获取字符串并对其进行解码。请参阅:Convert.FromBase64String
  • 它不适用于此网址:google.com/…
  • 它有效。你解码图像了吗?

标签: vb.net winforms webbrowser-control


【解决方案1】:

此代码允许使用标准 WebBrowser 控件导航到 Google 图片搜索页面并通过鼠标右键单击来选择/下载图片。

要对其进行测试,请将 WebBrowser 控件和 FlowLayoutPanel 拖放到表单上,然后导航到 Google 图片搜索页面。

须知:


请注意,当当前文档完成时,事件处理程序会被连接起来,而当浏览器导航到另一个页面时,事件处理程序会被删除。这可以防止对DocumentCompleted 事件的意外调用。

当前文档完成后,在图像上单击鼠标右键会创建一个新的 PictureBox 控件,该控件将添加到 FlowLayouPanel 以进行演示。

鼠标单击处理程序 (Protected Sub OnHtmlDocumentClick()) 中的代码检测当前图像是 Base64Encoded 字符串还是外部源 URI
在第一种情况下,它调用Convert.FromBase64String 将字符串转换为字节数组,在第二种情况下,它使用 WebClient 类将图像下载为字节数组。

在这两种情况下,然后将数组传递给另一个方法 (Private Function GetBitmapFromByteArray()),该方法使用 Image.FromStream() 从数组返回图像>MemoryStream 使用 Byte 数组初始化。

这里的代码没有执行空检查和类似的防故障测试。应该的,这取决于你。

Public Class frmBrowser
    Private WebBrowserDocumentEventSet As Boolean = False
    Private base64Pattern As String = "base64,"

    Private Sub frmBrowser_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        WebBrowser1.ScriptErrorsSuppressed = True
        WebBrowser1.IsWebBrowserContextMenuEnabled = False
    End Sub

    Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
        If WebBrowser1.ReadyState = WebBrowserReadyState.Complete AndAlso WebBrowserDocumentEventSet = False Then
            WebBrowserDocumentEventSet = True
            AddHandler WebBrowser1.Document.MouseDown, AddressOf OnHtmlDocumentClick
        End If
    End Sub

    Protected Sub OnHtmlDocumentClick(sender As Object, e As HtmlElementEventArgs)
        Dim currentImage As Image = Nothing

        If Not (e.MouseButtonsPressed = MouseButtons.Right) Then Return
        Dim source As String = WebBrowser1.Document.GetElementFromPoint(e.ClientMousePosition).GetAttribute("src")

        If source.Contains(base64Pattern) Then
            Dim base64 As String = source.Substring(source.IndexOf(base64Pattern) + base64Pattern.Length)
            currentImage = GetBitmapFromByteArray(Convert.FromBase64String(base64))
        Else
            Using wc As WebClient = New WebClient()
                currentImage = GetBitmapFromByteArray(wc.DownloadData(source))
            End Using
        End If

        Dim p As PictureBox = New PictureBox() With {
            .Image = currentImage,
            .Height = Math.Min(FlowLayoutPanel1.ClientRectangle.Height, FlowLayoutPanel1.ClientRectangle.Width)
            .Width = .Height,
            .SizeMode = PictureBoxSizeMode.Zoom
        }
        FlowLayoutPanel1.Controls.Add(p)
    End Sub

    Private Sub WebBrowser1_Navigating(sender As Object, e As WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
        If WebBrowser1.Document IsNot Nothing Then
            RemoveHandler WebBrowser1.Document.MouseDown, AddressOf OnHtmlDocumentClick
            WebBrowserDocumentEventSet = False
        End If
    End Sub

    Private Function GetBitmapFromByteArray(imageBytes As Byte()) As Image
        Using ms As MemoryStream = New MemoryStream(imageBytes)
            Return DirectCast(Image.FromStream(ms).Clone(), Image)
        End Using
    End Function
End Class

【讨论】:

  • 我们有过的最佳答案。感谢您的努力,它工作得很好!
  • 顺便说一句,如果其他人使用此代码并希望将图像保存到文件中,那么您需要在 GetBitmapFromByteArray 函数中执行此操作。由于返回的图像“currentImage”不会像您期望的那样将其内容写入磁盘。
  • 您可以使用currentImage 将图像保存到光盘。只需在If source.Contains(base64Pattern) Then ( ... ) End If 之后插入currentImage.Save("currentImage.png", ImageFormat.Png)。它将图像保存在应用程序的路径中。您可以使用HtmlElementID attribute 来命名它。并不是说它作为一个名字有多大意义,它是一堆随机字符,无论如何......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-03
  • 2013-03-05
相关资源
最近更新 更多