「Microsoft Print to PDF」でPDF出力
Windows 10 には、「Microsoft Print to PDF」が搭載され、手軽にPDF生成できますが、Delphiでも、この機能を使い、「印刷結果を名前を付けて保存」ダイアログを出さずにPDF生成できないかな・・と思っていたら、
Microsoft Print to PDF で C/C++ コードから出力ファイル名を指定する方法
の記事を見つけたので、これを参考に、コードを書いてみたいと思います。
印刷プログラムを書いてみよう
まずは、
Delphi Tips - TPrinter オブジェクト
にある例を参考にして、印刷プログラムのコードを書いてみます。
uses節に Printers (最近のDelphiだと、Vcl.Printers)を追加し、
フォームにボタンを追加し、OnClickイベントに以下のコードを入力します。
procedure TForm1.Button1Click(Sender: TObject);
begin
with Printer do
begin
Title := 'プリントテスト';
BeginDoc;
Canvas.TextOut(10, 10, 'プリントテスト ページ1');
NewPage;
Canvas.TextOut(10, 10, 'プリントテスト ページ2');
EndDoc;
end;
end;
コンパイル後、ボタンをクリックして、印刷されるのを確認します。
「Microsoft Print to PDF」を使い、PDF出力するように修正しよう
プリンタを「Microsoft Print to PDF」に指定し、出力するPDFファイルを指定して、「印刷結果を名前を付けて保存」ダイアログを出さずにPDFファイルを生成します。
ボタンのOnClickイベントにコードを追加します。
procedure TForm1.Button1Click(Sender: TObject);
var
idx: Integer;
PdfFileName: String;
DeviceName, DriverName, PortName: array[0..MAX_PATH - 1] of Char;
DeviceMode: THandle;
begin
PdfFileName := ExtractFilePath(Application.ExeName) + 'test.pdf';
with Printer do
begin
idx := Printers.IndexOf('Microsoft Print to PDF');
if idx < 0 then exit;
PrinterIndex := idx;
GetPrinter(DeviceName, DriverName, PortName, DeviceMode);
SetPrinter(DeviceName, DriverName, PChar(PdfFileName), 0);
end;
with Printer do
begin
Title := 'プリントテスト';
BeginDoc;
Canvas.TextOut(10, 10, 'プリントテスト ページ1');
NewPage;
Canvas.TextOut(10, 10, 'プリントテスト ページ2');
EndDoc;
end;
end;
コンパイル後、ボタンをクリックすると、実行プログラムがあるフォルダにPDFファイルが出力されているのを確認します。
生成したPDFファイルを確認してみよう
生成したPDFファイルを、Adobe Acrobat Readerで表示してみます。
メニュー[ファイル]-[プロパティ]で「文書のプロパティ」を表示します。
PrinterのTitleプロパティに格納した文字列が、タイトル欄に表示されるのですが、
日本語だと文字化けするのは、仕様みたいです。
最後に
「Microsoft Print to PDF」が表示する「印刷結果を名前を付けて保存」ダイアログの、最初に表示するフォルダは、プログラムから制御できないみたいですが、今回のやり方を使うと、TSaveDialogを使って「名前を付けて保存」ダイアログを使用することで、最初に表示するフォルダを設定する場合などにも使えそうです。
また、LightReport2など、TPrinterを使用しているコンポーネントでも、今回のやり方を使って、PDF出力機能を追加したりできそうですね。
2020/12/08 追記
Windows 10の設定で、「Windows で通常使うプリンターを管理する」がONの場合、これを実行した後、(別のアプリなどで)印刷するとき、プリンターが「Microsoft Print to PDF」になってしまうので、対策が必要かもしれません。