拡張メタファイルによるWYSIWYG印刷の方法がわかりたい

戻る

○Windows3.1とWindows95/NTのメタファイル
Windows3.1 では図形をファイルに保存する方法として、メタファイルをサポート しています。このメタファイルは、通常デバイスやアプリケーションに依存しており、 メタファイルを生成したアプリケーションやデバイス以外で再生すると正しく表示 できないことがほとんどです。また、メタファイルに記録できるGDI関数は限られて おり、あまり使い勝手のよいものではありませんでした。
WindowsNT, Windows95 では、Windows3.1 のメタファイルの欠点を補うために、 拡張メタファイル(Enhanced Metafile) をサポートしています。
 拡張メタファイルは、どのデバイスでも再生でき、デバイスに依存しません。 そして、ヘッダーの拡張、記述文字列、メタファイル パレット、記録できるGDI 関数の種類と数がWindowsメタファイルと比較してかなり増えました。 また、拡張メタファイルレコードと再生コードは、スケーリング、クリッピング、 埋め込み、問い合わせなどで問題となった Windowsメタファイルの制約がなくなり ました。
拡張メタファイルの生成に利用する参照デバイスに、プリンタデバイスコンテキスト を利用することにより、WYSIWYG(what-you-see-is-what-you-get)を実現できます。 そして、複数のデバイスで同じの拡張メタファイルを再生しても、同一のスケールで 再生することができます。

11-1 メタファイルとは

メタファイルとは、文字や図形を描画するGDI関数の呼び出しを記録したファイル です。このファイルを再生することにより、特定の図形を何度でも表示させることが でき、プログラムの修正をすることなく異なる図形を描画させることができます。
しかし、メタファイルAPI CretaMetaFile() で生成される標準メタファイル は、描画する図形を再生する領域に関する情報はなく、生成するアプリケーションに 依存していることが多く、再利用が困難なことが多いようです。
また、メタファイルを保存するアプリケーションは、アプリケーション独自の データファイル内にメタファイルを保存することもあります。
Win32 でサポートされる WindowsメタファイルAPIは、 16ビットアプリケーション の下位互換性を保つためにサポートされています(表11-1)。
これらのAPIを利用して、Windows3.1 で生成されたメタファイルを WindowsNT, Windows95 上で再生することができます。

表11-1:Windowsメタファイル関数
CloseMetaFile メタファイルのデバイスコンテキストをクローズする
CopyMetaFile メタファイルをコピーする
CreateMetaFile メタファイルのデバイスコンテキストを作成する
DeleteMetaFile メタファイルハンドルを無効化する
EnumMetaFile メタファイル内部のGDI呼び出しを返す
EnumMetaFileProc メタファイルデータを処理する
GetMetaFile Windows メタファイルを作成する
GetMetaFileBitsEx メタファイル ビットをバッファにコピーする
PlayMetaFile デバイスコンテキストにメタファイルを再生する
PlayMetaFileRecord メタファイルレコードを再生する
SetMetaFileBitsEx データからメモリベースのメタファイルを作成する

○メタファイルヘッダー
メタファイルは、METAHEADER 構造体と、METARECORD 構造体から構成されます (図11-1, リスト11-1, リスト11-2)。
METARECORD 構造体には、実行するGDI関数の情報が設定されます。 rdFunction メンバは、META_xxxxxx (Win32 SDK WINGDI.H) で 定義される関数番号が設定されます。
記録されたGDI関数ごとの METARECORD を得るには、EnumMetaFile() で メタファイルレコードを列挙します。

○メタファイルを移動可能にするには
メタファイルを移動可能にするは、METAFILEHEADER 構造体 または、 APMFILEHEADER(Aldus Placesble Metafiles File Header)(注1) 構造体を、 METAHEADER構造体の前に追加したメタファイルを生成する必要が あります(図11-2)。
(注1)APMFILEHEADERが本家のようだが、最近のマイクロソフトの資料には METAFILEHEADERがあるので、この構造体がマイクロソフト社のスタンダードに なってしまったのではないかと思われる。
ところが、この構造体は、Win32 SDK のヘッダファイルにはないため、 アプリケーションが独自に定義する必要があります(リスト11-3)。
そして、この構造体を設定するAPIはないため、独自にファイルをオープンして、 METAFILEHEADER 構造体を書き込み、GetWinMetaFileBits() で取得した メタファイルを METAFILEHEADER構造体の直後に書き込みます。
再配置可能メタファイルを再生するときも、生成するときと同様にアプリケーション が独自に METAFILEHEADER 構造体を読み出して表示する領域の設定を行う必要が あります。そして、メタファイル本体は、SetWinMetaFileBits() でメモリ内に 格納後に再生させます。
なお、画像がデバイス面全体に収まるようにするには、MM_ANISOTROPIC マッピングモードを使って画像をスケールしたメタファイル でなければなりません。



図11-1:メタファイルの構造
+------------+------------+------------+---------- | METAHEADER | METARECORD | METARECORD | ... +------------+------------+------------+----------
図11-2:再配置可能メタファイルの構造
+----------------+------------+------------+------------+---------- | METAFILEHEADER | METAHEADER | METARECORD | METARECORD | ... +----------------+------------+------------+------------+----------
リスト11-1:METAHEADER構造体
typedef struct tagMETAHEADER { WORD mtType; /* 1:メモリ内,2:ディスクファイル内 */ WORD mtHeaderSize; /* メタファイルヘッダサイズ */ WORD mtVersion; /* Windowsのバージョン番号 */ DWORD mtSize; /* ファイルのサイズ */ WORD mtNoObjects; /* メタファイル内に存在するオブジェクト総数 */ DWORD mtMaxRecord; /* メタファイルの最大レコードのサイズ */ WORD mtNoParameters; /* 予約 */ } METAHEADER;
リスト11-2:METARECORD構造体
typedef struct tagMETARECORD { DWORD rdSize; /* レコードのサイズ */ WORD rdFunction; /* 関数の番号 */ WORD rdParm[1]; /* 関数のパラメータを格納するワードの配列 */ } METARECORD;
リスト11-3:METAFILEHEADER構造体の定義
#pragma pack(2) typedef struct { DWORD key; /* 0x9AC6CDD7L */ HANDLE hmf; /* NULL */ SMALL_RECT bbox; /* メタファイルを再生して生成される図形の矩形 */ WORD inch; /* 解像度[dpi] 1440未満の値 */ DWORD reserved; /* 0L */ WORD checksum; /* 最初の10ワードをXORした結果 */ } METAFILEHEADER; /* または APMFILEHEADER */ #pragma pack()
リスト11-4:METAFILEHEADER構造体にチェックサム(checksum)を設定する(checksumメンバーは、他のメンバーの設定後に設定する)
METAFILEHEADER mfh; LPWORD lpw; /* METAFILEHEADER の値を設定する */ ZeroMemory(&mfh, sizeof(mfh)); mfh.key = 0x9AC6CDD7L; : : /* チェックサム */ lpw = (LPWORD)&mfh; for(iCt = 0; iCt < 10; iCt++){ mfh.checksum ^= *lpw++; }



11-2 拡張されたメタファイル

WindowsNT, Windows95 では、拡張メタファイル(Enhanced Metafile) を利用する ことができます。拡張メタファイルは、Windowsメタファイルでサポートされなかった 多くのGDI関数をサポートし、図形を表示する矩形を0.01[mm]単位で設定する ことにより、どのアプリケーションで表示しても同様のサイズで表示することが できます。
矩形を指定しないときは、図形の最小矩形が設定され、表示するときにスケーリング され、クライアント領域からはみ出すことなく表示させます。
これは、デバイスに依存しないことを意味します。Windowsメタファイルの移動可能 なメタファイルは、デバイスや、アプリケーションに依存した形式で記録されたもの が多く、他のアプリケーションで再生することが困難なものがほとんどでした。
拡張メタファイルの生成は、Windowsメタファイルと比較して簡単に生成・再生を行う ことができ、デバイス依存にさせないための豊富な機能を持っています。
拡張メタファイルAPIには、Windows3.1 で生成した Windowsメタファイルを拡張 メタファイルに変換する SetWinMetaFileBits() なども 含まれます(表11-2)。

表11-2:拡張メタファイル関数
CloseEnhMetaFile 拡張メタファイルのデバイスコンテキストをクローズする
CopyEnhMetaFile 拡張メタファイルをコピーする
CreateEnhMetaFile 拡張メタファイルデバイスコンテキストを作成する
DeleteEnhMetaFile 拡張メタファイルハンドルを無効化する
EnhMetaFileProc 拡張メタファイルデータを処理する
EnumEnhMetaFile 拡張メタファイル内部のGDI呼び出しを返す
GdiComment 拡張メタファイルにコメントを追加する
GetEnhMetaFile 拡張メタファイルを作成する
GetEnhMetaFileBits 拡張メタファイルビットをバッファにコピーする
GetEnhMetaFileDescription 拡張メタファイルのクリエイタとタイトルを返す
GetEnhMetaFileHeader 拡張メタファイルヘッダを返す
GetEnhMetaFilePaletteEntries 拡張メタファイルのパレットエントリを返す
GetWinMetaFileBits メタファイルの内容をWindows形式で取得する
PlayEnhMetaFile デバイスコンテキストに拡張メタファイルを再生する
PlayEnhMetaFileRecord 拡張メタファイルレコードを再生する
SetEnhMetaFileBits データからメモリベースの拡張メタファイルを作成する
SetWinMetaFileBits Windowsメタファイルデータから拡張メタファイルを作成する


○拡張メタファイルヘッダー
拡張メタファイルヘッダーENHMETAHEADER構造体、ENHMETARECORD構造体 は、Windowsメタファイルの METAFILEHEADER 構造体とMETAHEADER 構造体の情報を含んだ構成になっています(図11-3, リスト11-5, リスト11-6)。
拡張メタファイルヘッダのメンバへのアクセスは、APIで行うことができ、 参照するデバイスの情報は指定するデバイスコンテキストから設定されます。
メタファイルレコードに設定されるGDI関数は、EMR_xxxxxx (Win32 SDK WINGDI.H)で定義してあります。
コメントは、プライベートデータを設定するために利用します。パブリックコメントを 利用することにより、EPS(PostScript)を埋め込むことができます。



図11-3:拡張メタファイルの構造
+---------------+--------------+---------------+---------------+--...--+------------+ | ENHMETAHEADER | コメント* ** | ENHMETARECORD | ENHMETARECORD | ... | パレット** | +---------------+--------------+---------------+---------------+--...--+------------+ * コメントは GDIComment() で設定する ** 省略可能
リスト11-5:ENHMETAHEADER構造体
typedef struct tagENHMETAHEADER { /* enmh */ DWORD iType; /* レコードの種類 EMR_HEADER */ DWORD nSize; /* 構造体のサイズ */ RECTL rclBounds; /* 画像を囲むことのできる最小の長方形の寸法 */ RECTL rclFrame; /* 画像を取り囲む長方形の寸法を、 0.01[mm]単位 */ DWORD dSignature; /* ENHMETA_SIGNATURE */ DWORD nVersion; /* メタファイルのバージョン */ DWORD nBytes; /* 拡張メタファイルのサイズ [bytes] */ DWORD nRecords; /* 拡張メタファイル内のレコード数 */ WORD nHandles; /* 拡張メタファイルのハンドルテーブル内ハンドル数 */ WORD sReserved; /* 予約 */ DWORD nDescription; /* 拡張メタファイルの内容に関する記述の文字数 */ DWORD offDescription; /* 先頭から内容に関する記述を格納配列までのオフセット */ DWORD nPalEntries; /* 拡張メタファイルのパレット内のエントリ数 */ SIZEL szlDevice; /* 参照デバイスの解像度(ピクセル単位) */ SIZEL szlMillimeters; /* 参照デバイスの解像度(ミリメートル単位) */ } ENHMETAHEADER;
リスト11-6:ENHMETARECORD構造体
typedef struct tagENHMETARECORD { /* enmr */ DWORD iType; /* レコードの種類 */ DWORD nSize; /* レコードのサイズ */ DWORD dParm[1]; /* GDI関数に渡されるパラメータの配列 */ } ENHMETARECORD;



○Windows95の印刷処理
拡張メタファイルは、Windows95 の印刷処理で、大きな役割を果たしています。
Windows3.1 での印刷処理は、アプリケーションがプリンタデバイスコンテキストに 対して、GDI関数で描画処理を行うと同時に、プリンタドライバでプリンタコード に変換を行います。このため、アプリケーションが描画処理を行い、スプールファイル が完全に生成されるまで他の処理を行うことができませんでした。
Windows95 の印刷処理は、Windows3.1 と同様の処理を行う RAW モードと、GDI関数 の実行をスプールファイルでなく拡張メタファイルに書き込む EMF モードがあります。 アプリケーションには、GDI関数の記録が終了した時点で印刷処理が終了したように 見えるため、見かけ上の印刷速度か向上します(注2)。
(注2)ただし、複雑な図形や、文字属性の設定の多いデータの印刷を行うときには、 必ずしも速度が向上するとは限りません。
生成された拡張メタファイルは、バックグラウンドでプリンタドライバによって プリンタコードに変換され、プリンタに出力されます。

○Windows95の印刷文書を格納するDOCINFO構造体の拡張
Windows95 の印刷で利用する DOCINFO 構造体は、Windows95 のために拡張されて います(注3)。
(注3)WindowsNT では、拡張されたメンバは無視されます。
32ビットアプリケーションで、この構造体を利用するときには、利用しない項目を 確実にNULLで初期化しておく必要があります。
DOCINFO 構造体にゴミが入っていると、StartDoc() が異常終了する ためです。

11-3 拡張メタファイルの印刷とWYSIWYG

 Windowsでの印刷処理は、ディスプレイに描画するときとほとんど同様に行うことが できます。ディスプレイと異なる点は、以下のとおりです。
  1. 描画処理の前後に印刷するページを管理する処理が必要なこと
  2. 実際に印字できる領域は印字可能範囲に限られる (物理的な用紙サイズの全体に描画ができる訳ではない)
  3. デバイス全体が一つの描画領域であること (ディスプレイのようにウインドウで区切られることはない)
○印字可能範囲の取得
印字可能範囲は、プリンタデバイスコンテキストから取得することができます。
Windows3.1 では、これらの情報を取得するために Escape() を 利用します。
WindowsNTでは同様に利用できますが、Windows95 では、どエスケープ関数がほとんど 廃止されました。Windows95でサポートされるエスケープ関数を表11-3に 示します。
このため、新しく作成する32ビットアプリケーションではできるだけ、 Escape() の利用は避けたほうがようでしょう。

○エスケープ関数の代わりの関数
表11-3のエスケープ関数のほとんどは、Win32APIでサポートされています。
GetDeviceCaps() で取得する情報は、印刷を行うときには、重要な情報を 提供します(図11-4)。この情報はディスプレイドライバやプリンタドライバ から取得されます。
アプリケーションはこれらの情報から、実際に印字できるデバイスの性能を取得 することができます。
なお、プリンタはディスプレイと異なり、印字可能範囲があり、必ず、
 印字可能範囲 < 用紙サイズ
となります。
ディスプレイにプリンタの印刷イメージを表示させるときには、少なくとも、印字可能 範囲と印字オフセットを意識する必要があります。
これらの値は、プリンタの解像度のピクセル値で取得でき、ディスプレイでこの値を 利用するときは、ディスプレイの解像度に合せたピクセル値に変換する必要が あります。

表11-3:Windows95でサポートされるエスケープ
ABORTDOC
ENDDOC
GETPHYSPAGESIZE
GETPRINTINGOFFSET
GETSCALINGFACTOR
NEWFRAME
NEXTBAND
SETABORTPROC
SETCOPYCOUNT
STARTDOC

表11-4:Win32APIとEscape()ファンクションの関係
Win32 APIEscape()ファンクション
AbortDoc() ABORTDOC
EndDoc() ENDDOC
EndPage() NEWFRAME
SetAbortProc() SETABORTPROC
StartDoc() STARTDOC
GetDeviceCaps(PHYSICALWIDTH) GETPHYSPAGESIZE
GetDeviceCaps(PHYSICALHEIGHT) GETPHYSPAGESIZE
GetDeviceCaps(PHYSICALOFFSETX) GETPRINTINGOFFSET
GetDeviceCaps(PHYSICALOFFSETY) GETPRINTINGOFFSET
GetDeviceCaps(SCALINGFACTORX) GETSCALINGFACTOR
GetDeviceCaps(SCALINGFACTORY) GETSCALINGFACTOR


図11-4:用紙サイズの情報

|←-------------(1)------------→| | | | |←---------(3)--------→| | | | | | → |(5)|← | | ↓ +--------------------------------+ ----------- | | (6) ↑ | +------------------------+ | ------- | | | | | ↑ ↑ | | | | | | | | | | | | | | | | | | | | | | | | | | | 印字可能範囲 | | | | | | | | (4) (2) | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ↓ | | +------------------------+ | ------- | | | ↓ +--------------------------------+ ------------ (1) 物理用紙幅 GetDeviceCaps(PHYSICALWIDTH) (2) 物理用紙高 GetDeviceCaps(PHYSICALHEIGHT) (3) 印字可能領域幅 GetDeviceCaps(HORZRES) (4) 印字可能領域高 GetDeviceCaps(VERTRES) (5) 印刷可能領域の水平マージン GetDeviceCaps(PHYSICALOFFSETX) (6) 印刷可能領域の垂直マージン GetDeviceCaps(PHYSICALOFFSETY)


○プリンタに出力する場合の注意点
拡張メタファイルをプリンタに出力するときに注意しなければならない点は、 一般的にディスプレイと比較してはるかに解像度が高いことや、印刷するために生成 したメタファイルは印刷する用紙サイズを意識することが多いため、他のプリンタ用に 生成したメタファイルでも、表示データの寸法が正確に再生されなければならない点 です。
プリンタはそれ自身に能力の違いがありますが、印刷を行う用紙サイズはA4、 B4などのように、プリンタことに変化しないため、意図的に印刷する用紙サイズを 変更して拡大・縮小を行わない限り、指定されたサイズをできるだけ忠実に再生する 必要があります。

○拡張メタファイルと文字の重ね合わせ
一般的にビジネスで使用する帳票は、ミリやインチで表や文字の位置を決めることが 多いようです。そのような帳票を印刷するアプリケーションが印字処理を行う場合、 メタファイルと重ねあわせる印字データもミリやインチで印字位置を決定することに なります。
このため、拡張メタファイルの描画位置とアプリケーションが印字する文字 などの位置を一致させるには、メタファイルの描画で得られる図形がどのような デバイスで再生しても寸法が変化しないようにする必要があります (図11-5)。

○印字可能範囲が異なるプリンタで同じメタファイルを再生するには
参照デバイスより印字可能範囲が狭いデバイスで拡張メタファイルを 再生する必要があるときは、印字可能範囲が狭いデバイスに合わせてメタファイルを 生成するか、デバイスごとにメタファイルを生成するなどの考慮が必要になります (図11-6)。
また、印刷する図形の位置やサイズに依存せず、どのデバイスでも図形全体を表示 させたいときは、拡張メタファイルのピクチャフレームで得られる0.01[mm]単位の サイズを、デバイスで表示できる範囲に縮小することにより可能です。



図11-5:拡張メタファイルで表を作成する例
+--------------+ +--------------+ +--------------+ | | | +--+-------+ | | +--+-------+ | | A 100 | | | | | | | | A| 100| | | | | +--+-------+ | | +--+-------+ | | B 200 | + | | | | | = | | B| 200| | | | | +--+-------+ | | +--+-------+ | | C 300 | | | | | | | | C| 300| | | | | +--+-------+ | | +--+-------+ | | D 400 | | | | | | | | D| 400| | | | | +--+-------+ | | +--+-------+ | +--------------+ +--------------+ +--------------+ 印字データ 拡張メタファイル 印刷結果 表をメタファイルで生成したとき、メタファイルと 印刷データの縮尺や位置が正確に一致しなければ 正しい印字結果を得ることができない。
図11-6:印字可能範囲で異なるプリンタで同じメタファイルを再生
+--------------+ +--------------+ +--------------+ | +----------+ | | +--------- | | +--------+ | | | | | | | | | | | | | | | | | | | | | | | | | 図形 | | | | 図形 | | | 図形 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +--------+ | | +----------+ | | | | | +--------------+ +--------------+ +--------------+ (1) (2) (3) (1) 参照デバイスのプリンタで再生 (図形は正確に再生される) (2) 印字可能範囲が参照デバイスより狭いプリンタで再生 (範囲外の図形は切れてしまう) (3) 印字可能範囲が参照デバイスより狭いプリンタで再生 (メタファイルを縮小して表示)



○印字位置の誤差
拡張メタファイルは、あらゆるデバイスに対して同一の描画を可能にしますが、 デバイスの解像度が低い場合、印字位置に誤差が生じます。 また、メタファイルをデバイスに表示するときには、必ずドライバがもつデバイス情報 に依存します。
このため、デバイスドライバが返す数値に誤差や間違いがある場合、 正しい位置やサイズで表示できない可能性があります。
さらに、プリンタドライバの印字可能範囲は、プリンタドライバを介さずに(スプーラ に直接プリンタコードを出力する)印刷するときと比較して狭いことがあり、プリンタ のすべての印字領域を利用することができないことがあります。

○誤差の抑制
前述したとおり、拡張メタファイルに記録する図形のサイズは、0.01[mm] 単位で 指定することができます。
設定された値は、再生時に GetEnhMetaFileHeader()ENHMETAHEADER 構造体を取得し、rclFrame メンバから取得することができます。
拡張メタファイルデバイスコンテキストに対して描画を行う場合、どのマッピング モードでも描画することができますが、図形のサイズを正確に再生しなければならない ときは、MM_HIMETRIC のような 0.01[mm] を基本単位にするマッピングモード が有利になります(リスト11-7)。
フォントを描画するとき、そのサイズはポイント数で制御しているため、 MM_TWIPS で描画すると誤差を少なくすることができます。
プログラムで座標やサイズの変換を行うと計算誤差が出やすく、正しいサイズの図形が 得られなくことがありますので、用途に合わせて適切なマッピングモードで描画する 必要があります。

○ディスプレイを参照デバイスにした場合
参照デバイスがプリンタの場合、GetDeviceCaps() で取得できる印字可能範囲 全体に印字を行いますが、ディスプレイを参照デバイスにした場合、メタファイルの 表示を行うウインドウのクライアント領域がメタファイルの印字可能範囲に なります。
このため、プリンタのように HORZSIZE, VERTSIZE を利用することが できません。ディスプレイ上で拡張メタファイルを再生する場合、ウインドウの クライアント領域を取得して 0.01[mm] 単位の矩形に変換する必要があります (リスト11-8)。

○拡張メタファイルの再生
拡張ファイルの再生は、PlayEnhMetaFile() で行うことが できます(リスト11-9)。
このとき、拡張メタファイルを再生する矩形を正確に設定しなければ、正しいサイズで 描画することができません。これらの情報は、ENHMETAHEADER 構造体に 格納され、参照したデバイスの情報を得ることもできます。 拡張メタファイルの生成に設定した、再生領域の矩形を再生するデバイスでのサイズ を計算し、PlayEnhMetaFile() の引数に設定して実行します。
これによって、拡張メタファイルの図形を、表示するデバイスで正確に再生することが できます。
拡張メタファイルにパレットが含まれるとき、 アプリケーションが出力デバイスの カラーパレットを設定してから再生することにより、色の一貫性を保てます。
ほとんどの場合、PlayEnhMetaFile() で描画できますが、 ENHMETARECORD 構造体の内容を追加・変更・削除する必要があるときは、 EnumEnhMetaFile() を利用することにより拡張メタファイルに書き込まれた GDI関数を取得することができます。
EnhMetaFileProc() 内で処理を行わないレコードは、 PlayEnhMetaFileRecord() に渡すことにより、処理を行わせることが できます。



リスト11-7:MM_HIMETRICを指定した拡張メタファイルの生成
/* 参照デバイス(プリンタ)のDCを得る */ hDC = CreateDC(lpszDriver, lpszDevice, lpszOutput, NULL); /* デバイスの印字可能サイズを得る 1/100[mm]単位 */ rect.left = 0; rect.top = 0; rect.right = GetDeviceCaps(hPrnDC, HORZSIZE) * 100; rect.bottom = GetDeviceCaps(hPrnDC, VERTSIZE) * 100; /* メタファイルのDCを得る */ hMetaDC = CreateEnhMetaFile(hDC, lpszMetaFile, &rect, "Sample"); /* (0, 0) - (iMMX*100, -iMMY*100) の矩形に描画を行う */ SetMapMode(hMetaDC, MM_HIMETRIC); 描画処理 : : /* 終了処理 */ DeleteEnhMetaFile(CloseEnhMetaFile(hMetaDC)); DeleteDC(hDC);
リスト11-8:ウィンドウのクライアント領域サイズを0.01mm単位で得る
/* 論理インチ単位から算出 */ GetClientRect(hWnd, &rect); iLogX = GetDeviceCaps(hdc, LOGPIXELSX); iLogY = GetDeviceCaps(hdc, LOGPIXELSY); rect.right = MulDiv(rect.right, 2540, iLogX); rect.bottom = MulDiv(rect.bottom, 2540, iLogY); /* ミリ単位から算出 */ GetClientRect(hWnd, &rect); iMMX = GetDeviceCaps(hdc, HORZSIZE); iMMY = GetDeviceCaps(hdc, VERTSIZE); iDevX = GetDeviceCaps(hdc, HORZRES); iDevY = GetDeviceCaps(hdc, VERTRES); rect.right = MulDiv(rect.right, iMMX * 100, iDevX); rect.bottom = MulDiv(rect.bottom, iMMY * 100, iDevY);
リスト11-9:メタファイルを再生する
/* ハンドルをオープンする */ hMeta = GetEnhMetaFile(lpszMetaFileName); hdc = GetDC(hWnd); /* 表示デバイスの描画範囲を得る */ GetClientRect(hWnd, &rect); /* メタファイルを再生する */ PlayEnhMetaFile(hdc, hMeta, &rect); /* ハンドルの解放 */ DeleteEnhMetaFile(hMeta); ReleaseDC(hWnd, hdc);



11-4 プログラムについて

○ソースリスト \META
拡張メタファイルの表示、印刷処理と、生成処理のサンプルプログラムです。
☆拡張メタファイル表示/印刷サンプル
拡張メタファイルを読み込み、ディスプレイとプリンタに出力します。
ディスプレイには、単純にメタファイルを描画した状態と、プリンタの設定を行う ことにより、プリンタに出力したときの印刷イメージを表示します。 そして、印刷イメージの左にプリンタの表示能力を表示します。
ディスプレイに表示するときは、取得した座標の1/4で表示し、[操作]-[拡大],[縮小] で表示倍率を変化させることができます。ただし、印刷は常に原寸で行います。
他のアプリケーションで生成した拡張メタファイルでも、再生して印刷することが できますので、拡張メタファイルの調査やテストに利用できます。
METAPRN.C(ソースファイル)
METAPRN.H(ヘッダファイル)
RESOURCE.H(リソースヘッダファイル)
METAPRN.RC(リソースファイル)
METAPRN.ICO(アイコンファイル)
MAKEFILE.MP(メイクファイル)
☆拡張メタファイル生成サンプル
プリンタデバイスコンテキストを参照デバイスにした、拡張メタファイルを生成 します。図形は、MM_HIMETRIC でマッピングし、参照プリンタデバイスの印字可能 範囲全体(実際には、1[mm] 引いています)に 10[mm] 単位のグリッドを 描画します。
生成するメタファイルのファイル名は、 ENHMETA.EMF で固定です。
ENHMETA.C(ソースファイル)
MAKEFILE.EM(メイクファイル)

○おわりに
主要な16ビットアプリケーションは、ほぼ32ビット化されつつありますが、 まだ使い慣れた16ビットアプリケーションを手放せない状態から抜け出せません。
32ビットの図形作成ツールが一般的になり、拡張メタファイルが流通するように なれば、拡張メタファイルの用途はさらに広がるのではないかと思われます。