【问题标题】:Programmatically Printing in Adobe Reader 9 using .NET Interop使用 .NET 互操作在 Adob​​e Reader 9 中以编程方式打印
【发布时间】:2008-10-24 14:48:57
【问题描述】:

我正在使用 VB.Net WinForms。我想调用 Adob​​e Reader 9 ActiveX 控件来打印一些 PDF。我已将 ActiveX 控件添加到 VS 工具箱中(dll 为 AcroPDF.dll,COM 名称为“Adobe PDF Reader”。经过一些实验,以下代码有效。

Dim files As String() = Directory.GetFiles(TextBoxPath.Text, "*.pdf", SearchOption.TopDirectoryOnly)

Using ActiveXPDF As New AxAcroPDFLib.AxAcroPDF

    Me.Controls.Add(ActiveXPDF)
    ActiveXPDF.Hide()

    For Each filename As String In files

        ActiveXPDF.LoadFile(filename)
        ActiveXPDF.printAll()

        'Begin Yukky Hack    '


        Dim endTime As Date = DateAdd(DateInterval.Second, 20, Now)
        Do While Now < endTime
            My.Application.DoEvents()
        Loop

        'End Yuk   '

    Next

End Using

如果没有 Yuk 位,这只会打印一些 PDF,看起来 End Using 语句在完成打印之前正在调用控件上的 dispose。

因此,对 printAll 的调用似乎是非阻塞的,但我找不到可以查询的回调或状态属性,以查看打印假脱机是否已完成。我错过了一个属性/方法,还是有更优雅(响应更快)的解决方法?

【问题讨论】:

    标签: .net vb.net interop activex adobe-reader


    【解决方案1】:

    使用这种方法打印多个文档并不像您发现的那样好用。

    让它工作是相当棘手的,但这里是解决方案的一般描述。

    我使用 System.Diagnostics.Process 使用 myProcess.StartInfo.Verb = "Print" 进行打印 然后我分两步检查打印机队列的状态和状态,以确保打印准备就绪,可以打印下一个文档。使用 WMI 和 ManagementObjectSearcher 使用“SELECT * FROM Win32_Printer”枚举打印机信息。 逻辑是,在继续打印下一个之前,我尝试查看假脱机是否开始。

    有关 Win32_Printer WMI 类,请参阅 http://msdn.microsoft.com/en-us/library/aa394363.aspx

    【讨论】:

    • +1 但这几乎和我的“稍等一下”hack 一样可怕!我想知道为什么它是这样的皮塔饼。我决定不打电话给 Dispose,我想这更糟......
    【解决方案2】:

    我在 Delphi 中使用 AcroPDF 时遇到了同样的问题。然后我发现当我使用消息“停止”进程时,AcroPDF 开始打印。

    所以我只是创建了一个模态 TForm,它会在几秒钟后自行关闭。

    var
      formModal : TFormModal;
    begin
      formModal := TFormModal.Create(self);
      //PrintMethodHere  
      frmPecas.CarregarDocumentoParaImpressao();
      formModal.ShowModal;
    end;
    

    TFormModal 就是这个,我只是在表单上插入一个加载图标来表示“打印”之类的东西。

    unit FModal;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, Animate, GIFCtrl;
    
    type
      TFormModal = class(TForm)
        Timer: TTimer;
        imgGif: TRxGIFAnimator;
        procedure TimerTimer(Sender: TObject);
        procedure FormShow(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure FormCreate(Sender: TObject);
        procedure FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      FormModal: TFormModal;
    
    implementation
    
    {$R *.dfm}
    //    Author: Anderson Mello  Date: 09-fev-2012
    //  DEscription: Using TTimer after 5 seconds I close this form
    procedure TFormModal.TimerTimer(Sender: TObject);
    begin
     close;
    end;
    
    //    Author: Anderson Mello  Date: 09-fev-2012
    //  Description: Enable the timer only when the form is shown
    procedure TFormModal.FormShow(Sender: TObject);
    begin
     Timer.Enabled := true;
    end;
    
    //  Description: disable when close
    procedure TFormModal.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
     Timer.Enabled := false;
    end;
    
    //    Author: Anderson Mello  Date: 09-fev-2012
    //  Description: disable close button "X", so the user can't close 
    procedure TFormModal.FormCreate(Sender: TObject);
    var
      hSysMenu:HMENU;
    begin
      hSysMenu:=GetSystemMenu(Self.Handle,False);
      if hSysMenu <> 0 then begin
        EnableMenuItem(hSysMenu,SC_CLOSE,MF_BYCOMMAND or MF_GRAYED);
        DrawMenuBar(Self.Handle);
      end;
      KeyPreview:=True;
    end;
    
    //    Author: Anderson Mello  Date: 09-fev-2012
    //  Description: disable shortcuts to close
    procedure TFormModal.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      if (Key = VK_F4) and (ssAlt in Shift) then
        Key:=0;
    end;
    

    【讨论】:

      【解决方案3】:

      我们最终将 Adob​​e 的 PDF Verifier 用于我们自己的测试目的。为了做到这一点,我们必须实际启动 acrobat 并使用SendInput 以编程方式操作它的界面。

      我很想看看是否可以使用内部 API。

      【讨论】:

        【解决方案4】:

        您可以使用此代码通过相应的软件显示任何文件。

        Sub Show_Document(ByVal FILENAME As String)
            Dim p As Process = Nothing
            Try
                If My.Computer.FileSystem.FileExists(FILENAME) Then
                    p = Process.Start(FILENAME)
                    p.Dispose()
                End If
        
            Catch ex As Exception
        
            Finally
        
            End Try
        
        End Sub
        

        【讨论】:

        • 问题是关于如何打印 PDF,而不是打开它们。我知道他们可以在新的 Adob​​e Reader 实例中单击“打印”,但这是一个可用性噩梦。此外,吞下异常是不好的做法。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-21
        • 2019-04-28
        • 2014-03-10
        • 1970-01-01
        • 2011-01-15
        • 1970-01-01
        • 2013-01-23
        相关资源
        最近更新 更多