【问题标题】:Printing from webbrowser twice从网络浏览器打印两次
【发布时间】:2013-10-05 16:14:52
【问题描述】:

当我尝试多次打印 COM 网络浏览器时,我遇到了问题。
复制问题:

1) 创建一个新的“Windows 窗体”项目
2) 将 COM 引用添加到“Microsoft Internet Controls”
3) 将 webbrowser 控件“webbrowser1”和按钮“button1”添加到表单(来自工具箱)
4) 确保您有文件“c:\index.html”
5)添加此代码...

Option Explicit On

Imports System.IO
Imports System.Reflection
Imports System.Diagnostics.Process
Imports System.Runtime.InteropServices
Imports SHDocVw

Public Class Form1
Dim WithEvents p As New PrintHTML
Dim htmlfilename As String

Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    p = Nothing
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    htmlfilename = "c:\index.html"
    WebBrowser1.Navigate(htmlfilename)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    p.PrintHTMLDocument(htmlfilename)
End Sub
End Class

Public Class PrintHTML

Dim documentLoaded As Boolean = False
Dim documentPrinted As Boolean = False

Public Sub PrintHTMLDocument(ByVal htmlfilename As String)

    Dim ie As New InternetExplorer
    AddHandler DirectCast(ie, InternetExplorer).PrintTemplateTeardown, AddressOf PrintedCB
    AddHandler DirectCast(ie, InternetExplorer).DocumentComplete, AddressOf LoadedCB

    ie.Navigate(htmlfilename)
    While Not documentLoaded AndAlso ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) <> OLECMDF.OLECMDF_ENABLED
        Application.DoEvents()
        Threading.Thread.Sleep(100)
    End While

    Try
        ie.ExecWB(OLECMDID.OLECMDID_PRINT, OLECMDEXECOPT.OLECMDEXECOPT_DONTPROMPTUSER, vbNull, vbNull)
        While Not documentPrinted
            Application.DoEvents()
            Threading.Thread.Sleep(100)
        End While
    Catch ex As Exception
        Debug.Print(ex.Message)
    End Try
End Sub

Private Sub LoadedCB(ByVal obj As Object, ByRef url As Object)
    documentLoaded = True
End Sub

Private Sub PrintedCB(ByVal obj As Object)
    documentPrinted = True
End Sub
End Class

当我第一次单击 button1 时,一切都按预期运行(打印开始),但是当我单击 button1 进行多次打印时 - 而不是打印,我收到错误消息:

在 my.exe 中发生了“System.Runtime.InteropServices.COMException”类型的第一次机会异常
试图撤销尚未注册的放置目标(HRESULT 异常:0x80040100 (DRAGDROP_E_NOTREGISTERED))

什么可能导致这个错误,我怎样才能摆脱它,以便能够使用描述的组件多次打印文档?

【问题讨论】:

    标签: vb.net


    【解决方案1】:

    在再次调用Navigate 之前,您似乎忘记将documentLoadeddocumentPrinted 设置回false。从上次打印出来它们仍然是true,并且您的等待事件循环逻辑不起作用。即,它应该是:

    documentLoaded = False
    documentPrinted = False
    ie.Navigate(htmlfilename)
    While Not documentLoaded AndAlso ie.QueryStatusWB(OLECMDID.OLECMDID_PRINT) <> OLECMDF.OLECMDF_ENABLED
        Application.DoEvents()
        Threading.Thread.Sleep(100)
    End While
    

    还有另一个问题。显然,您不会在 PrintHTMLDocument 中重复使用 InternetExplorer 对象并在每次打印时创建一个新实例。如果出于某种原因您不想重复使用它,您至少应该在PrintHTMLDocument 的末尾调用ie.Quit。否则,您将依赖 .NET 垃圾收集器来释放对象(这是一个进程外 COM 自动化对象,每个都占用一些大量系统资源)。如果您确实打算重复使用它,请确保只添加一次事件处理程序。

    【讨论】:

    • 是的,就是这样!谢谢诺塞拉蒂奥。我的代码现在完全按预期工作。我必须使用新实例来打印文档,但我不知道为什么我的部分代码丢失了?也许我发布了“太快了”。是的,每次打印后我都会删除处理程序,调用 ie.Quit 并设置 ie=Nothing。我认为这足以清洁一个物体。
    • 没问题,很高兴它有帮助。如果您执行这样的清理工作应该没问题。
    猜你喜欢
    • 2010-11-22
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 2012-10-30
    • 2021-04-28
    相关资源
    最近更新 更多