2017年3月7日

Adobe Reader(X以降)で指定したファイルの指定したページを開く

以前Adobe Acrobat/Readerで指定したPDFファイルの指定したページを開く方法について書きましたが、コメントでおかぽんさんからAdobe Reader X以降ではこの方法が使えなくなっているとの指摘をいただきました。

...DDEを使った方法ですが、Acrobat X から、DDEのサービス名が変更されています。...
調べてみると、Actobat/ReaderのVersion 10(X)以降で、DDEのサービス名が Acroview + [A|R] + <MajorVersion> に変更されたことが原因とのことです。というわけでこれに対応してみました。
uses
{$IF RTLVersion >= 23.00}
  Winapi.Windows, System.SysUtils, System.Win.Registry, System.AnsiStrings,
  Vcl.DdeMan;
{$ELSE}
  Windows, SysUtils, Registry, {$IFDEF UNICODE}AnsiStrings, {$ENDIF}DdeMan;
{$IFEND}

function GetAcrobatPathname: String;
begin

  with TRegistry.Create do
  begin
    try
      RootKey := HKEY_CLASSES_ROOT;
      OpenKeyReadOnly('Software\Adobe\Acrobat\Exe');
      try
        Result := AnsiDequotedStr(ReadString(''),'"');

      finally
        CloseKey;
      end;

    finally
      Free;
    end;
  end;

end;

procedure OpenPDF(const Filename: String; Page: Integer);
const
  CDdeCommand: AnsiString = '[DocOpen("%s")][DocGoTo(NULL,%d)]';
var
  Macro: AnsiString;
  Pathname: String;
  ServiceName: String;
  MajorVersion: Integer;
  AcrobatType: String;
begin

  Macro := {$IFDEF UNICODE}{$IF RTLVersion >= 23.00}System.{$IFEND}AnsiStrings.{$ENDIF}
           Format(CDdeCommand,[Filename,Page - 1]);

  Pathname := GetAcrobatPathname;

  ServiceName := 'Acroview';
  MajorVersion := GetFileVersion(Pathname) shr 16;
  if MajorVersion >= 10 then
  begin
    if CompareText(ExtractFileName(Pathname),'AcroRd32.exe') = 0 then
    begin
      AcrobatType := 'R';
    end
    else
    begin
      AcrobatType := 'A';
    end;

    ServiceName := ServiceName + Format('%s%d',[AcrobatType,MajorVersion]);
  end;

  with TDdeClientConv.Create(nil) do
  begin
    try
      ConnectMode := ddeManual;
      ServiceApplication := ChangeFileExt(Pathname,'');
      SetLink(ServiceName,'Control');
      if (OpenLink or ((MajorVersion >= 15) and OpenLink)) = True then
      begin
        ExecuteMacro(PAnsiChar(Macro),False);
        CloseLink;
      end;

    finally
      Free;
    end;
  end;

end;
Acrobat/Readerの実行ファイルの場所をレジストリの"HKEY_CLASSES_ROOT\Software\Adobe\Acrobat\Exe"から取得し、SysUtils.GetFileVersionで問い合わせたバージョン情報の上位16ビット(メジャーバージョン)とファイル名からサービス名を組み立て、DDEをTDdeClientConv.OpenLinkで呼び出してTDdeClientConv.ExecuteMacroでマクロ実行することでファイルを開きページを移動する、という手順になります。またAcrobat/Reader DCの場合TDdeClientConv.OpenLinkの内部でWinExec(en)を使用して起動した直後にDdeConnect(en)を呼び出すと失敗するようなので、リトライするようにしています。

おかぽんさん、情報ありがとうございました。

Adobe Reader(X以降)で指定したファイルの指定したページを開く(Gist)

0 件のコメント: