SetMapMode

SetMapModeで、印刷や描画する時の出力単位を、デバイスピクセル単位や、メートル単位など、指定のものに切り替えられる。

SetMapMode function (wingdi.h) - Win32 apps | Microsoft Docs
マッピングモード

新しくプリンタを買いまして、

f:id:BG1:20200620133547p:plain
プリンタ名をメモ

プリンタ名をメモしておく。

							// 取得したプリンタ名のプリンタで"ABCDE"を印刷.
							DOCINFO di = {0};	// DOCINFO構造体diを{0}で初期化.
							di.cbSize = sizeof(DOCINFO);	// sizeofでDOCINFOのサイズを指定.
							di.lpszDocName = _T("SetMapMode");	// ドキュメント名は"SetMapMode"とする.
							hPrinterDC = CreateDC(NULL, ptszPrinterName, NULL, NULL);	// CreateDCでptszPrinterNameのデバイスコンテキストハンドルhPrinterDCを取得.
							if (hPrinterDC != NULL){	// hPrinterDCがNULLでなければ.
								iRetSD = StartDoc(hPrinterDC, &di);	// StartDocで印刷ジョブの開始.
								if (iRetSD > 0){	// 印刷開始成功.
									iRetSP = StartPage(hPrinterDC);	// StartPageでページの開始.
									if (iRetSP > 0){	// ページ開始成功.
										TextOut(hPrinterDC, 0, 0, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(0, 0)の位置に"ABCDE"を描画.
										EndPage(hPrinterDC);	// EndPageでページ終了.
									}
									EndDoc(hPrinterDC);	// EndDocで印刷ジョブ終了.
								}
								DeleteDC(hPrinterDC);	// DeleteDCでhPrinterDCを削除.
							}

以前、StartDocの項で作ったプログラムをベースとする。
最初、(0, 0)に"ABCDE"を印刷。

プリンタ名を入れる
プリンタ名を入れる

エディットコントロールにプリンタ名を入れる。

こんな感じ
こんな感じ

こんな感じ。

Printで印刷
Printで印刷

Printで印刷。

ここが原点
ここが原点

ここが原点。

										//TextOut(hPrinterDC, 0, 0, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(0, 0)の位置に"ABCDE"を描画.
										TextOut(hPrinterDC, 50, 50, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(50, 50)の位置に"ABCDE"を描画.
										EndPage(hPrinterDC);	// EndPageでページ終了.

(50, 50)に変更すると、

右下に移動する
右下に移動する

2つを比較すると、これだけ右下に移動する。

										//TextOut(hPrinterDC, 0, 0, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(0, 0)の位置に"ABCDE"を描画.
										//TextOut(hPrinterDC, 50, 50, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(50, 50)の位置に"ABCDE"を描画.
										TextOut(hPrinterDC, 10, 10, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(10, 10)の位置に"ABCDE"を描画.
										EndPage(hPrinterDC);	// EndPageでページ終了.

今度は(10, 10)に変更、

(50, 50)よりは左上に戻っている
(50, 50)よりは左上に戻っている

(50, 50)よりはだいぶ左上に戻っている。
というかほんの少ししか右下に移動していない。

										//TextOut(hPrinterDC, 0, 0, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(0, 0)の位置に"ABCDE"を描画.
										//TextOut(hPrinterDC, 50, 50, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(50, 50)の位置に"ABCDE"を描画.
										SetMapMode(hPrinterDC, MM_LOMETRIC);	// SetMapModeで, 1デバイスピクセル単位から0.1ミリ単位に変更, かつY軸を下に向かって増加からY軸を上に向かって増加に変更.
										TextOut(hPrinterDC, 10, 10, _T("ABCDE"), _tcslen(_T("ABCDE")));	// TextOutでプリンタの(10, 10)の位置に"ABCDE"を描画.
										EndPage(hPrinterDC);	// EndPageでページ終了.

ここで、SetMapModeでMM_LOMETRICを指定して、(10, 10)で出力すると、

上が切れている
上が切れている

上が切れている。
1デバイスピクセル単位から、0.1ミリメートル単位に切り替わる。
さらに、Y軸方向が下に増加から、上に増加に切り替わる。
そのため、10 * 0.1ミリメートル = 1ミリメートル原点より上から描画されるため、1ミリメートル切れてしまっている。

そこで、(10, -10)というようにY軸座標はマイナスで指定すると、

Y軸座標は1ミリ下に描画される
Y軸座標は1ミリ下に描画される

Y軸座標は1ミリ下に描画される。

Sample/winapi/SetMapMode/SetMapMode/src/SetMapMode at master · bg1bgst333/Sample · GitHub