Windows 10 標準装備の仮想プリンタ Microsoft Print to PDF ですが、作成されるPDFファイル名をアプリケーションプログラムのコードから指定できないか探していたところ、以下を見つけました。
How to programmatically print to PDF file without prompting for filename in C# using the Microsoft Print To PDF printer that comes with Windows 10
https://stackoverflow.com/questions/31896952/how-to-programmatically-print-to-pdf-file-without-prompting-for-filename-in-c-sh
C/C++ から Windwos API を直接呼び出している場合は、CreateDC の第3パラメータ DOCINFO 構造体の3つ目のメンバ lpszOutput にデフォルトの "PORTPROMPT:" ではなく出力したいファイル名を指定すればいいです。
DOCINFO di = { sizeof(di), "テストDocName" };
di.lpszOutput = "C:\\HOGE\\HOGEHOGE.PDF";
OWLNext の場合は、TPrinter インスタンスにメンバ関数 GetData を呼び出して取得する TPrintDialog::TData クラスインスタンスに SetDevNames で設定するときの第3パラメータに、出力したいファイル名を指定すればいいです。OWLNext はそのデータを元に TCreatedDC::TCreatedDC にて、Windows API 関数 CreateDC を呼び出すようになっています。
TPrinter printer;
printer.GetData()->SetDevNames("winspool", "Microsoft Print to PDF", "C:\\HOGE\\HOGEHOGE.PDF");
VC141 + OWLNext6.44.2 で動作するサンプルコードができましたので載せておきます。
#define _USE_MATH_DEFINES
#define _OWLPCH
#include <owl/pch.h>
#pragma hdrstop
#include <owl/printer.h>
#include <owl/printdia.h>
#include <owl/applicat.h>
#include <owl/framewin.h>
#include <owl/menu.h>
#include <windows.h>
#include <algorithm>
#include <cmath>
#include <memory>
#include <string>
#include "pdf.rh"
class TMyPrintOut : public owl::TPrintout {
public:
TMyPrintOut(const char* title) : owl::TPrintout(title) {}
void GetDialogInfo(int& minPage, int& maxPage, int& selFromPage, int& selToPage)
{ minPage = maxPage = selFromPage = selToPage = 1; }
bool HasPage(int pageNumber) { return pageNumber == 1; }
void BeginPage(owl::TRect& clientR);
void PrintPage(int page, owl::TRect& bandRect, unsigned flags);
};
void TMyPrintOut::BeginPage(owl::TRect& clientRect)
{
DC->SetMapMode(MM_ANISOTROPIC);
DC->SetViewportExt(PageSize);
owl::TSize printableSize(DC->GetDeviceCaps(HORZSIZE), DC->GetDeviceCaps(VERTSIZE));
owl::TSize windowExtt(printableSize.cx * 10, printableSize.cy * 10);
DC->SetWindowExt(windowExtt);
clientRect.left = clientRect.top = 0;
clientRect.right = clientRect.left + windowExtt.cx;
clientRect.bottom = clientRect.top + windowExtt.cy;
}
void TMyPrintOut::PrintPage(int , owl::TRect& , unsigned )
{
owl::TRect clientRect;
BeginPage(clientRect);
DC->MoveTo(clientRect.left, clientRect.bottom / 2);
DC->LineTo(clientRect.right, clientRect.bottom / 2);
DC->MoveTo(clientRect.right / 2, clientRect.bottom);
DC->LineTo(clientRect.right / 2, clientRect.top);
double r = std::min(clientRect.right, clientRect.bottom) / 4;
int n = int(M_PI * r);
for (int i = -n; i <= n; i++) {
double t = i * M_PI / n;
double c = std::cos(t);
double s = std::sin(t);
int dx = int(r * (1 + c) * (-s));
int dy = int(r * (1 + c) * c);
int x = int(clientRect.right / 2 + dx);
int y = int(clientRect.bottom / 2 + dy);
if (i == -n)
DC->MoveTo(x, y);
else
DC->LineTo(x, y);
}
}
class TMyFrame : public owl::TFrameWindow {
public:
TMyFrame(const char* name) : owl::TFrameWindow(0, name) {}
private:
void CmOutputPDF();
DECLARE_RESPONSE_TABLE(TMyFrame);
};
DEFINE_RESPONSE_TABLE1(TMyFrame, owl::TFrameWindow)
EV_COMMAND(CM_OUTPUTPDF, CmOutputPDF),
END_RESPONSE_TABLE;
void TMyFrame::CmOutputPDF()
{
try {
std::string driver = "winspool";
std::string device = "Microsoft Print to PDF";
std::string port = "C:\\WORK\\PDFOWL.PDF";
owl::TPrinter printer;
printer.GetData()->SetDevNames(driver.c_str(), device.c_str(), port.c_str());
TMyPrintOut printOut("PDF出力テスト");
printer.Print(this, printOut, false);
}
catch (const std::exception& x) {
MessageBox(x.what(), "エラー", MB_OK | MB_ICONERROR);
}
catch (...) {
MessageBox("想定外の例外です。", "エラー", MB_OK | MB_ICONERROR);
}
}
class TMyApp : public owl::TApplication {
public:
TMyApp(const char* title) : owl::TApplication(title), Title(title) {}
private:
void InitMainWindow() {
std::unique_ptr<owl::TFrameWindow> mainWindow(new TMyFrame(Title.c_str()));
mainWindow->SetMenuDescr(owl::TMenuDescr(MAIN_MENU, 1, 0, 0, 0, 0, 0));
SetMainWindow(mainWindow.release());
}
std::string Title;
};
int OwlMain(int , char** )
{
TMyApp("PDF出力テスト").Run();
return 0;
}
#define MAIN_MENU 10000
#define CM_OUTPUTPDF 10100
#include "pdf.rh"
#include <owl/window.rh>
#include <owl/except.rc>
#include <owl/printer.rc>
MAIN_MENU MENU {
POPUP "ファイル(&F)"
{
MENUITEM "PDF出力(&P)", CM_OUTPUTPDF
MENUITEM "終了(&X)", CM_EXIT
}
}
CMakeLists.txt は https://perce-neige.hateblo.jp/entry/2018/10/25/214023 にあります。