Windows における印刷は、基本的には画面に対する Graphics の描画と 同じである。Printer device context に対し、描画を行えばよい。違いは、 Job としてスプールさせることと、紙送りがあることである。
基本的な流れは、
Printer を指定するには、通常 windows common dialog 関数の一つである PrintDlg() を使う。この時引数として渡す PRINTDLG構造体 の Flags メンバーに PD_RETURNDC を設定しておくと、ユーザが printer を 指定した時、対応する device context を生成して戻ってくるので便利である。 また、PD_RETURNDEFAULT も一緒に指定すると、dialog box を表示せずに 「通常使うプリンタ」の device context が得られるので、常に 「通常使うプリンタ」へ出力するプログラムにすることも容易にできる。
印刷 Job は一般に時間がかかるので、途中でキャンセルする仕掛けが必要である。 これは、SetAbortProc() 関数に Callback 関数を渡すことで実現する。 SetAbortProc() 関数に引数として渡されるCallback 関数は、 BOOL 値を戻し、TRUE を戻せば続行、FALSE を 戻せば中止(キャンセル)となる。ドキュメントによれば印刷中は、約 2 秒に一回、 この関数が呼び出されるらしい。
次の例は、指定された printer で、左上隅が(100,200)、右下隅が(300,500)の 長方形を印刷するプログラムである。なお、ここでは AbortProc() は常にTRUEを返している (つまり、この関数を削除して、かつ SetAbortProc() の行を削除してもよい)。 このソースコードを例えば prsample.c というファイルに書き出してコンパイル・リンクするには、
cl /W3 prsample.c comdlg32.lib gdi32.libとする。
/* prsample.c
**
** Sample program for print job.
**
** To compile and link,
** cl /W3 prsample.c comdlg32.lib gdi32.lib
*/
#include <windows.h>
#include <tchar.h>
#include <commdlg.h>
BOOL CALLBACK AbortProc(HDC hdc, int iError)
{
return TRUE;
}
void main()
{
PRINTDLG pd;
DOCINFO di;
pd.lStructSize = sizeof(PRINTDLG);
pd.hDevMode = (HANDLE)NULL;
pd.hDevNames = (HANDLE)NULL;
pd.Flags = PD_RETURNDC;
pd.hwndOwner = (HWND)NULL;
pd.hDC = (HDC)NULL;
pd.nFromPage = 1;
pd.nToPage = 1;
pd.nMinPage = 0;
pd.nMaxPage = 0;
pd.nCopies = 1;
pd.hInstance = (HANDLE)NULL;
pd.lCustData = 0;
pd.lpfnPrintHook = (LPPRINTHOOKPROC)NULL;
pd.lpfnSetupHook = (LPSETUPHOOKPROC)NULL;
pd.lpPrintTemplateName = (LPCTSTR)NULL;
pd.lpSetupTemplateName = (LPCTSTR)NULL;
pd.hPrintTemplate = (HANDLE)NULL;
pd.hSetupTemplate = (HANDLE)NULL;
if(!PrintDlg(&pd))
{
return;
}
SetAbortProc(pd.hDC, AbortProc);
di.cbSize = sizeof(DOCINFO);
di.lpszDocName = _T("Print Sample");
di.lpszOutput = (LPCTSTR)NULL;
di.lpszDatatype = (LPCTSTR)NULL;
di.fwType = 0;
if(StartDoc(pd.hDC, &di) <= 0)
{
DeleteDC(pd.hDC);
return;
}
if(StartPage(pd.hDC) <= 0)
{
EndDoc(pd.hDC);
DeleteDC(pd.hDC);
return;
}
Rectangle(pd.hDC, 100, 200, 300, 500);
EndPage(pd.hDC);
EndDoc(pd.hDC);
DeleteDC(pd.hDC);
}