使用 .NET Interop 在 Adob​​e Reader 9 中以编程方式打印

发布于 2024-07-08 01:07:52 字数 888 浏览 15 评论 0原文

我正在使用 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 的调用似乎是非阻塞的,但我找不到可以查询以查看打印假脱机是否已进行的回调或状态属性。我缺少一个属性/方法,或者是否有更优雅(且响应更快)的解决方法?

I am using VB.Net WinForms. I would like to call the Adobe Reader 9 ActiveX control to print some PDFs. I have added the ActiveX control to the VS toolbox (the dll is AcroPDF.dll, the COM name "Adobe PDF Reader". After some experiment the following code works.

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

Without the Yuk bit this will only print some of the PDFs, it seems that the End Using statement is calling dispose on the control before it has finished printing.

Therefore it seems the call to printAll is non-blocking but I can't find a callback or status property I can query to see if the print spooling has been completed. I am missing a property/method or is there a more elegant (and more responsive) work around?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁吢 2024-07-15 01:07:53

使用此方法打印多个文档的效果并不像您所发现的那样好。

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

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

请参阅 http://msdn.microsoft.com/en-us/library/aa394363 .aspx 用于 Win32_Printer WMI 类。

Using this method to print multiple documents is not going to work good as you found.

Having it work is quite tricky but here is a general description of the solution.

I use System.Diagnostics.Process to print using myProcess.StartInfo.Verb = "Print"
Then I check the Status and State of printer queue in two steps to make sure that the printing is ready enough to be able to print the next document. Use WMI and ManagementObjectSearcher to enumerate the printer info using "SELECT * FROM Win32_Printer".
The logic is that I try to see if the spooling is started before continuing to print the next one.

See http://msdn.microsoft.com/en-us/library/aa394363.aspx for the Win32_Printer WMI class.

箹锭⒈辈孓 2024-07-15 01:07:53

我在 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;

I had the same problem using AcroPDF in Delphi.. then I figured out that when I "stop" the processo using a message, AcroPDF starts to print.

So I just create a modal TForm that closes itself after some seconds.

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

The TFormModal is this and I just insert a loading icon on the form to represents something like "printing".

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;
风蛊 2024-07-15 01:07:53

我们最终使用 Adob​​e 的 PDF Verifier 来进行我们自己的测试。 为了做到这一点,我们必须实际启动 acrobat 并使用 SendInput。

我非常有兴趣看看是否可以使用内部 API 来代替。

We ended up using Adobe's PDF Verifier for our own testing purposes. In order to do this we had to actually launch acrobat and manipulate it's interface programmatically using SendInput.

I would be very interested in seeing if it would be possible to use an internal API instead.

生生漫 2024-07-15 01:07:53

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

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

You can use this code to display any file with its appropriate software.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文