第298章 ネットワークプリンタを使う その2


今回はプリンタの「ページ設定」についてします。



ページ設定ダイアログは左の図のようなものです。用紙の大きさやら、 用紙の向き、周囲の空白などを設定します。プリンタの設定ボタンを 押すと他のプリンタの設定もできます。

これは、PageSetupDlg関数で行います。



では、PageSetupDlg関数を見てみましょう。

BOOL PageSetupDlg( LPPAGESETUPDLG lppsd );

lppsdにはPAGESETUPDLG構造体へのポインタを指定します。

ユーザーがOKボタンを押すと0以外が返ります。キャンセルボタンを 押すか、エラーが発生した場合は0が返ります。

PAGESETUPDLG構造体は、次のように定義されています。

typedef struct tagPSD { DWORD lStructSize; HWND hwndOwner; HGLOBAL hDevMode; HGLOBAL hDevNames; DWORD Flags; POINT ptPaperSize; RECT rtMinMargin; RECT rtMargin; HINSTANCE hInstance; LPARAM lCustData; LPPAGESETUPHOOK lpfnPageSetupHook; LPPAGEPAINTHOOK lpfnPagePaintHook; LPCTSTR lpPageSetupTemplateName; HGLOBAL hPageSetupTemplate; } PAGESETUPDLG, *LPPAGESETUPDLG;

lStructSizeは、この構造体のサイズです。

hwndOwnerは、このダイアログボックスのオーナーのウィンドウハンドルです。 オーナーがいないときはNULL似もなり得ます。

hDevModeは、DEVNAMES構造体のグローバルメモリオブジェクトのハンドルです。 入力時には、ダイアログボックスを初期化するために使われるDEVNAMES構造体の グローバルメモリオブジェクトのハンドルを指定します。出力時にはユーザーが選択した 項目が入ったDEVNAMES構造体のグローバルメモリオブジェクトのハンドルとなります。 ユーザーが何も選択しなかったときはNULLになります。

hDevNamesは、DEVNAMES構造体のグローバルメモリオブジェクトのハンドルです。 この構造体には、ドライバーの名前、プリンターの名前、出力ポートの名前を含んでいます。 入力時にはダイアログボックスを初期化するために使われるDEVNAMES構造体の グローバルメモリオブジェクトのハンドルを指定します。出力時にはユーザーの選択が 反映されます。ユーザーが何も選択しなかったときはNULLとなります。

Flagsには、ページ設定ダイアログボックスを初期化するのに使われるビットフラグのセットです。 次の組み合わせで指定します。

PSD_DEFAULTMINMARGINSプリンタに許された最小のマージンを設定します。
PSD_MARGINSや、PSD_MINMARGINSがあると無視されます。
PSD_DISABLEMARGINSマージンコントロールを使用不能にします。
PSD_DISABLEORIENTATION「向き」を使用不能にします。
PSD_DISABLEPAGEPAINTINGサンプルページの描画をしません。
もし、PagePaintHookフックプロシージャを使えるようにしてあるならば、これが 設定してあってもサンプルページは描画する事ができます。
PSD_DISABLEPAPERペーパーコントロールを使用不能にします。
ユーザーがペーパーサイズやペーパーソース(給紙方法)をセットできないようにします。
PSD_DISABLEPRINTERプリンタボタンを使用不能にします。
PSD_ENABLEPAGEPAINTHOOKlpfnPagePaintHookメンバを有効にします。
PSD_ENABLEPAGESETUPHOOKlpfnPageSetupHookメンバで指定された フックプロシージャを有効にします。
PSD_ENABLEPAGESETUPTEMPLATEhInstanceやlpPageSetupTemplateNameメンバが 指しているダイアログボックステンプレートが使われます
PSD_ENABLEPAGESETUPTEMPLATEHANDLEhPageSetupTemplateメンバが プレロードされたダイアログボックスのデータブロックを指していることを示します。
このフラグが立っていると、lpPageSetupTemplateNameメンバは無視されます。
PSD_INHUNDREDTHSOFMILLIMETERSマージンやペーパーサイズの単位が ミリメートルの100分の1になります。
rtMargin, rtMinMargin, ptPageSizeメンバの単位がミリメートルの100分の1になります。
PSD_INTHOUSANDTHSOFINCHESサイズの単位がインチの1000分の1となります。
PSD_INWININIINTLMEASURE使われません。
PSD_MARGINSrtMarginメンバで指定された値をシステムに使わせます。

もしこれがセットされていないとすべてのマージンに1インチがセットされます。

PSD_MINMARGINSrtMinMarginメンバに指定された値をシステムに使わせます。
ユーザーにこの値より小さい値を使わせるのを防ぎます。
PSD_NONETWORKBUTTONネットワークボタンを隠します。
PSD_NOWARNINGデフォルトプリンタが存在しないときのワーニングを表示しません。
PSD_RETURNDEFAULTPageSetupDlg関数はダイアログボックスを表示しません。
その代わりデフォルトプリンタのhDevMode, hDevNamesをセットします。
PSD_SHOWHELPヘルプボタンを表示します。
hwndOwnerはHELPMSGSTRING登録メッセージを処理しなくてはなりません。

ptPaperSize はユーザーによって選択された用紙の寸法を指定します。
PSD_INTHOUSANDTHSOFINCHESまたは、PSD_INHUNDREDTHSOFMILLIMETERSフラグにより 単位が異なります。

rtMinMargin は、許される最小のマージンを指定します。
PSD_MINMARGINSフラグがセットされていないと無視されます。

rtMarginは、マージンの値を指定します。もし、PSD_MARGINSフラグがセットされていると、 rtMarginはマージン値を初期化します。PageSetupDlg関数が戻ってきたときに、rtMarginには ユーザーによってセットされた値が格納されています。

hInstanceには、lpPageSetupTemplateNameメンバで指定されたダイアログボックスのテンプレート を含むアプリケーションまたはモジュールのインスタンスハンドルを指定します。(PSD_ENABLEPAGESETUPTEMPLATE フラグをセットしたとき)

lCustDataには、アプリケーション定義のデータを指定します。これは、lpfnPageSetupHookメンバで示された プロシージャに送られます。プロシージャではWM_INITDIALOGメッセージが来たときにlParamを調べると わかります。

lpfnPageSetupHookには、PageSetupHookフックプロシージャのポインタを指定します。 PSD_ENABLEPAGESETUPHOOKフラグがセットされていないと無視されます。

lpfnPagePaintHookには、PagePaintHookフックプロシージャのポインタを指定します。 PSD_ENABLEPAGEPAINTHOOKフラグがセットされていないと無視されます。

lpPageSetupTemplateNameには、hInstanceメンバによって指定されたモジュールのダイアログボックステンプレート の名前を指定します。PSD_ENABLEPAGESETUPTEMPLATEフラグがセットされていないと無視されます。

hPageSetupTemplateには、ダイアログボックスのテンプレートのメモリオブジェクトのハンドルを指定します これには、PSD_ENABLEPAGESETUPTEMPLATEHANDLEフラグがセットされていなくてはなりません。

さて、PageSetupDlg関数でユーザーの希望を聞いた後、SetPrinter関数で状態を設定するわけですが、 その前に現在の状態をGetPrinter関数で取得しておく必要があります。このGetPrinter関数がちょっと曲者で 普通に使用するとエラーとなります。

BOOL GetPrinter( HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded );

hPrinterには、プリンタのハンドルを指定します。これは、OpenPrinterまたはAddPrinter関数で取得できます。

Levelには、pPrinterによって指し示されたバッファに蓄える構造体のレベルを指定します。
Windows95/98では1,2,5が使用できます。
NT/2000では、1,2,3,4,5,7,8,9が使えます。

pPrinterには、指定されたプリンタに関する情報を格納する構造体のポインタを指定します。 Levelで指定したレベルnに対してPRINTER_INFO_n構造体が使われます。

cbBufには、pPrinterで示されたバッファのサイズを指定します。

pcbNeededには、プリンタ情報のサイズを格納する変数のポインタを指定します。 この値よりcbBufが小さいときGetPrinter関数は失敗します。cbBufがこの値と等しいか、 それよりも大きいとき関数は成功し、その値はバッファに蓄えられたバイト数を表します。

関数が成功すると0以外の値を返します。失敗すると0を返します。

通常プリンタ情報を取得するときはレベル2を使います。

さて、単純に考えると

HANDLE hPrn; PRINTER_INFO_2 prn_info_2; DWORD dwNeeded; GetPrinter(hPrn, 2, (LPBYTE)&prn_info_2, sizeof(PRINTER_INFO_2), &dwNeeded);

というような感じで使うように思われますが、これは失敗します。

HANDLE hPrn; DWORD dwNeeded, dwSize; PRINTER_INFO_2 *pprn_info; GetPrinter(hPrn, 2, 0, 0, &dwNeeded); //dwNeededの分だけpprn_infoにメモリを確保 dwSize = dwNeeded; GetPrinter(hPrn, 2, (LPBYTE)pprn_info, dwSize, &dwNeeded);

と2段がまえで実行する必要があります。あるいは、最初からとんでもなく大きな配列を 用意しておいて使うという手もあります。(邪道です)

//あまり感心しない方法 DWORD dwNeeded; HANDLE hPrn; BYTE prn[1024 * 10]; PRINTER_INFO_2 *prn_info; OpenPrinter("\\\\nec9821\\epson", &hPrn, NULL); GetPrinter(hPrn, 2, prn, 1024*10, &dwNeeded); prn_info = (PRINTER_INFO_2 *)prn;

さて、いずれにしてもプリンタの名前を取得しなくてはいけません。 これは、PAGESETUPDLG構造体から取得することにします。 PageSetupDlg関数が戻ってきたときには、PAGESETUPDLG関数にプリンタの 情報が含まれています。このhDevModeメンバを使うことにします。 DEVNAMES構造体については、すでに 77章297章で出ていますが、 大変複雑なので、あとの章で解説することにします。

この構造からデバイス名を取得するには、

DEVMODE *pdev; char szPrnName[256]; ... pdev = (DEVMODE *)GlobalLock(psd.hDevMode); strcpy(szPrnName, (char *)(pdev->dmDeviceName));

のようにすれば取得できます。

さて、PageSetupDlg関数関数でページ設定の変更点をPAGESETUP構造体に 取得しておいて、現在のプリンタ設定をGetPrinter関数で取得して、 変更点をPRINTER_INFO_2構造体のpDevModeメンバに書き込みます。 そして、さらにSetPrinter関数を呼ぶ前にDocumentProperties関数を呼んで DEVMODE構造体のデバイス依存部分のアップデートをしなくてはいけません。

LONG DocumentProperties( HWND hWnd, HANDLE hPrinter, LPTSTR pDeviceName, PDEVMODE pDevModeOutput, PDEVMODE pDevModeInput, DWORD fMode );

指定されたプリンタの初期化された情報を取得したり、変更したりします。あるいは プリンタ設定プロパティシートを表示したりします。

Windows 95/98では、PrinterProperties関数と同じプロパティシートを表示します。 PrinterProperties関数については、すでに 第79章で解説してあるのでこちらを見てください。

hWndには、プロパティシートの親ウィンドウのハンドルを指定します。

hPrinterには、プリンタハンドルを指定します。

pDeviceNameには、デバイス名を指定します。

pDevModeOutputには、関数が戻ってきたときにユーザーに指定されたデータを格納する DEVMODE構造体へのポインタを指定します。

pDevModeInputには、プロパティシートを初期化するのに使うDEVMODE構造体へのポインタを 指定します。(DE_IN_BUFFERフラグがセットされたときのみ使われます。)

fModeは、この関数の動作を指定します。0を指定すると、DEVMODE構造体に必要なバイト数が 返ります。それ以外の時は次の組み合わせで指定します。

DM_IN_BUFFER入力値です。プリンタの現在の設定とpDevModeInputで指定した DEVMODE構造体の設定とをマージします。
DM_IN_PROMPT入力値。プリンタドライバのプロパティシートを表示した後、 ユーザーによって入力される値でDEVMODE構造体の設定を変更します。
DM_OUT_BUFFER出力値。DEVMODE構造体にプリンタドライバの現在の 設定を書き込みます。

fModeが0の時は、必要なバッファサイズが返ります。プロパティシートを表示したときは、 IDOKまたは、IDCANCELが返ります。表示しないときは関数が成功したらIDOKが返ります。 関数が失敗したときは、マイナスの値が返ります。

次にSetPrinter関数は、どうなっているかというと

BOOL SetPrinter( HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD Command );

hPrinterには、プリンタハンドルを指定します。

Levelには、構造体のレベルを指定します。 Windows 95/98では、0, 2, 5のいずれかを指定します。
NT/2000では、0, 2, 3, 4, 5, 7, 8, 9のいずれかを指定します。
Commandに、0以外を指定するときは必ず0に設定します。

pPrinterには、設定するデータの情報が格納されているバッファのポインタを指定します。 または、Commandに指定するコマンドの情報が格納されているバッファへのポインタを指定します。

Commandには、実行するコマンドを指定します。Levelが0以外の時は必ず0を指定します。Levelに0を 指定したときは、次のいずれかを指定します。

PRINTER_CONTROL_PAUSEプリンタのポーズ
PRINTER_CONTROL_PURGEすべての印刷ジョブの削除
PRINTER_CONTROL_RESUMEポーズしているプリンタの再開
PRINTER_CONTROL_SET_STATUSプリンタの状態を設定します。pPrinterがさす値によって 決まります。

関数が成功すると0以外の値が返ります。失敗すると0が返ります。

前置きが長くなってしまいました。具体的なプログラムは次章で示します。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

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