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); }