開発環境 Microsoft Visual C++ 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Win32 プロジェクト
プロジェクト名 PrnTest
アプリケーションの種類 Windows アプリケーション
追加のオプション 空のプロジェクト
文字セット Unicode

参考

PrnTest.c
// Unicode文字セット
 
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include "resource.h"
 
#define pxtolm(px,dpi) ((px) * 254 / (dpi))	// Pixel to LoMetric
#define lmtopx(lm,dpi) ((lm) * (dpi) / 254)	// LoMetric to Pixel
#define LOGWRITE(fmt,var) LogWrite(TEXT(#var)TEXT("=[")fmt##TEXT("]\n"), var)
 
// プリンタ能力
typedef struct {
	int nHorzRes;		// 印刷可能領域の幅 (ピクセル単位)
	int nVertRes;		// 印刷可能領域の高さ (ピクセル単位)
	int nPhysicalWidth;	// 物理ページ全体の幅 (ピクセル単位)
	int nPhysicalHeight;	// 物理ページ全体の高さ (ピクセル単位)
	int nPhysicalOffsetX;	// 物理ページの左辺から印刷可能領域の左辺までの距離 (ピクセル単位)
	int nPhysicalOffsetY;	// 物理ページの上辺から印刷可能領域の上辺までの距離 (ピクセル単位)
	int nDpiX;		// 水平方向のピクセル数 (論理インチ当たり)
	int nDpiY;		// 垂直方向のピクセル数 (論理インチ当たり)
} PRNCAPS;
 
// 関数プロトタイプ宣言
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnInitDialog(HWND hDlg);
void OnPageSetup(HWND hDlg);
void OnPrint(HWND hDlg);
void TestPrint(HDC hdc);
void OnDestroy(void);
void TracePrnInfo(void);
void GetPrnCaps(HDC hdc, PRNCAPS *ppc);
 
int LogOpen(void);
void LogClose(void);
void LogWrite(LPCTSTR format, ...);
int LogCopy(HWND hEdit);
 
// 外部変数
HWND g_hEdit;
HGLOBAL g_hDevMode = NULL;	// デバイスモード構造体ハンドル
HGLOBAL g_hDevNames = NULL;	// デバイス名構造体ハンドル
 
TCHAR g_szLog[MAX_PATH];
FILE *g_pLog = NULL;
 
//==============================================================================
int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DialogProc);
	return 0;
}
 
//------------------------------------------------------------------------------
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	INT_PTR iRet = TRUE;	// メッセージを処理した
 
	switch (uMsg) {
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_PAGESETUP:
			OnPageSetup(hDlg);
			break;
		case IDC_PRINT:
			OnPrint(hDlg);
			break;
		}
		break;
	case WM_INITDIALOG:
		OnInitDialog(hDlg);
		iRet = TRUE;	// SetFocusでフォーカスを設定した場合はFALSE
		break;
	case WM_CLOSE:
		EndDialog(hDlg, IDOK);
		break;
	case WM_DESTROY:
		OnDestroy();
		break;
	default:
		iRet = FALSE;	// メッセージを処理しなかった
	}
	return iRet;
}
 
//------------------------------------------------------------------------------
void OnInitDialog(HWND hDlg)
{
	PRINTDLGEX pd;
	HRESULT hr;
 
	g_hEdit = GetDlgItem(hDlg, IDC_EDIT);
 
	// デフォルトプリンタの取得
	ZeroMemory(&pd, sizeof pd);
	pd.lStructSize	= sizeof pd;
	pd.hwndOwner	= hDlg;
	pd.Flags	= PD_RETURNDEFAULT | PD_NOPAGENUMS;
	pd.nStartPage	= START_PAGE_GENERAL;
	hr = PrintDlgEx(&pd);
	if (FAILED(hr)) {
		return;
	}
	g_hDevMode = pd.hDevMode;
	g_hDevNames = pd.hDevNames;
 
	TracePrnInfo();
}
/*
	PRINTDLG pd;
	BOOL br;
 
	ZeroMemory(&pd, sizeof pd);
	pd.lStructSize	= sizeof pd;
	pd.Flags	= PD_RETURNDEFAULT;
	br = PrintDlg(&pd);
	if (br == FALSE) {
		return;
	}
*/
 
//------------------------------------------------------------------------------
void OnPageSetup(HWND hDlg)
{
	PAGESETUPDLG psd;
	BOOL br;
 
	// ページ設定ダイアログ
	ZeroMemory(&psd, sizeof psd);
	psd.lStructSize	= sizeof psd;
	psd.hwndOwner	= hDlg;
	psd.hDevMode	= g_hDevMode;
	psd.hDevNames	= g_hDevNames;
	psd.Flags	= 0;
	br = PageSetupDlg(&psd);
	if (br == FALSE) {
		return;	// キャンセル時、デバイス構造体ハンドルはそのまま
	}
	g_hDevMode = psd.hDevMode;
	g_hDevNames = psd.hDevNames;
 
	TracePrnInfo();
}
/*
	PRINTDLG pd;
	BOOL br;
 
	ZeroMemory(&pd, sizeof pd);
	pd.lStructSize	= sizeof pd;
	pd.hwndOwner	= hDlg;
	pd.hDevMode	= g_hDevMode;
	pd.hDevNames	= g_hDevNames;
	pd.Flags	= PD_PRINTSETUP;
	br = PrintDlg(&pd);
	if (br == FALSE) {
		return;	// キャンセル時、デバイス構造体ハンドルはそのまま
	}
*/
 
//------------------------------------------------------------------------------
void OnPrint(HWND hDlg)
{
	PRINTDLGEX pd;
	HRESULT hr;
	BOOL br;
 
	// 印刷ダイアログ
	ZeroMemory(&pd, sizeof pd);
	pd.lStructSize	= sizeof pd;
	pd.hwndOwner	= hDlg;
	pd.hDevMode	= g_hDevMode;
	pd.hDevNames	= g_hDevNames;
	pd.Flags	= PD_NOPAGENUMS | PD_RETURNDC;
	pd.nStartPage	= START_PAGE_GENERAL;
	hr = PrintDlgEx(&pd);
	if (FAILED(hr)) {
		return;
	}
	g_hDevMode = pd.hDevMode;
	g_hDevNames = pd.hDevNames;
	if (pd.dwResultAction != PD_RESULT_PRINT) {
		return;
	}
 
	// テスト印刷
	TestPrint(pd.hDC);
	br = DeleteDC(pd.hDC);
}
 
//------------------------------------------------------------------------------
void TestPrint(HDC hdc)
{
	PRNCAPS pc;
	DOCINFO di;
	HPEN hPen;
	HGDIOBJ hPenOld;
	RECT rcMargin;		// 余白
	RECT rc;
	BOOL br;
	int nr;
 
	// デバイス能力の取得
	GetPrnCaps(hdc, &pc);
 
	// 最小余白
	rcMargin.left	= pc.nPhysicalOffsetX;
	rcMargin.top	= pc.nPhysicalOffsetY;
	rcMargin.right	= pc.nPhysicalWidth - pc.nHorzRes - pc.nPhysicalOffsetX;
	rcMargin.bottom	= pc.nPhysicalHeight - pc.nVertRes - pc.nPhysicalOffsetY;
 
	// 余白10.0mmの枠
	rcMargin.left	= max(lmtopx(100, pc.nDpiX), rcMargin.left);
	rcMargin.top	= max(lmtopx(100, pc.nDpiY), rcMargin.top);
	rcMargin.right	= max(lmtopx(100, pc.nDpiX), rcMargin.right);
	rcMargin.bottom	= max(lmtopx(100, pc.nDpiY), rcMargin.bottom);
 
	SetRect(&rc, rcMargin.left, rcMargin.top,
		pc.nPhysicalWidth - rcMargin.right, pc.nPhysicalHeight - rcMargin.bottom);
	OffsetRect(&rc, -pc.nPhysicalOffsetX, -pc.nPhysicalOffsetY);
 
	// 開始
	ZeroMemory(&di, sizeof di);
	di.cbSize	= sizeof di;
	di.lpszDocName	= TEXT("test print");
	nr = StartDoc(hdc, &di);
	nr = StartPage(hdc);
 
	// 幅0.3mmの黒いペン
	hPen = CreatePen(PS_INSIDEFRAME, lmtopx(3, pc.nDpiY), RGB(0x00,0x00,0x00));
	hPenOld = SelectObject(hdc, hPen);
	br = Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
	SelectObject(hdc, hPenOld);
	br = DeleteObject(hPen);
 
	// 終了
	nr = EndPage(hdc);
	nr = EndDoc(hdc);
}
 
//------------------------------------------------------------------------------
void OnDestroy(void)
{
	HGLOBAL hr;
 
	hr = GlobalFree(g_hDevMode);
	hr = GlobalFree(g_hDevNames);
}
 
//------------------------------------------------------------------------------
void TracePrnInfo(void)
{
	LPDEVNAMES pdn;
	LPDEVMODE pdm;
	HDC hdc;		// 情報コンテキスト。デバイス準備不要。GDI出力不可
	LPTSTR pszDriver;	// ドライバ名
	LPTSTR pszDevice;	// デバイス名
	LPTSTR pszPort;		// 出力ポート名
	PRNCAPS pc;
	int nWidth;
	int nHeight;
	BOOL br;
 
	// ログ開始
	LogOpen();
 
	// デバイス名構造体
	pdn = (LPDEVNAMES)GlobalLock(g_hDevNames);
	pszDriver = _tcsdup((LPCTSTR)pdn + pdn->wDriverOffset);
	pszDevice = _tcsdup((LPCTSTR)pdn + pdn->wDeviceOffset);
	pszPort = _tcsdup((LPCTSTR)pdn + pdn->wOutputOffset);
	br = GlobalUnlock(g_hDevNames);
 
	LOGWRITE(TEXT("%s"), pszDriver);
	LOGWRITE(TEXT("%s"), pszDevice);
	LOGWRITE(TEXT("%s"), pszPort);
 
	// デバイスモード構造体
	pdm = (LPDEVMODE)GlobalLock(g_hDevMode);
	hdc = CreateIC(pszDriver, pszDevice, pszPort, pdm);
	GlobalUnlock(g_hDevMode);
 
	GetPrnCaps(hdc, &pc);
	br = DeleteDC(hdc);
 
	LogWrite(TEXT("\n"));
	LOGWRITE(TEXT("%d px"), pc.nHorzRes);
	LOGWRITE(TEXT("%d px"), pc.nVertRes);
	LOGWRITE(TEXT("%d px"), pc.nPhysicalWidth);
	LOGWRITE(TEXT("%d px"), pc.nPhysicalHeight);
	LOGWRITE(TEXT("%d px"), pc.nPhysicalOffsetX);
	LOGWRITE(TEXT("%d px"), pc.nPhysicalOffsetY);
	LOGWRITE(TEXT("%d dpi"), pc.nDpiX);
	LOGWRITE(TEXT("%d dpi"), pc.nDpiY);
 
	// 計算
	nWidth = pxtolm(pc.nPhysicalWidth, pc.nDpiX);
	nHeight = pxtolm(pc.nPhysicalHeight, pc.nDpiY);
 
	LogWrite(TEXT("\n"));
	LOGWRITE(TEXT("%d * 0.1mm"), nWidth);
	LOGWRITE(TEXT("%d * 0.1mm"), nHeight);
 
	// ログ終了・エディットコントロールに転記
	LogClose();
	LogCopy(g_hEdit);
 
	free(pszPort);
	free(pszDevice);
	free(pszDriver);
}
 
//------------------------------------------------------------------------------
void GetPrnCaps(HDC hdc, PRNCAPS *ppc)
{
	ppc->nHorzRes = GetDeviceCaps(hdc, HORZRES);
	ppc->nVertRes = GetDeviceCaps(hdc, VERTRES);
	ppc->nPhysicalWidth = GetDeviceCaps(hdc, PHYSICALWIDTH);
	ppc->nPhysicalHeight = GetDeviceCaps(hdc, PHYSICALHEIGHT);
	ppc->nPhysicalOffsetX = GetDeviceCaps(hdc, PHYSICALOFFSETX);
	ppc->nPhysicalOffsetY = GetDeviceCaps(hdc, PHYSICALOFFSETY);
	ppc->nDpiX = GetDeviceCaps(hdc, LOGPIXELSX);
	ppc->nDpiY = GetDeviceCaps(hdc, LOGPIXELSY);
}
 
//==============================================================================
int LogOpen(void)
{
	TCHAR szPath[_MAX_PATH];
	TCHAR szDrive[_MAX_DRIVE];
	TCHAR szDir[_MAX_DIR];
	TCHAR szFName[_MAX_FNAME];
	TCHAR szExt[_MAX_EXT];
	DWORD dw;
	errno_t er;
 
	// 実行ファイル名からログファイル名を作る
	dw = GetModuleFileName(NULL, szPath, _countof(szPath));
	if (dw == 0) {
		return -1;
	}
	er = _tsplitpath_s(szPath,
		szDrive, _countof(szDrive), szDir, _countof(szDir),
		szFName, _countof(szFName), szExt, _countof(szExt));
	if (er != 0) {
		return -1;
	}
	er = _tmakepath_s(g_szLog, _countof(g_szLog), szDrive, szDir, szFName, _T("log"));
	if (er != 0) {
		return -1;
	}
 
	// ログファイルのオープン
	er = _tfopen_s(&g_pLog, g_szLog, TEXT("wt,ccs=UNICODE"));
	if (er != 0) {
		return -1;
	}
 
	return 0;
}
 
//------------------------------------------------------------------------------
void LogClose(void)
{
	// ログファイルのクローズ
	fclose(g_pLog);
}
 
//------------------------------------------------------------------------------
void LogWrite(LPCTSTR format, ...)
{
	va_list arg_ptr;
	int ir;
 
	va_start(arg_ptr, format);
	ir = _vftprintf_s(g_pLog, format, arg_ptr);
	va_end(arg_ptr);
}
 
//------------------------------------------------------------------------------
int LogCopy(HWND hEdit)
{
	HANDLE hFile;
	HANDLE hMap;
	LPBYTE pBaseAddr;
	BOOL br;
 
	// ログファイルのメモリマップ割当
	hFile = CreateFile(g_szLog, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		return -1;
	}
	hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
	if (hMap == NULL) {
		return -1;
	}
	pBaseAddr = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
	if (pBaseAddr == NULL) {
		return -1;
	}
 
	// コピー
	br = SetWindowText(hEdit, (LPCTSTR)(pBaseAddr + 2));	// BOM(ff fe)読み飛ばし
	PostMessage(hEdit, EM_SETSEL, 0, 0);	// Sendはダメみたい
 
	// ログファイルのメモリマップ解除
	br = UnmapViewOfFile(pBaseAddr);
	br = CloseHandle(hMap);
	br = CloseHandle(hFile);
 
	return 0;
}
 

resource.h
#define IDD_DIALOG	100
#define IDC_EDIT	1000
#define IDC_PAGESETUP	1001
#define IDC_PRINT	1002
 

PrnTest.rc
// resource script
#include <windows.h>
#include "resource.h"
 
IDD_DIALOG DIALOGEX 100, 100, 300, 240
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION "PrnTest"
FONT 9, "MS Pゴシック"
BEGIN
	EDITTEXT	IDC_EDIT,4,4,200,200,
			ES_MULTILINE | ES_WANTRETURN | ES_AUTOVSCROLL | WS_VSCROLL
	PUSHBUTTON	"ページ設定(&U)",IDC_PAGESETUP,208,4,64,16
	PUSHBUTTON	"印刷(&P)",IDC_PRINT,208,28,64,16
END
 

出力
pszDriver=[winspool]
pszDevice=[Canon iP2700 series]
pszPort=[USB001]

pc.nHorzRes=[4800 px]
pc.nVertRes=[6826 px]
pc.nPhysicalWidth=[4960 px]
pc.nPhysicalHeight=[7015 px]
pc.nPhysicalOffsetX=[80 px]
pc.nPhysicalOffsetY=[70 px]
pc.nDpiX=[600 dpi]
pc.nDpiY=[600 dpi]

nWidth=[2099 * 0.1mm]
nHeight=[2969 * 0.1mm]
最終更新:2012年10月06日 05:23