第77章 印刷 基礎の基礎


前章までで自作メモ帳が少しメモ帳らしくなりました。
でも、何か物足りないですね。そうです印刷機能がないのです。 と、いうことで今回から少し印刷について解説します。いきなり全部を解説すると 混乱して何がなんだかわからん!ということになるので 少しずつ解説します。

実は、ただ印刷するだけならそんなに難しくはありません。 しかし、実際には印刷の形式だの途中で印刷をやめる機能だのを付けなくてはいけないので そのあたりが面倒くさいのです。今回は、全部省略してもっともシンプルなものを 作ります。ですから、全く汎用性はありません。

1.DOCINFO構造体のメンバをセット(di) 2.hdc = CreateDC(プリンタドライバ名, プリンタ名, ポート, NULL); 3.StartDoc(hdc, &di); 4.StartPage(hdc); 5.hdcに書き込みをする 6.EndPage(hdc); 7.EndDoc(hdc); 8.DeleteDC(hdc);

要するに、画面に表示するときとほとんど同じ要領です。 hdcは必ずCreateDC関数で作ります。hdcができたらStartDoc, StartPage関数を 呼びます。hdcに書き込んだ内容が印刷されます。後は、後始末をすればよいわけです。

typedef struct { // di int cbSize; LPCTSTR lpszDocName; LPCTSTR lpszOutput; LPCTSTR lpszDatatype; // Windows 95 のみ DWORD fwType; // Windows 95 のみ } DOCINFO;

cbSizeは、この構造体のサイズを設定します。

lpszOutputは、印刷をするときはNULLにします。ファイル名を設定して 印刷ジョブをファイルにリダイレクトすることもできます。

最後の2つのメンバは無視してください。

次にCreateDC関数ですが、これは第47章で少しだけ出てきました。

HDC CreateDC( LPCTSTR lpszDriver, // ドライバ名 LPCTSTR lpszDevice, // デバイス名 LPCTSTR lpszOutput, // 使いません( NULL ) CONST DEVMODE *lpInitData // オプションデータ );

ドライバ名にはプリンタドライバの名前を指定します。 筆者の環境ではEPMJ3です。

エー、そんなものどうやったらわかるの?

はい、WINDOWのディレクトリにあるwin.iniファイルを 調べてみてください。その中に[windows]というセクションがあります。 そして、そのセクションのdeviceキー(昔はエントリーといいました)を 見てください。ちなみに筆者の環境では
[windows]
NullPort=None
load=
run=
device=EPSON MJ-3000CU,EPMJ3,LPT1:
という具合になっています。
deviceキーのところを見ると最初がデバイス名、次が ドライバ名、最後にポートが書かれています。

ポートというのはコンピュータの玄関みたいなものです。 本当は、プログラム中でwin.iniファイルを調べて これらの文字列を取得しなくてはいけないのですが、 今回は簡単のために直接プログラムにこれらの文字を 書き込みます。ですから、汎用性は全くないプログラムとなります。

int StartDoc( HDC hdc, // デバイスコンテキストハンドル CONST DOCINFO *lpdi // DOCINFO構造体のアドレス );

これで印刷ジョブが開始されます。成功したときは 0より大きな数値を返します。失敗したときは0または マイナスの数値を返します。

int StartPage( HDC hDC // デバイスコンテキストハンドル );

この関数はプリンタドライバの準備を行います。

int EndPage( HDC hdc // デバイスコンテキストハンドル );

この関数はデバイスに「1ページ分書き込んだよ!」と知らせます。 また、新しいページに進むようにドライバに連絡します。 成功したときは0より大きい数値を、失敗したときは0以下の数値を 返します。

int EndDoc( HDC hdc // デバイスコンテキストハンドル );

印刷終了直後にこの関数を呼び出します。成功したら0より大きい数値を、 失敗したときは0以下の数値を返します。

最後にDeleteDC関数を呼んでデバイスコンテキスハンドルを解放します。

では、サンプルのプログラムを見てみましょう。

// prn01.rcの一部 // 自分で作る人はwindows.hと自作ヘッダーファイルをinclude するのを忘れない ///////////////////////////////////////////////////////////////////////////// // // Menu // MYMENU MENU DISCARDABLE BEGIN POPUP "ファイル(&F)" BEGIN MENUITEM "終了(&X)", IDM_END MENUITEM "印刷(&P)", IDM_PRINT END END

リソーススクリプトは単にメニュー項目を決めているだけです。

// prn01.cpp #define STRICT #include <windows.h> #include "resource.h" LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); BOOL InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); int MyPrint(void); char szClassName[] = "prn01"; //ウィンドウクラス int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; if (!hPrevInst) { if (!InitApp(hCurInst)) return FALSE; } if (!InitInstance(hCurInst, nCmdShow)) { return FALSE; } while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; }

これは、いつもと同じです。

//ウィンドウ・クラスの登録 BOOL InitApp(HINSTANCE hInst) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst; //インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; return (RegisterClass(&wc)); }

これもいつもとほぼ同じです。クラスメニューの名前を登録するのを 忘れないでください。

//ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかる印刷処理", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 CW_USEDEFAULT, //幅 CW_USEDEFAULT, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

ここはいつもと同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; switch (msg) { case WM_COMMAND: switch (LOWORD(wp)) { case IDM_END: SendMessage(hWnd, WM_CLOSE, 0, 0); break; case IDM_PRINT: MyPrint(); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } break; case WM_CLOSE: id = MessageBox(hWnd, (LPCSTR)"終了してもよいですか", (LPCSTR)"終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0L; }

メニューで「印刷」が選ばれたら自作関数MyPrintを呼ぶようにしています。

int MyPrint(void) { HDC hdc; DOCINFO docinfo; TEXTMETRIC textmetric; memset(&docinfo, 0, sizeof(DOCINFO)); docinfo.cbSize = sizeof(DOCINFO); docinfo.lpszDocName = "testprint"; //注意!CreateDCの引数は各個人の環境で異なります //Windows3.1では3番目の引数も設定が必要です //Windows95では最初の引数は無視されるのでNULLにしてもよいです hdc = CreateDC("EPMJ3", "EPSON MJ-3000CU", NULL, NULL); StartDoc(hdc, &docinfo); StartPage(hdc); GetTextMetrics(hdc, &textmetric); TextOut(hdc, 10, textmetric.tmHeight * 1, "これはテスト印刷です。", 22); TextOut(hdc, 10, textmetric.tmHeight * 2, "テスト印刷の2行目です。", 24); SetTextColor(hdc, RGB(255, 0, 0)); TextOut(hdc, 10, textmetric.tmHeight * 3, "色も変えられます!", 18); EndPage(hdc); EndDoc(hdc); DeleteDC(hdc); return 0; }

hdcをCreateDCで作ったら後は画面表示の時と全く同じですね。 テキストの色を変えていますが、プリンタがカラーでないと 多分無視されるか、エラーになります。

BOOL GetTextMetrics( HDC hdc, // デバイスコンテキストハンドル LPTEXTMETRIC lptm // TEXTMETRIC構造体のアドレス );

現在のフォントに対するメトリックを取得します。 成功すればTRUE、失敗したときはFALSEを返します。

typedef struct tagTEXTMETRIC { // tm LONG tmHeight; LONG tmAscent; LONG tmDescent; LONG tmInternalLeading; LONG tmExternalLeading; LONG tmAveCharWidth; LONG tmMaxCharWidth; LONG tmWeight; LONG tmOverhang; LONG tmDigitizedAspectX; LONG tmDigitizedAspectY; BCHAR tmFirstChar; BCHAR tmLastChar; BCHAR tmDefaultChar; BCHAR tmBreakChar; BYTE tmItalic; BYTE tmUnderlined; BYTE tmStruckOut; BYTE tmPitchAndFamily; BYTE tmCharSet; } TEXTMETRIC;

メンバがいっぱいあります。全部については説明しません。 tmHeightは、文字セルの高さを表します。 文字セルの高さはtmAscent + tmDescentのことです。

tmDescentとは、基準線より下に行く部分です。(j,y,pなど)

tmAscentとは、基準線から文字セルの上端までです。

後は、各自ヘルプなどで調べてみてください。


左の図は実際に印刷をした用紙をスキャナで読みとったものです。


[SDK Index] [総合Index] [Previous Chapter] [Next Chapter]

Update Sep/22/1997 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。