Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2010年05月05日] [更新 2014年08月31日] Delphi サンプルプログラム集
724_Adobe Acrobat オブジェクトの操作
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro +Adobe Acrobat Pro 9.5.5
開発環境にも,実行環境にも,Adobe Acrobat が必要
724_Acrobat_TAcroApp.zip [2,300 KB] 2014年08月31日版 (EXE 同梱)







Adobe Acrobat オブジェクトの操作


ワードやエクセルの操作同様,Adobe Acrobat もそのオブジェクト(OLE : Adobe では IAC と言っている) を生成して操作することができます.Delphi にはこれらのオブジェクトを操作するオブジェクトは用意されていません.タイプライブラリの取り込みで必要なユニットファイルを作成します.

このページのサンプルは,開発値環境にも実行環境にも (Adobe Reader ではなく) Adobe Acrobat がインストールされていなければ動作しません.これはワードやエクセルがインストールされていなければ,基本的にはその操作ができないのと同じです.
Adobe Acrobat がインストールされていない環境での PDF 文書の操作については,リンクの [720] [07_PDF 文書の作成や操作関係の参考リンク - Adobe サイト以外] を参考にしてください.

参考リンクの [PDF VBA (Excel) から Acrobat ... ] の記事は,Acrobat SDK を解析しながら作成したそうです.折角公開していただいているので,利用しない手はありません.





01_タイプライブラリの取り込み


このページのサンプルを利用するには,[タイプライブラリの取り込]で,Adobe Acroabat のタイプライブラリの取り込を行い,Acrobat_TLB.pas という名前のユニットを作成します.これがコンポーネントのファイルとなります.

ここでは,このコンポーネントを Delphi にあらかじめ用意してある dclusr.dpk というパッケージに登録 (インストール) するものとします.このパッケージをまだインストールしていない場合は,インストールしておきます.

このタイプライブラリの取り込みの記事は,Delphi 2010 の操作画像です.



図1
タイプライブラリの取り込
  • [コンポーネント]
  • [コンポーネントのインポート]
図2
追加
  • [登録済みのタイプライブラリ] にはおそらくないので [追加]で
図3
DLLまたはTLBを選択
  • Acrobat.dll を選択
  • Acrobat.tlb でもよい
    Acrobat.tlb はタイプライブラリファイルそのもの
図4
登録パレットの選択
  • 今回は [ActiveX] とした
  • 存在しない名前にすると作成される
  • [コンポーネントラッパーを生成する] にチェック]
  • [ユニットディレクトリ] はコンポーネントのファイルが出力される場所
    パスが通った場所にする
    今回はデフォルトのままとした
図5
登録先パッケージ
  • 今回は既存のパーパッケージ
図6
dclusr.dpk に登録
  • dclusr140.pbl は,dclusr.dpk のコンパイル済のファイル名
図7
[上書き保存] [ビルド]
  • [上書き保存]
  • [ビルド] または [再構築]
  • IDE を一度閉じて,再起動




02_PDF 文書を表示


Adobe Acrobat を起動して PDF 文書を表示します.表示ウィンドウの位置とサイズを指定するために,Acrobat のクラス名である AcrobatSDIWindow をウィンドウリストから検索してウィンドウハンドルを取得しています.このサンプルで設定した内容は,Acrobat の次回起動時にもこの設定が使用されます.本来は元の値を保存して,終了時は元に戻すべきでしょう.

フォームを閉じると,システムで開いている Acrobat 全てが閉じて終了となります.Button3 クリックでも Acrobat が閉じますが,システムには Acrobat.exe が残った状態となっています.

参考リンクの AcroExch.App 等はクラス識別子 (CLSID) です.
後述のように,CreateOleObject あるいは CreateComObject で PDF 関係のオブジェクトを生成する場合に使用します.
CreateOleObject または CreateComObject で PDF 関係のオブジェクトを生成した場合は,ConnectTo メソッドを実行する必要はありません.TAcroApp 等のクラスにもキャストできます.



図8
設計時画面
  • TAcroApp 関係コンポーネントを配置
図9
Button1 クリック
  • 表示文書は [ファイル] [プロパティ] のダイアログの [開き方] の倍率を全体表示にしてある
  • これは Power Point の画面ではない
図10
頁数は 47 になっている
図11
Button2 クリック
  • ツールバーが表示される
  • この動作はトグル

リスト1
PDF 文書を表示
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Acrobat_TLB, OleServer;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    AcroApp1: TAcroApp;
    AcroAVDoc1: TAcroAVDoc;
    AcroPDDoc1: TAcroPDDoc;
    Panel1: TPanel;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private 宣言 }
    AcroHandle : Cardinal;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

//AcroAppConst.pasは同梱の定数ユニット
uses AcroAppConst;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  ウィンドウハンドルからウィンドウのクラス名を取得する関数
//-----------------------------------------------------------------------------
function GetWindowClassNameStr(hWindow: HWND): String;
var
  Buffer : array[0..MAX_PATH-1] of Char;
  Len    : Integer;
begin
  FillChar(Buffer, SizeOf(Buffer), #0);
  Len := GetClassName(hWindow, Buffer, Length(Buffer));
  if Len > 0 then begin
    Result := Buffer;
  end else begin
    Result := '';
  end;
end;

//-----------------------------------------------------------------------------
//  アプリのウィンドウハンドルを取得するためのEnumWindowsのコールバック関数
//
//  Acrobatのトップウィンドのクラス名はAcrobatSDIWindow
//  この関数はWindowsが呼出すメッセージ処理なのでTFormのメンバーにはできない
//-----------------------------------------------------------------------------
function EnumWindowsProc(hTopWnd: HWND; lp: LPARAM): BOOL; stdcall;
var
  ClassName : String;
begin
  Result := True;

  //クラス名がAcrobatのトップウィンドウのものかクラス名で調査
  //取得できたら引数のlpにその値を代入してこれ以上の列挙はしない
  ClassName := GetWindowClassNameStr(hTopWnd);
  if UpperCase(ClassName) = UpperCase('AcrobatSDIWindow') then begin
    LPDWORD(lp)^ := hTopWnd;
    Result := False;
  end;
end;

//=============================================================================
//  このフォームを前面に表示
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  FormStyle := fsStayOnTop;
end;

//=============================================================================
//  このフォームを閉じる時はPDF文書も閉じてAcrobatを終了させる
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Button3Click(nil);
end;

//=============================================================================
//  ファイル選択ダイアログを表示してPDF文書を選択
//
//  ここで設定している位置サイズやメニューの表示は,Acrobatの次回起動時にも
//  この設定が使用されるので,本来は元に戻しておくべき
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile     : String;
  PageCount : Integer;
  Flag      : OleVariant;
begin
  with OpenDialog1 do begin
    InitialDir := ExtractFileDir(ParamStr(0));
    DefaultExt := 'PDF';
    Filter     := 'PDF|*.PDF';
    Options    := [ofReadOnly];
  end;

  if OpenDialog1.Execute then begin
    Update;
    AFile := OpenDialog1.FileName;

    //開いているのは閉じる
    AcroAVDoc1.Close(-1);
    AcroAVDoc1.Open(AFile, '');

    //AcroAVDoc1をTAcroAppのAVDocオブジェクトとする
    AcroAVDoc1.ConnectTo(AcroApp1.GetAVDoc(0) as CAcroAVDoc);

    //開いたドキュメントからPDDocオブジェクトを取得
    AcroPDDoc1.ConnectTo(AcroAVDoc1.GetPDDoc as CAcroPDDoc);
    //総頁数を取得して表示
    PageCount := AcroPDDoc1.GetNumPages;
    Panel1.Caption := '頁数 ' + IntToStr(PageCount);

    AcroAVDoc1.SetTitle('Acrobat テスト Presented by Mr.XRAY');
    //SetViewModeの5は本文のみの表示
    AcroAVDoc1.SetViewMode(5);

    //メニューバー,ツールバー,左側のツールバーも非表示にしてしまう
    Flag := 0;
    AcroApp1.SetPreferenceEx(avpShowMenuBar, Flag);
    AcroApp1.SetPreferenceEx(avpShowToolBar, Flag);
    AcroApp1.SetPreferenceEx(avpShowLeftToolBar, Flag);

    //ウィンドウの列挙
    //Acrobatのハンドルが取得できればAcroHandleにその値を返す
    //そのハンドルを使用してPDF文書の表示位置とサイズを変更
    EnumWindows(@EnumWindowsProc, LPARAM(@AcroHandle));
    if AcroHandle <> 0 then begin
      SetWindowPos(AcroHandle, 0, 0, 0, 800, 600, SWP_NOZORDER);
    end;

    //表示
    AcroApp1.Show;
  end;
end;

//=============================================================================
//  ツールバー表示のトグル動作
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  Flag : OleVariant;
  SetV : OleVariant;
begin
  Flag := AcroApp1.GetPreferenceEx(avpShowToolBar);
  if Flag = 'false' then begin
    SetV := 1;
  end else begin
    SetV := 0;
  end;
  AcroApp1.SetPreferenceEx(avpShowToolBar, SetV);
end;

//=============================================================================
//  PDF文書を閉じてAcrobatも閉じる
//  このサンプルはTAcroApp等のコンポーネントを配置している
//  したがって,アプリ起動時にそのインスタンスが生成される
//  このアプリを終了するまでシステムのプロセスにはAcrobat.exeが残ることになる
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
  //下の2行はCloseAllDocsがあれば本来は不要
  AcroAVDoc1.Close(1);
  AcroPDDoc1.Close;
  AcroApp1.CloseAllDocs;

  //Acrobatの終了.必ずHideメソッドと対で使用する
  AcroApp1.Hide;
  AcroApp1.Exit;
end;

end.




03_TPanel 上に PDF 文書を表示


フォームに配置した TPanel 上に PDF 文書を表示する例です.
この TPanel 上に表示する方法は,表示開始時は TPanel の Client 領域に表示されますが,フォームのサイズを変更しても表示サイズは変更されません.そこで Acrobat のウィンドウハンドルを取得して,そのウィンドウの位置とサイズをフォームの OnResize イベントで再設定しています.Acrobat を他のウィンドウ上に表示した場合のクラス名は,Amber External Window です.


図12
設計時画面
  • TAcroApp 関係コンポーネントを配置
  • [Button1] PDF 文書を開く
  • [Button2] 前のページを表示
  • [Button3] 次のページを表示
  • [Button4] 100 % 表示
  • [Button5] 描画領域幅に合わせて表示
  • [Button6] 印刷
図13
Button1 クリックしてPDF表示
  • くどいようだがこれは Power Point の画面ではない
図14
Button3 で頁を進めた画面
図15
Button4 で 100% 表示

リスト2
PDF 文書を TPanel 上に表示
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Acrobat_TLB, OleServer;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    AcroApp1: TAcroApp;
    AcroAVDoc1: TAcroAVDoc;
    AcroPDDoc1: TAcroPDDoc;
    AcroAVPageView1: TAcroAVPageView;
    Panel2: TPanel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Panel3: TPanel;
    OpenDialog1: TOpenDialog;
    Button5: TButton;
    Button6: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormResize(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
  private
    { Private 宣言 }
    AcroHandle : Cardinal;
    PageCount  : Integer;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

//AcroAppConst.pasは同梱の定数ユニット
uses AcroAppConst;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  ウィンドウハンドルからウィンドウのクラス名を取得する関数
//-----------------------------------------------------------------------------
function GetWindowClassNameStr(hWindow: HWND): String;
var
  Buffer : array[0..MAX_PATH-1] of Char;
  Len    : Integer;
begin
  FillChar(Buffer, SizeOf(Buffer), #0);
  Len := GetClassName(hWindow, Buffer, Length(Buffer));
  if Len > 0 then begin
    Result := Buffer;
  end else begin
    Result := '';
  end;
end;

//-----------------------------------------------------------------------------
//  ウィンドウハンドルを取得するためのコールバック関数
//  OpenInWindowExで表示した場合のAcrobatのクラス名はAmber External Window
//  このクラス名のウィンドウを検索する
//  この関数はWindowsが呼出すメッセージ処理なのでTFormのメンバーにはできない
//-----------------------------------------------------------------------------
function EnumChildWindowsProc(hWindow: HWND; lp: LPARAM): BOOL; stdcall;
var
  ClassName : String;
begin
  Result := True;

  ClassName := GetWindowClassNameStr(hWindow);
  if UpperCase(ClassName) = UpperCase('Amber External Window') then begin
    //取得したハンドル値を呼出し側で使用するために,引数のlpに代入
    //取得したらそれ以上の列挙は不要なのでResult := Falseにして列挙終了
    LPDWORD(lp)^ := hWindow;
    Result := False;
  end;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatも閉じる
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //下の2行はCloseAllDocsがあれば本来は不要
  AcroAVDoc1.Close(1);
  AcroPDDoc1.Close;
  AcroApp1.CloseAllDocs;

  //Acrobatの終了.必ずHideメソッドと対で使用する
  AcroApp1.Hide;
  AcroApp1.Exit;
end;

//=============================================================================
//  フォームをリサイズしたら表示しているAcrobatもリサイズ
//  OpenInWindowExで表示してもリサイズは自動ではない
//=============================================================================
procedure TForm1.FormResize(Sender: TObject);
begin
  if AcroHandle <> 0 then begin
    SetWindowPos(AcroHandle,
                 0,
                 0,
                 0,
                 Panel1.Width,
                 Panel1.Height,
                 SWP_NOZORDER or SWP_NOMOVE );
  end;
end;

//=============================================================================
//  ファイル選択ダイアログを表示してPDF文書を選択
//
//  ここで設定している位置サイズやメニューの表示は,Acrobatの次回起動時にも
//  この設定が使用されるので,本来は元に戻しておくべき
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile  : String;
  PageNo : Integer;
begin
  with OpenDialog1 do begin
    InitialDir := ExtractFileDir(ParamStr(0));
    DefaultExt := 'PDF';
    Filter     := 'PDF|*.PDF';
    Options    := [ofReadOnly];
  end;

  if OpenDialog1.Execute then begin
    Update;
    AFile := OpenDialog1.FileName;

    //Panel1上にPDF文書を表示
    //開いているのは閉じる
    AcroAVDoc1.Close(-1);
    AcroAVDoc1.OpenInWindowEx(AFile,
                              Panel1.Handle,
                              AV_PAGE_VIEW,
                              0,
                              0,
                              PDDontCare,
                              AVZoomFitPage,
                              100,
                              100,
                              0);

    //AcroAVDoc1をTAcroAppのAVDocオブジェクトとする
    AcroAVDoc1.ConnectTo(AcroApp1.GetAVDoc(0) as CAcroAVDoc);

    //開いたドキュメントからPDDocオブジェクトを取得
    AcroPDDoc1.ConnectTo(AcroAVDoc1.GetPDDoc as CAcroPDDoc);
    //後の操作用にAcroAVPageViewオブジェクトを取得しておく
    AcroAVPageView1.ConnectTo(AcroAVDoc1.GetAVPageView as CAcroAVPageView);

    //現在の頁番号(最初の頁番号は0)と総頁数を取得して表示
    PageNo         := AcroAVPageView1.GetPageNum;
    PageCount      := AcroPDDoc1.GetNumPages;
    Panel3.Caption := IntToStr(PageNo + 1) +' / ' + IntToStr(PageCount);

    Self.Caption := AcroAVDoc1.GetTitle;

    //AcrobatはPanel1上に表示しているので.このTPanelの子ウィンドウを検索し
    //Panel1上のAcrobatのハンドルをAcroHandleに取得する
    EnumChildWindows(Panel1.Handle, @EnumChildWindowsProc, LPARAM(@AcroHandle));
  end;
end;

//=============================================================================
//  前の頁を表示
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  PageNo : Integer;
begin
  if AcroPDDoc1.GetNumPages < 0 then exit;

  PageNo  := AcroAVPageView1.GetPageNum;
  if (PageNo + 1) > 1 then begin
    AcroAVPageView1.GoTo_(PageNo - 1);
    Panel3.Caption := IntToStr(PageNo) +' / ' + IntToStr(PageCount);
  end;
end;

//=============================================================================
//  次の頁を表示
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
  PageNo : Integer;
begin
  if AcroPDDoc1.GetNumPages < 0 then exit;

  PageNo := AcroAVPageView1.GetPageNum;
  if (PageNo + 1) < PageCount then begin
    AcroAVPageView1.GoTo_(PageNo + 1);
    Panel3.Caption := IntToStr(PageNo + 2) +' / ' + IntToStr(PageCount);
  end;
end;

//=============================================================================
//  100%表示にする
//=============================================================================
procedure TForm1.Button4Click(Sender: TObject);
begin
  if AcroPDDoc1.GetNumPages < 0 then exit;

  AcroAVPageView1.ZoomTo(AVZoomNoVary, 100);
end;

//=============================================================================
//  描画領域の幅に合わせた表示にする
//=============================================================================
procedure TForm1.Button5Click(Sender: TObject);
begin
  if AcroPDDoc1.GetNumPages < 0 then exit;

  AcroAVPageView1.ZoomTo(AVZoomFitVisibleWidth, 0);
end;

//=============================================================================
//  印刷
//  印刷開始と終了頁が間違っていると印刷しないので注意
//
//  [備考]
//  Windows XP(SP3) + Delphi2010(UP5) Pro + Adobe Acrobat Pro 8.1.5
//  の環境下では,印刷の際に別のAcrobatのウィンドが表示され,印刷が終了しても
//  閉じない
//  印刷メソッド実行後,AcroApp1.Hideを実行すれば閉じる(見えなくなる?)
//=============================================================================
procedure TForm1.Button6Click(Sender: TObject);
var
  nFirstPage      : Integer;
  nLastPage       : Integer;
  nPSLevel        : Integer;
  bBinaryOk       : Integer;
  bShrinkToFit    : Integer;
  bReverse        : Integer;
  bFarEastFontOpt : Integer;
  bEmitHalftones  : Integer;
  iPageOption     : Integer;
begin
  if AcroPDDoc1.GetNumPages < 0 then exit;

  nFirstPage      := 0;
  nLastPage       := PageCount - 1;
  nPSLevel        := 3;
  bBinaryOk       := 1;
  bShrinkToFit    := 0;
  bReverse        := 0;
  bFarEastFontOpt := 0;
  bEmitHalftones  := 0;
  iPageOption     := -3;

  AcroAVDoc1.PrintPagesSilentEx(nFirstPage,
                                nLastPage,
                                nPSLevel,
                                bBinaryOk,
                                bShrinkToFit,
                                bReverse,
                                bFarEastFontOpt,
                                bEmitHalftones,
                                iPageOption);
end;

end.




04_Adobe Acrobat オブジェクトの実行時 ( 動的 ) 生成


Acrobat 関係のオブジェクトを実行時 (動的) に生成する場合の例です.
テスト内容は最初のサンプルと同じです.


図16
設計時画面

リスト3
Acrobat 関係オブジェクトの実行時生成
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Acrobat_TLB, OleServer;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Panel1: TPanel;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private 宣言 }
    AcroHandle : Cardinal;
    AAcroApp: TAcroApp;
    AAcroAVDoc: TAcroAVDoc;
    AAcroPDDoc: TAcroPDDoc;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

//AcroAppConst.pasは同梱の定数ユニット
uses AcroAppConst;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  ウィンドウハンドルからウィンドウのクラス名を取得する関数
//-----------------------------------------------------------------------------
function GetWindowClassNameStr(hWindow: HWND): String;
var
  Buffer : array[0..MAX_PATH-1] of Char;
  Len    : Integer;
begin
  FillChar(Buffer, SizeOf(Buffer), #0);
  Len := GetClassName(hWindow, Buffer, Length(Buffer));
  if Len > 0 then begin
    Result := Buffer;
  end else begin
    Result := '';
  end;
end;

//-----------------------------------------------------------------------------
//  アプリのウィンドウハンドルを取得するためのEnumWindowsのコールバック関数
//
//  Acrobatのトップウィンドのクラス名はAcrobatSDIWindow
//  この関数はWindowsが呼出すメッセージ処理なのでTFormのメンバーにはできない
//-----------------------------------------------------------------------------
function EnumWindowsProc(hTopWnd: HWND; lp: LPARAM): BOOL; stdcall;
var
  ClassName : String;
begin
  Result := True;

  //クラス名がAcrobatのトップウィンドウのものかクラス名で調査
  //取得できたら引数のlpにその値を代入してこれ以上の列挙はしない
  ClassName := GetWindowClassNameStr(hTopWnd);
  if UpperCase(ClassName) = UpperCase('AcrobatSDIWindow') then begin
    LPDWORD(lp)^ := hTopWnd;
    Result := False;
  end;
end;

//=============================================================================
//  このフォームを前面に表示
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  FormStyle := fsStayOnTop;
end;

//=============================================================================
//  このフォームを閉じる時はPDF文書も閉じてAcrobatを終了させる
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Button3Click(nil);
end;

//=============================================================================
//  ファイル選択ダイアログを表示してPDF文書を選択
//
//  ここで設定している位置サイズやメニューの表示は,Acrobatの次回起動時にも
//  この設定が使用されるので,本来は元に戻しておくべき
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile     : String;
  PageCount : Integer;
  Flag      : OleVariant;
begin
  with OpenDialog1 do begin
    InitialDir := ExtractFileDir(ParamStr(0));
    DefaultExt := 'PDF';
    Filter     := 'PDF|*.PDF';
    Options    := [ofReadOnly];
  end;

  if OpenDialog1.Execute then begin
    Update;
    AFile := OpenDialog1.FileName;

    if not Assigned(AAcroApp) then begin
      AAcroApp   := TAcroApp.Create(Self);
      AAcroAVDoc := TAcroAVDoc.Create(Self);
      AAcroPDDoc := TAcroPDDoc.Create(Self);
    end;

    //開いているのは閉じる
    AAcroAVDoc.Close(-1);
    AAcroAVDoc.Open(AFile, '');

    //AcroAVDoc1をTAcroAppのAVDocオブジェクトとする
    AAcroAVDoc.ConnectTo(AAcroApp.GetAVDoc(0) as CAcroAVDoc);

    //開いたドキュメントからPDDocオブジェクトを取得
    AAcroPDDoc.ConnectTo(AAcroAVDoc.GetPDDoc as CAcroPDDoc);
    //総頁数を取得して表示
    PageCount := AAcroPDDoc.GetNumPages;
    Panel1.Caption := '頁数 ' + IntToStr(PageCount);

    AAcroAVDoc.SetTitle('Acrobat テスト Presented by Mr.XRAY');
    //SetViewModeの5は本文のみの表示
    AAcroAVDoc.SetViewMode(5);

    //メニューバー,ツールバー,左側のツールバーも非表示にしてしまう
    Flag := 0;
    AAcroApp.SetPreferenceEx(avpShowMenuBar, Flag);
    AAcroApp.SetPreferenceEx(avpShowToolBar, Flag);
    AAcroApp.SetPreferenceEx(avpShowLeftToolBar, Flag);


    //ウィンドウの列挙
    //Acrobatのハンドルが取得できればAcroHandleにその値を返す
    //そのハンドルを使用してPDF文書の表示位置とサイズを変更
    EnumWindows(@EnumWindowsProc, LPARAM(@AcroHandle));
    if AcroHandle <> 0 then begin
      SetWindowPos(AcroHandle, 0, 0, 0, 800, 600, SWP_NOZORDER);
    end;

    //表示
    AAcroApp.Show;
  end;
end;

//=============================================================================
//  ツールバー表示のトグル動作
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  Flag : OleVariant;
  SetV : OleVariant;
begin
  if Assigned(AAcroApp) then begin
    Flag := AAcroApp.GetPreferenceEx(avpShowToolBar);
    if Flag = 'false' then begin
      SetV := 1;
    end else begin
      SetV := 0;
    end;
    AAcroApp.SetPreferenceEx(avpShowToolBar, SetV);
  end;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatも閉じる
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
begin
  if Assigned(AAcroApp) then begin
    //下の2行はCloseAllDocsがあれば本来は不要
    AAcroAVDoc.Close(1);
    AAcroPDDoc.Close;
    AAcroApp.CloseAllDocs;

    //Acrobatの終了.必ずHideメソッドと対で使用する
    AAcroApp.Hide;
    AAcroApp.Exit;

    FreeAndNil(AAcroApp);
    FreeAndNil(AAcroAVDoc);
    FreeAndNil(AAcroPDDoc);
  end;
end;

end.




05_PDF 文書を他の形式のファイルに変換


Acrobat の JavaScript API を使用して,各種のファイル形式に変換するサンプルです.
TIFF と JPEG 画像への変換状態はいいようですが,ワードや HTML ファイルへの変換では,画像と文字列の位置も文字列 (テキスト) もかなり崩れてしまいます.この結果は,Adobe Acrobat から [ファイル] [書き出し] で保存しても同じです.
PDF 文書からテキストのみを取り出すサンプルは,[434_ワードやエクセルのテキスト抽出] も参考にしてください.

JSObject を使用したプログラムは,参考リンクの記事にあるように,Acrobat JavaScript の説明書を見ながらの作業と動作確認となります.このファイル形式の変換以外にも多くの機能があります.
JSObject は,Acrobat_TLB.pas 内に定義はありません.OleVariant 型で扱います.



図17
設計時画面
  • TAcroApp オブジェクト類は実行時生成
  • [Button1] PDF 文書を開く
  • [Button2] ワード文書として保存
  • [Button3] テキスト文書で保存
  • [Button4] HTML 文書として保存
  • [Button5] TIFF 画像で保存
  • [Button6] JPEG 画像で保存
図18
ワード文書に変換
  • 画像も文字も崩れてしまう
図19
テキスト文書に変換
  • 取り出せるのはテキストのみ
図20
HTML 文書に変換
  • 作成されるファイルは 1 つだが各頁へのリンクとなっている
  • 画像は images というフォルダが自動的に作成されてそこに格納される
  • 各ページの内容は崩れている
図21
TIFF 画像に変換
  • Windows フォトビューアーで表示中
  • 各頁ごとにファイルができる
  • TIFF と JPEG 画像への変換はかなり良い
図22
JPEG 画像に変換
  • Windows フォトビューワで表示中
  • 各ページごとにファイルができる

リスト4
PDF 文書を他の形式のファイルに変換して保存
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, Acrobat_TLB, OleServer;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    btnClose: TButton;
    Panel1: TPanel;
    OpenDialog1: TOpenDialog;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private 宣言 }
    AAcroApp: TAcroApp;
    AAcroAVDoc: TAcroAVDoc;
    AAcroPDDoc: TAcroPDDoc;
    AAcroJSObj : OleVariant;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  このフォームを閉じる時はPDF文書も閉じてAcrobatを終了させる
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  btnCloseClick(nil);
end;

//=============================================================================
//  ファイル選択ダイアログを表示してPDF文書を選択
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile     : String;
  PageCount : Integer;
begin
  with OpenDialog1 do begin
    InitialDir := ExtractFileDir(ParamStr(0));
    DefaultExt := 'PDF';
    Filter     := 'PDF|*.PDF';
    Options    := [ofReadOnly];
  end;

  if OpenDialog1.Execute then begin
    Update;
    AFile := OpenDialog1.FileName;

    if not Assigned(AAcroApp) then begin
      AAcroApp   := TAcroApp.Create(Self);
      AAcroAVDoc := TAcroAVDoc.Create(Self);
      AAcroPDDoc := TAcroPDDoc.Create(Self);
    end;

    //Panel1上にPDF文書を表示
    //開いているのは閉じる
    AAcroAVDoc.Close(-1);
    AAcroAVDoc.Open(AFile, '');

    //AcroAVDoc1をTAcroAppのAVDocオブジェクトとする
    AAcroAVDoc.ConnectTo(AAcroApp.GetAVDoc(0) as CAcroAVDoc);

    //開いたドキュメントからPDDocオブジェクトを取得
    AAcroPDDoc.ConnectTo(AAcroAVDoc.GetPDDoc as CAcroPDDoc);
    //総頁数を取得して表示
    PageCount := AAcroPDDoc.GetNumPages;
    Panel1.Caption := '頁数 ' + IntToStr(PageCount);

    //JavaScriptオブジェクトを取得
    AAcroJSObj := AAcroPDDoc.GetJSObject;
  end;
end;

//=============================================================================
//  PDF文書をワード文書として保存
//  必ずしも成功するとは限らない.成功しても文字や画像が正しく反映されるとは限
//  らない
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  SaveFileName : String;
begin
  if not Assigned(AAcroApp) then exit;
  if AAcroPDDoc.GetNumPages <= 0 then exit;

  Screen.Cursor := crHourGlass;
  try
    SaveFileName := ExtractFilePath(ParamStr(0)) + 'Test.doc';
    AAcroJSObj.SaveAs(SaveFileName , 'com.adobe.acrobat.doc');
  except
  end;
  Screen.Cursor := crDefault;
end;

//=============================================================================
//  PDF文書をテキストファイルとして保存
//  テキストがない場合は..(要確認)
//  画像があるPDFはテキストのみの保存となる
//=============================================================================
procedure TForm1.Button3Click(Sender: TObject);
var
  SaveFileName : String;
begin
  if not Assigned(AAcroApp) then exit;
  if AAcroPDDoc.GetNumPages <= 0 then exit;

  Screen.Cursor := crHourGlass;
  try
    SaveFileName := ExtractFilePath(ParamStr(0)) + 'Test.txt';
    AAcroJSObj.SaveAs(SaveFileName , 'com.adobe.acrobat.plain-text');
  except
  end;
  Screen.Cursor := crDefault;
end;

//=============================================================================
//  PDF文書をHTML 4.01形式のHTMLファイルとして保存
//  HTMLファイルはPDFが何頁あっても1つだけ生成される
//  画像はimagesというフォルダが自動的に作成されてその中に保存される
//  PDF文書によっては失敗して例外でストップする場合あり(tryでは捕捉不可)
//=============================================================================
procedure TForm1.Button4Click(Sender: TObject);
var
  SaveFileName : String;
begin
  if not Assigned(AAcroApp) then exit;
  if AAcroPDDoc.GetNumPages <= 0 then exit;

  Screen.Cursor := crHourGlass;
  try
    SaveFileName := ExtractFilePath(ParamStr(0)) + 'Test401.html';
    AAcroJSObj.SaveAs(SaveFileName , 'com.adobe.acrobat.html-4-01-css-1-00');
  except
  end;
  Screen.Cursor := crDefault;
end;

//=============================================================================
//  PDF文書をTIFF画像ファイルとして保存
//  複数頁のPDFは1頁に付き1つのTIFF画像ファイルとなる
//=============================================================================
procedure TForm1.Button5Click(Sender: TObject);
var
  SaveFileName : String;
begin
  if not Assigned(AAcroApp) then exit;
  if AAcroPDDoc.GetNumPages <= 0 then exit;

  Screen.Cursor := crHourGlass;
  try
    SaveFileName := ExtractFilePath(ParamStr(0)) + 'TIFFImages\Test.tif';
    ForceDirectories(ExtractFileDir(SaveFileName));
    AAcroJSObj.SaveAs(SaveFileName, 'com.adobe.acrobat.tiff');
  except
  end;
  Screen.Cursor := crDefault;
end;

//=============================================================================
//  PDF文書をJPEG画像ファイルとして保存
//  複数頁のPDFは1頁に付き1つのJPEG画像ファイルとなる
//=============================================================================
procedure TForm1.Button6Click(Sender: TObject);
var
  SaveFileName : String;
begin
  if not Assigned(AAcroApp) then exit;
  if AAcroPDDoc.GetNumPages <= 0 then exit;

  Screen.Cursor := crHourGlass;
  try
    SaveFileName := ExtractFilePath(ParamStr(0)) + 'JPEGImages\Test.jpg';
    ForceDirectories(ExtractFileDir(SaveFileName));
    AAcroJSObj.SaveAs(SaveFileName, 'com.adobe.acrobat.jpeg');
  except
  end;
  Screen.Cursor := crDefault;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatも閉じる
//=============================================================================
procedure TForm1.btnCloseClick(Sender: TObject);
begin
  if Assigned(AAcroApp) then begin
    //下の2行はCloseAllDocsがあれば本来は不要
    AAcroAVDoc.Close(1);
    AAcroPDDoc.Close;
    AAcroApp.CloseAllDocs;

    //Acrobatの終了.必ずHideメソッドと対で使用する
    AAcroApp.Hide;
    AAcroApp.Exit;

    FreeAndNil(AAcroApp);
    FreeAndNil(AAcroAVDoc);
    FreeAndNil(AAcroPDDoc);
  end;
end;

end.




06_CreateOleObject と CreateComObject


ワードやエクセルと同じように Acrobat の OLE オブジェクトを,CreateOleObject で生成することもできます.以下のコードはその例です.Acrobat_TLB.pas 内をみると分かりますが,これらのコードは全て同じ動作をします.
これらの方法は,オブジェクト間に ConnectTo を使わず,キャストだけでいいので,ある意味では使いやすいかも知れません.


リスト5
Acrobat 関係オブジェクトを CreateOleObject で生成する例 - CAcroApp にキャスト
//=============================================================================
//  Acrobarを起動してPDF文書を表示
//
//  App,AcroAVDoc,AcroPDDoc等はAcrobat_TLBで定義されているので使用しない
//  usesにAcrobat_TLBが必要
//  CreateComObjectにはusesにComObjが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile : String;
begin
  AFile := ExtractFilePath(ParamStr(0)) + 'Test Acro.pdf';

  AAcroApp   := CreateOleObject('AcroExch.App')   as CAcroApp;
  AAcroAVDoc := CreateOleObject('AcroExch.AVDOC') as CAcroAVDoc;
  AAcroPDDoc := CreateOleObject('AcroExch.PDDOC') as CAcroPDDoc;

  //PDF文書を開く
  AAcroAVDoc.Open(AFile, '');

  //AcroPDDocオブジェクトを取得してPDFの頁数を表示
  AAcroPDDoc := AAcroAVDoc.GetPDDoc as CAcroPDDoc;
  Label1.Caption := IntToStr(AAcroPDDoc.GetNumPages);

  //Showメソッドを実行しないと表示されない
  AAcroApp.Show;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatを終了
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  AAcroAVDoc.Close(0);
  AAcroPDDoc.Close;
  AAcroApp.CloseAllDocs;

  AAcroAVDoc := nil;
  AAcroPDDoc := nil;

  AAcroApp.Hide;
  AAcroApp.Exit;
  AAcroApp := nil;
end;


リスト6
Acrobat 関係オブジェクトを CreateOleObject で生成する例 - AcroApp にキャスト
//=============================================================================
//  Acrobarを起動してPDF文書を表示
//
//  App,AcroAVDoc,AcroPDDoc等はAcrobat_TLBで定義されているので使用しない
//  usesにAcrobat_TLBが必要
//  CreateComObjectにはusesにComObjが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile : String;
begin
  AFile := ExtractFilePath(ParamStr(0)) + 'Test Acro.pdf';

  AAcroApp   := CreateOleObject('AcroExch.App')   as AcroApp;
  AAcroAVDoc := CreateOleObject('AcroExch.AVDOC') as AcroAVDoc;
  AAcroPDDoc := CreateOleObject('AcroExch.PDDOC') as AcroPDDoc;

  //PDF文書を開く
  AAcroAVDoc.Open(AFile, '');

  //AcroPDDocオブジェクトを取得してPDFの頁数を表示
  AAcroPDDoc := AAcroAVDoc.GetPDDoc as AcroPDDoc;
  Label1.Caption := IntToStr(AAcroPDDoc.GetNumPages);

  //Showメソッドを実行しないと表示されない
  AAcroApp.Show;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatを終了
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  AAcroAVDoc.Close(1);
  AAcroPDDoc.Close;
  AAcroApp.CloseAllDocs;

  AAcroAVDoc := nil;
  AAcroPDDoc := nil;

  AAcroApp.Hide;
  AAcroApp.Exit;
  AAcroApp := nil;
end;


リスト7
Acrobat 関係オブジェクトを CreateComObject で生成する例
//=============================================================================
//  Acrobarを起動してPDF文書を表示
//
//  App,AcroAVDoc,AcroPDDoc等はAcrobat_TLBで定義されているので使用しない
//  usesにAcrobat_TLBが必要
//  CreateComObjectにはusesにComObjが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile : String;
begin
  AFile := ExtractFilePath(ParamStr(0)) + 'Test Acro.pdf';

  AAcroApp   := CreateComObject(CLASS_AcroApp)   as AcroApp;
  AAcroAVDoc := CreateComObject(CLASS_AcroAVDoc) as AcroAVDoc;
  AAcroPDDoc := CreateComObject(CLASS_AcroPDDoc) as AcroPDDoc;

  //PDF文書を開く
  AAcroAVDoc.Open(AFile, '');

  //AcroPDDocオブジェクトを取得してPDFの頁数を表示
  AAcroPDDoc := AAcroAVDoc.GetPDDoc as AcroPDDoc;
  Label1.Caption := IntToStr(AAcroPDDoc.GetNumPages);

  //Showメソッドを実行しないと表示されない
  AAcroApp.Show;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatを終了
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  AAcroAVDoc.Close(1);
  AAcroPDDoc.Close;
  AAcroApp.CloseAllDocs;

  AAcroAVDoc := nil;
  AAcroPDDoc := nil;

  AAcroApp.Hide;
  AAcroApp.Exit;
  AAcroApp := nil;
end;


リスト8
Acrobat 関係オブジェクトを OleVariant 型で扱う場合
//=============================================================================
//  Acrobarを起動してPDF文書を表示
//  各オブジェクトをOleVariantで扱う場合の例
//
//  App,AcroAVDoc,AcroPDDoc等はAcrobat_TLBで定義されているので使用しない
//  usesにAcrobat_TLBが必要
//  CreateComObjectにはusesにComObjが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  AFile : String;
begin
  AFile := ExtractFilePath(ParamStr(0)) + 'Test Acro.pdf';

  //OleVariantで使用する場合はキャストは不要だがコード補完機能は使用不可
  AAcroApp   := CreateOleObject('AcroExch.App');
  AAcroAVDoc := CreateOleObject('AcroExch.AVDOC');
  AAcroPDDoc := CreateOleObject('AcroExch.PDDOC');

  //PDF文書を開く
  AAcroAVDoc.Open(AFile, '');

  //AcroPDDocオブジェクトを取得してPDFの頁数を表示
  //OleVariantではキャスト不要
  AAcroPDDoc := AAcroAVDoc.GetPDDoc;
  Label1.Caption := IntToStr(AAcroPDDoc.GetNumPages);

  //Showメソッドを実行しないと表示されない
  AAcroApp.Show;
end;

//=============================================================================
//  PDF文書を閉じてAcrobatを終了
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  AAcroAVDoc.Close(1);
  AAcroPDDoc.Close;
  AAcroApp.CloseAllDocs;

  //OleVariantで使用する場合はUnassigned
  AAcroAVDoc := Unassigned;
  AAcroPDDoc := Unassigned;

  AAcroApp.Hide;
  AAcroApp.Exit;
  AAcroApp := Unassigned;
end;