【问题标题】:WebBrowser, handle pdf load completeWebBrowser,处理pdf加载完成
【发布时间】:2013-09-14 18:08:34
【问题描述】:

我想知道是否有人知道让 .pdf 文件在加载时触发就绪状态的简单方法。我正在构建一个程序来打开 url 并截取屏幕截图,然后将它们放入 excel 中。

网络浏览器将正确加载 html 文档,但在加载 .pdf 文件时卡在 While Not pageready 中。浏览器控件正确呈现.pdf

Private Sub btngo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btngo.Click
    Dim file As String
    Dim Obj As New Object
    Dim result As String
    Dim sheet As String = "sheet1"
    Dim xlApp As New Excel.Application

    If lblpath.Text <> "" Then
        file = lblpath.Text
        Dim xlWorkBook = xlApp.Workbooks.Open(file)
        Dim xlWorkSheet = xlWorkBook.Worksheets(sheet)
        Dim range = xlWorkSheet.UsedRange

        ProgressBar1.Value = 0

        For rCnt = 4 To range.Rows.Count
            'url cell
            Obj = CType(range.Cells(rCnt, 2), Excel.Range)
            ' Obj.value now contains the value in the cell.. 
            Try
                ' Creates an HttpWebRequest with the specified URL. 
                Dim myHttpWebRequest As HttpWebRequest = CType(WebRequest.Create(Obj.value), HttpWebRequest)
                ' Sends the request and waits for a response. 
                Dim myHttpWebResponse As HttpWebResponse = CType(myHttpWebRequest.GetResponse(), HttpWebResponse)
                If myHttpWebResponse.StatusCode = HttpStatusCode.OK Then
                    result = myHttpWebResponse.StatusCode
                    WebBrowser1.ScrollBarsEnabled = False
                    WebBrowser1.Navigate(myHttpWebRequest.RequestUri)

                    WaitForPageLoad()

                    CaptureWebBrowser(WebBrowser1)
                End If
                ' Release the resources of the response.
                myHttpWebResponse.Close()

            Catch ex As WebException
                result = (ex.Message)
            Catch ex As Exception
                result = (ex.Message)
            End Try


            RichTextBox1.AppendText(result & "    " & Obj.value & vbNewLine)

            If radpre.Checked = True Then
                range.Cells(rCnt, 3).value = result
            ElseIf radcob.Checked = True Then
                range.Cells(rCnt, 4).value = result
            ElseIf radpost.Checked = True Then
                range.Cells(rCnt, 5).value = result

            End If


            ProgressBar1.Value = rCnt / range.Rows.Count * 100
        Next

        With xlApp
            .DisplayAlerts = False
            xlWorkBook.SaveAs(lblpath.Text.ToString)
            .DisplayAlerts = True
        End With

        xlWorkBook.Close()
        xlApp.Quit()

        'reclaim memory
        Marshal.ReleaseComObject(xlApp)
        xlApp = Nothing
    End If
End Sub

Private Function CaptureWebBrowser(ByVal wb As WebBrowser) As Image
    Try
        Dim hBitmap As Bitmap = New Bitmap(wb.Width, wb.Height)
        wb.DrawToBitmap(hBitmap, wb.Bounds)
        Dim img As Image = hBitmap
        Return img
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
    Return Nothing
End Function


Private Sub WaitForPageLoad()
    AddHandler WebBrowser1.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
    While Not pageready
        Application.DoEvents()
    End While
    pageready = False
End Sub

Private Sub PageWaiter(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
    If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
        pageready = True
        RemoveHandler WebBrowser1.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
    End If
End Sub

更新到已解决


我对反馈感到非常满意。我真的很喜欢Noseratio 提供的答案。我不知道使用代码模式不是最佳实践。打开 .pdf 或任何其他非基于 Web 的文档时,readyState 将永远不会更改为 0。看到这个程序对我来说只是一种不工作的方式,我很满意只捕获.html.htm

我的要求是

  1. 打开excel文档
  2. 解析位于 excel 文档中的链接
  3. 确定响应代码
  4. 将响应代码和屏幕截图写入 excel

程序解析和检索反馈的速度远快于我手动完成的速度。 .html.htm 的屏幕截图为非技术人员提供了成功从生产环境迁移到 COB 并返回生产环境的 excel 文件证明。

Noseratio 所述的代码没有遵循最佳实践,也不是高质量的。这是一个快速而肮脏的实现。

Option Infer On
Imports Microsoft.Office.Interop
Imports System.Net
Imports System.Runtime.InteropServices

Public Class Form1


Public Property pageready As Boolean

Private Sub OpenToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OpenToolStripMenuItem.Click
    OpenFileDialog1.ShowDialog()
End Sub

Private Sub OpenFileDialog1_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles OpenFileDialog1.FileOk
    lblpath.Text = OpenFileDialog1.FileName.ToString
End Sub

Private Sub btngo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btngo.Click
    Dim file As String
    Dim Obj As New Object
    Dim result As String
    Dim sheet As String = "sheet1"
    Dim xlApp As New Excel.Application
    Dim img As Bitmap
    Dim path As String = "C:\Documents and Settings\user\My Documents\Visual Studio 2010\Projects\COB-HTML-Tool\COB-HTML-Tool\bin\Debug\tmp.bmp"
    If lblpath.Text <> "" Then
        file = lblpath.Text
        Dim xlWorkBook = xlApp.Workbooks.Open(file)
        Dim xlWorkSheet = xlWorkBook.Worksheets(sheet)
        Dim range = xlWorkSheet.UsedRange

        ProgressBar1.Value = 0

        For rCnt = 4 To range.Rows.Count
            'url cell
            Obj = CType(range.Cells(rCnt, 2), Excel.Range)
            ' Obj.value now contains the value in the cell.. 
            Try
                ' Creates an HttpWebRequest with the specified URL. 
                Dim myHttpWebRequest As HttpWebRequest = CType(WebRequest.Create(Obj.value), HttpWebRequest)
                ' Sends the request and waits for a response. 
                Dim myHttpWebResponse As HttpWebResponse = CType(myHttpWebRequest.GetResponse(), HttpWebResponse)
                If myHttpWebResponse.StatusCode = HttpStatusCode.OK Then
                    result = myHttpWebResponse.StatusCode


                    Dim len As Integer = myHttpWebRequest.RequestUri.ToString.Length - 4
                    If myHttpWebRequest.RequestUri.ToString.Substring(len) = ".htm" Or
                        myHttpWebRequest.RequestUri.ToString.Substring(len - 1) = ".html" Or
                        myHttpWebRequest.RequestUri.ToString.Substring(len) = ".asp" Then
                        WebBrowser1.Navigate(myHttpWebRequest.RequestUri)
                        WaitForPageLoad()

                        img = CaptureWebBrowser(WebBrowser1)
                        img.Save(path)
                    End If

                End If
    ' Release the resources of the response.
    myHttpWebResponse.Close()

            Catch ex As WebException
        result = (ex.Message)
    Catch ex As Exception
        result = (ex.Message)
    End Try


            RichTextBox1.AppendText(result & "    " & Obj.value & vbNewLine)

            If radpre.Checked = True Then
                range.Cells(rCnt, 3).value = result

                If img Is Nothing Then
                Else
                    If Dir(path) <> "" Then
                        range.Cells(rCnt, 4).Select()
                        Dim opicture As Object
                        opicture = xlApp.ActiveSheet.Pictures.Insert(path)
                        opicture.ShapeRange.LockAspectRatio = True
                        opicture.ShapeRange.width = 170
                        opicture.ShapeRange.height = 170
                        My.Computer.FileSystem.DeleteFile(path)

                    End If
                End If
            ElseIf radcob.Checked = True Then
                range.Cells(rCnt, 5).value = result
                If img Is Nothing Then
                Else
                    If Dir(path) <> "" Then
                        range.Cells(rCnt, 6).Select()
                        Dim opicture As Object
                        opicture = xlApp.ActiveSheet.Pictures.Insert(path)
                        opicture.ShapeRange.LockAspectRatio = True
                        opicture.ShapeRange.width = 170
                        opicture.ShapeRange.height = 170
                        My.Computer.FileSystem.DeleteFile(path)
                    End If
                End If
            ElseIf radpost.Checked = True Then
                range.Cells(rCnt, 7).value = result
                If img Is Nothing Then
                Else
                    If Dir(path) <> "" Then
                        range.Cells(rCnt, 8).Select()
                        Dim opicture As Object
                        opicture = xlApp.ActiveSheet.Pictures.Insert(path)
                        opicture.ShapeRange.LockAspectRatio = True
                        opicture.ShapeRange.width = 170
                        opicture.ShapeRange.height = 170
                        My.Computer.FileSystem.DeleteFile(path)
                    End If
                End If
            End If


            ProgressBar1.Value = rCnt / range.Rows.Count * 100
        Next

        With xlApp
            .DisplayAlerts = False
            xlWorkBook.SaveAs(lblpath.Text.ToString)
            .DisplayAlerts = True
        End With

        xlWorkBook.Close()
        xlApp.Quit()

        'reclaim memory
        Marshal.ReleaseComObject(xlApp)
        xlApp = Nothing
    End If
End Sub
Private Function CaptureWebBrowser(ByVal wb As WebBrowser) As Image

    Try
        wb.ScrollBarsEnabled = False
        Dim hBitmap As Bitmap = New Bitmap(wb.Width, wb.Height)
        wb.DrawToBitmap(hBitmap, wb.Bounds)
        Dim img As Image = hBitmap
        Return img
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
    Return Nothing
End Function


Private Sub WaitForPageLoad()
    AddHandler WebBrowser1.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
    While Not pageready
        Application.DoEvents()
        System.Threading.Thread.Sleep(200)
    End While
    pageready = False
End Sub

Private Sub PageWaiter(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
    If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
        pageready = True
        RemoveHandler WebBrowser1.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
    End If
End Sub


End Class

【问题讨论】:

  • 据我了解,浏览器不会呈现 .pdf,Adobe(或您拥有的任何 pdf 查看器)是。当文档完成触发时,是否可以检查 Web 浏览器控件的 URL?
  • 我明天必须检查调试。它确实呈现正确数量的页面。据我所知,浏览器控件使用已安装的 IE,而后者又调用已安装的 Adob​​e。有没有更简单的方法来调用网址和截图?
  • 您是尝试将 pdf 打印为屏幕截图还是只是绕过它并通过处理 readystate 完成继续?

标签: vb.net webbrowser-control


【解决方案1】:

很遗憾,您将无法使用webBrowser.DrawToBitmap 获取 PDF 视图的快照。在撰写本文时,Adobe Acrobat Reader ActiveX 控件不支持在自定义设备上下文上呈现,因此此方法不起作用,以及发送WM_PRINT 或调用IViewObject::Draw ,或者直接在通过 WebBrowser 上的 Reader ActiveX 对象上(我试过了,I'm not alone)。正确的解决方案是使用第 3 方 PDF 渲染组件。

附带说明,您应该避免使用这样的代码模式:

While Not pageready
    Application.DoEvents()
End While

这是一个busy waiting 紧密循环,徒劳地消耗 CPU 周期。至少,在循环中添加一些Thread.Sleep(200),但总体而言,您也应该避免使用using Application.DoEvents

【讨论】:

  • 我总是看到这个响应,但是还没有看到一个好的解决方案来解决等待页面准备好而不冻结 UI 的问题(仅仅因为 WBC 说“准备好”并不意味着页面真的“准备好了”,我经常在加载数据库数据的过程中得到这个)。
  • @JasonBayldon,这里是 my approach 来处理“准备就绪”,而不依赖于 readyState。可以类似地在 VB.NET 中完成。然而,这适用于导航到 HTML 页面,而不是 PDF。关于 PDF,我会托管 Adob​​e Reader ActiveX directly,没有 WebBrowser 层。
  • 感谢您的反馈。由于这是一个快速肮脏的扔掉程序,我将代码留给我编辑的内容。下次我会记住 Code Pattern 的用法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-11
  • 2012-04-30
  • 2018-11-07
  • 2012-05-14
  • 2011-02-16
  • 2013-10-31
  • 1970-01-01
相关资源
最近更新 更多