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

参考

a2pr.cpp
// マルチバイト文字セット
 
#include <Windows.h>
#include <WindowsX.h>
#include <tchar.h>
#include <stdio.h>
#include <time.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 WIDTH(rect) (rect.right - rect.left)
#define HEIGHT(rect) (rect.bottom - rect.top)
#define SECT_GEN _T("General")
 
// 関数プロトタイプ宣言
int GetIniFileName(void);
void WriteIniFileInt(LPCTSTR pszSect, LPCTSTR pszKey, int nVal);
int OpenMemMapFile(HWND hWnd);
void CloseMemMapFile(void);
DWORD CheckFile(void);
void DebugCodeTable(int nType);
 
INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnOK(HWND hDlg);
int GetDlgData(HWND hDlg);
void OnDropFiles(HWND hDlg, WPARAM wParam);
void OnInitDialog(HWND hDlg);
void OnDestroy(HWND hDlg);
 
int PrintProc(void);
int PreparePrint(void);
int PageProc(void);
int LineProc(int nPage, int nLine);
int PrintLine(LPCTSTR pszLine, int nLen, int nPage, int nLine);
 
// 外部変数構造体
static struct {
	TCHAR szIniFile[MAX_PATH];
	HWND hWndDir;
	HWND hWndFile;
	HGLOBAL hDevMode;	// デバイスモード構造体ハンドル
	HGLOBAL hDevNames;	// デバイス名構造体ハンドル
	HDC hdc;		// プリンタDC
	HFONT hFont[4];		// フォント 0:ANSI(半角英数) 1:SHIFTJIS(半角カナ・全角) 2:大 3:小
	int nPrintStyle;	// 帳票形式
	int nTabStop;		// タブストップ数
 
	// 帳票形式
	RECT rcMargin;		// 物理ページ余白
	int nMarginWidth;	// 物理ページ中央余白
	int nPageNum;		// 論理ページ数
	int nLineNum;		// 行数
	int nColNum;		// 列数
 
	// 対象ファイル
	TCHAR szPath[MAX_PATH];
	TCHAR szFile[MAX_PATH];
	HANDLE hFile;
	HANDLE hMap;
	LPBYTE pBaseAddr;
	DWORD dwFileSize;
	DWORD dwPos;
 
	// プリンタ能力
	int nHorzRes;		// 印刷可能領域の幅 (ピクセル単位)
	int nVertRes;		// 印刷可能領域の高さ (ピクセル単位)
	int nPhysicalWidth;	// 物理ページ全体の幅 (ピクセル単位)
	int nPhysicalHeight;	// 物理ページ全体の高さ (ピクセル単位)
	int nPhysicalOffsetX;	// 物理ページの左辺から印刷可能領域の左辺までの距離 (ピクセル単位)
	int nPhysicalOffsetY;	// 物理ページの上辺から印刷可能領域の上辺までの距離 (ピクセル単位)
	int nDpiX;		// 水平方向のピクセル数 (論理インチ当たり)
	int nDpiY;		// 垂直方向のピクセル数 (論理インチ当たり)
 
	// 印刷座標
	RECT rcPrint;		// 印刷範囲=物理ページ
	RECT rcLogPage[2];	// 論理ページ範囲
	int nLogPageWidth;	// 論理ページの幅
	int nLogPageHeight;	// 論理ページの高さ
	int nBodyTop;		// 本文の上辺
	int nBodyHeight;	// 本文の高さ
	int nLineHeight;	// 行の高さ
 
	int nPhyPageNo;		// 物理ページ番号
	int nLineNo;		// 行番号
	BOOL bLineCont;		// 行継続フラグ
	TCHAR szTime[19+1];	// タイムスタンプ
} g;
 
//==============================================================================
#define CHPRINT 0x1
#define IsPrint(c) ((ChType+1)[c] & CHPRINT)
 
unsigned char ChType[256+1] = {0};
 
// 文字種情報の初期化
void InitChType(void)
{
	int n;
 
	// IsPrint
	for (n = 0x20; n <= 0x7e; n++) {
		ChType[n+1] |= CHPRINT;
	}
	for (n = 0xa1; n <= 0xdf; n++) {
		ChType[n+1] |= CHPRINT;
	}
}
 
//==============================================================================
int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR lpCmdLine,
	int nCmdShow)
{
	InitChType();	// 文字種情報の初期化
	if (GetIniFileName()) {
		MessageBox(NULL, _T("iniファイル名の取得に失敗しました"), NULL, MB_OK);
		return 0;
	}
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), NULL, DialogProc);
	return 0;
}
 
//------------------------------------------------------------------------------
int GetIniFileName(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, szDir, szFName, szExt);
	if (er != 0) {
		return -1;
	}
	er = _tmakepath_s(g.szIniFile, szDrive, szDir, szFName, _T("ini"));
	if (er != 0) {
		return -1;
	}
	return 0;
}
 
//------------------------------------------------------------------------------
void WriteIniFileInt(LPCTSTR pszSect, LPCTSTR pszKey, int nVal)
{
	TCHAR szBuf[16];
 
	_stprintf_s(szBuf, _T("%d"), nVal);
	WritePrivateProfileString(pszSect, pszKey, szBuf, g.szIniFile);
}
 
//------------------------------------------------------------------------------
int OpenMemMapFile(HWND hWnd)
{
	g.hFile = CreateFile(g.szPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (g.hFile == INVALID_HANDLE_VALUE) {
		MessageBox(hWnd, _T("CreateFileに失敗しました"), NULL, MB_OK);
		return -1;
	}
	g.hMap = CreateFileMapping(g.hFile, NULL, PAGE_READONLY, 0, 0, NULL);
	if (g.hMap == NULL) {
		MessageBox(hWnd, _T("CreateFileMappingに失敗しました"), NULL, MB_OK);
		return -1;
	}
	g.pBaseAddr = (LPBYTE)MapViewOfFile(g.hMap, FILE_MAP_READ, 0, 0, 0);
	if (g.pBaseAddr == NULL) {
		MessageBox(hWnd, _T("MapViewOfFileに失敗しました"), NULL, MB_OK);
		return -1;
	}
	g.dwFileSize = GetFileSize(g.hFile, NULL);	// GetFileSizeEx
	if (g.dwFileSize == INVALID_FILE_SIZE) {
		g.dwFileSize = 0;	// INVALID_FILE_SIZEを取り扱うのは好ましくない
		MessageBox(hWnd, _T("GetFileSizeに失敗しました"), NULL, MB_OK);
		return -1;
	}
	return 0;
}
 
//------------------------------------------------------------------------------
void CloseMemMapFile(void)
{
	BOOL br;
 
	g.dwFileSize = 0;
	if (g.pBaseAddr) {
		br = UnmapViewOfFile(g.pBaseAddr);
		g.pBaseAddr = NULL;
	}
	if (g.hMap) {
		br = CloseHandle(g.hMap);
		g.hMap = NULL;
	}
	if (g.hFile) {
		br = CloseHandle(g.hFile);
		g.hFile = NULL;
	}
}
 
//------------------------------------------------------------------------------
DWORD CheckFile(void)
{
	DWORD dwPos;
	LPBYTE pby;
	BYTE by;
	int nByte;
 
	for (dwPos = 0; dwPos < g.dwFileSize; dwPos += nByte) {
		pby = g.pBaseAddr + dwPos;
		by = *pby;
		// マルチバイト文字判定
		if (_ismbblead(by)) {
			nByte = 2;
		} else {
			nByte = 1;
			if (!IsPrint(by)) {
				switch (by) {
				case _T('\r'):
					nByte = 2;
					continue;
				case _T('\t'):
					continue;
				}
				break;
			}
		}
	}
	return dwPos;
}
 
//------------------------------------------------------------------------------
void DebugCodeTable(int nType)
{
	LPCTSTR pszType[] = {_T("_ismbblead"), _T("_ismbbtrail"), _T("IsPrint")};
	LPCTSTR pszLine = _T("   0 1 2 3 4 5 6 7 8 9 A B C D E F\n");
	TCHAR szLine[80+1];
	TCHAR szBuf[2+1];
	int nHigh;
	int nLow;
	int nChar = 0;
	int nr;
 
	_stprintf_s(szLine, _T("[%s]\n"), pszType[nType]);
	OutputDebugString(szLine);
	OutputDebugString(pszLine);
 
	for (nHigh = 0; nHigh < 16; nHigh++) {
		_tcscpy_s(szLine, pszLine);
		_stprintf_s(szBuf, _T("%X_"), nHigh);
		memcpy_s(szLine, _countof(szLine), szBuf, 2);
 
		for (nLow = 0; nLow < 16; nLow++) {
			switch (nType) {
			case 0: nr = _ismbblead(nChar); break;
			case 1: nr = _ismbbtrail(nChar); break;
			case 2: nr = IsPrint(nChar); break;
			}
			szLine[3 + nLow * 2] = nr ? _T('o') : _T('.');
			nChar++;
		}
		OutputDebugString(szLine);
	}
}
 
//==============================================================================
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 IDOK:
			OnOK(hDlg);
			break;
		case IDCANCEL:
			PostMessage(hDlg, WM_CLOSE, 0, 0);
			break;
		}
		break;
	case WM_DROPFILES:
		OnDropFiles(hDlg, wParam);
		DragFinish((HDROP)wParam);
		break;
	case WM_INITDIALOG:
		OnInitDialog(hDlg);
		iRet = TRUE;	// SetFocusでフォーカスを設定した場合はFALSE
		break;
	case WM_CLOSE:
		EndDialog(hDlg, IDOK);
		break;
	case WM_DESTROY:
		OnDestroy(hDlg);
		break;
	default:
		iRet = FALSE;	// メッセージを処理しなかった
	}
	return iRet;
}
 
//------------------------------------------------------------------------------
void OnOK(HWND hDlg)
{
	PRINTDLGEX pd;
	HRESULT hr;
	LPDEVMODE pdm;
	LPDEVNAMES pdn;
	short sOri;
	int nr;
	BOOL br;
 
	// ダイアログデータの取得
	if (GetDlgData(hDlg)) {
		return;
	}
 
	// ファイルのオープン
	if (g.szPath[0] == _T('\0')) {
		MessageBox(hDlg, _T("ファイルを指定してください"), NULL, MB_OK);
		return;
	}
	if (OpenMemMapFile(hDlg)) {
		goto Exit;
	}
	g.dwPos = 0;
 
	// 文字分類
	DebugCodeTable(0);
	DebugCodeTable(1);
	DebugCodeTable(2);
 
	// ファイルの確認
	if (CheckFile() != g.dwFileSize) {
		nr = MessageBox(hDlg, _T("印刷できないファイルのようです"), NULL, MB_OKCANCEL);
		if (nr == IDCANCEL) goto Exit;
	}
 
	// 印刷ダイアログ
	ZeroMemory(&pd, sizeof pd);
	pd.lStructSize	= sizeof pd;
	pd.hwndOwner	= hDlg;
	pd.hDevMode	= g.hDevMode;
	pd.hDevNames	= g.hDevNames;
	pd.Flags	= PD_NOPAGENUMS;
	pd.nStartPage	= START_PAGE_GENERAL;
	hr = PrintDlgEx(&pd);
	if (FAILED(hr)) {
		goto Exit;
	}
	g.hDevMode = pd.hDevMode;
	g.hDevNames = pd.hDevNames;
	if (pd.dwResultAction != PD_RESULT_PRINT) {
		goto Exit;
	}
 
	// 帳票形式
	switch (g.nPrintStyle) {
	case 0:	// 横置き 2面
		sOri			= DMORIENT_LANDSCAPE;
		g.nPageNum		=   2;
		g.rcMargin.left		= 100;
		g.rcMargin.top		= 200;
		g.rcMargin.right	= 100;
		g.rcMargin.bottom	=  50;
		g.nMarginWidth		= 100;
		g.nLineNum		=  66;
		g.nColNum		=  80;
		break;
	case 1:	// 縦置き 1面
		sOri			= DMORIENT_PORTRAIT;
		g.nPageNum		=   1;
		g.rcMargin.left		= 200;
		g.rcMargin.top		= 100;
		g.rcMargin.right	= 150;
		g.rcMargin.bottom	= 100;
		g.nMarginWidth		=   0;
		g.nLineNum		= 100;
		g.nColNum		= 100;
		break;
	}
 
	// プリンタ準備
	pdm = (LPDEVMODE)GlobalLock(g.hDevMode);
	pdn = (LPDEVNAMES)GlobalLock(g.hDevNames);
	pdm->dmOrientation = sOri;
	g.hdc = CreateDC(NULL, (LPCTSTR)pdn + pdn->wDeviceOffset, NULL, pdm);
	br = GlobalUnlock(g.hDevNames);
	br = GlobalUnlock(g.hDevMode);
 
	SetBkMode(g.hdc, TRANSPARENT);
 
	// 印刷処理
	PrintProc();
Exit:
	br = DeleteDC(g.hdc);
	g.hdc = NULL;
	CloseMemMapFile();
}
 
//------------------------------------------------------------------------------
int GetDlgData(HWND hDlg)
{
	int nPrintStyle;
	int nTabStop;
	int n;
	LRESULT lr;
	BOOL br;
 
	for (n = 0; n < 2; n++) {
		lr = Button_GetCheck(GetDlgItem(hDlg, IDC_RADIO1 + n));
		if (lr == BST_CHECKED) {
			nPrintStyle = n;
			break;
		}
	}
	nTabStop = GetDlgItemInt(hDlg, IDC_TABSTOP, &br, FALSE);
	if (br == FALSE || nTabStop < 1 || 8 < nTabStop) {
		MessageBox(hDlg, _T("タブのサイズは1~8です"), NULL, MB_OK);
		return -1;
	}
	g.nPrintStyle = nPrintStyle;
	g.nTabStop = nTabStop;
	return 0;
}
 
//------------------------------------------------------------------------------
void OnDropFiles(HWND hDlg, WPARAM wParam)
{
	HDROP hDrop = (HDROP)wParam;
	TCHAR szDrive	[_MAX_DRIVE];
	TCHAR szDir	[_MAX_DIR];
	TCHAR szFName	[_MAX_FNAME];
	TCHAR szExt	[_MAX_EXT];
	TCHAR szDir2	[_MAX_PATH];
	UINT ur;
	errno_t er;
 
	ur = DragQueryFile(hDrop, 0, g.szPath, _countof(g.szPath));
 
	er = _tsplitpath_s(g.szPath, szDrive, szDir, szFName, szExt);
	_tmakepath_s(szDir2, szDrive, szDir, NULL, NULL);
	_tmakepath_s(g.szFile, NULL, NULL, szFName, szExt);
 
	SetWindowText(g.hWndDir, szDir2);
	SetWindowText(g.hWndFile, g.szFile);
}
 
//------------------------------------------------------------------------------
void OnInitDialog(HWND hDlg)
{
	int nX;
	int nY;
 
	g.hWndDir	= GetDlgItem(hDlg, IDC_DIR);
	g.hWndFile	= GetDlgItem(hDlg, IDC_FILE);
 
	nX = GetPrivateProfileInt(SECT_GEN, _T("X"), 0, g.szIniFile);
	nY = GetPrivateProfileInt(SECT_GEN, _T("Y"), 0, g.szIniFile);
	SetWindowPos(hDlg, HWND_TOP, nX, nY, 0, 0, SWP_NOSIZE);
 
	g.nPrintStyle = GetPrivateProfileInt(SECT_GEN, _T("PrintStyle"), 0, g.szIniFile);
	g.nTabStop = GetPrivateProfileInt(SECT_GEN, _T("TabStop"), 8, g.szIniFile);
 
	Button_SetCheck(GetDlgItem(hDlg, IDC_RADIO1 + g.nPrintStyle), BST_CHECKED);
	SetDlgItemInt(hDlg, IDC_TABSTOP, g.nTabStop, FALSE);
}
 
//------------------------------------------------------------------------------
void OnDestroy(HWND hDlg)
{
	RECT rc;
	HGLOBAL hr;
 
	hr = GlobalFree(g.hDevMode);
	hr = GlobalFree(g.hDevNames);
 
	if (IsIconic(hDlg) == FALSE) {
		GetWindowRect(hDlg, &rc);
		WriteIniFileInt(SECT_GEN, _TEXT("X"), rc.left);
		WriteIniFileInt(SECT_GEN, _TEXT("Y"), rc.top);
	}
	WriteIniFileInt(SECT_GEN, _TEXT("PrintStyle"), g.nPrintStyle);
	WriteIniFileInt(SECT_GEN, _TEXT("TabStop"), g.nTabStop);
}
 
//==============================================================================
// 印刷処理
int PrintProc(void)
{
	LOGFONT lf;
	DOCINFO di;
	time_t tmNow;
	struct tm tm;
	int n;
	int nr;
	BOOL br;
 
	// 印刷準備
	PreparePrint();
 
	// フォント
	ZeroMemory(&lf, sizeof lf);
	lf.lfCharSet	= DEFAULT_CHARSET;
	lf.lfHeight	= -g.nLineHeight;
	_tcscpy_s(lf.lfFaceName, _T("Courier New"));
	g.hFont[0] = CreateFontIndirect(&lf);
 
	_tcscpy_s(lf.lfFaceName, _T("MS 明朝"));
	g.hFont[1] = CreateFontIndirect(&lf);
 
	lf.lfHeight	= lmtopx(40, g.nDpiY);
	_tcscpy_s(lf.lfFaceName, _T("MS Pゴシック"));
	g.hFont[2] = CreateFontIndirect(&lf);
 
	lf.lfHeight	= lmtopx(30, g.nDpiY);
	_tcscpy_s(lf.lfFaceName, _T("MS Pゴシック"));
	g.hFont[3] = CreateFontIndirect(&lf);
 
	// 初期化
	g.nPhyPageNo	= 0;
	g.nLineNo	= 0;
	g.bLineCont	= FALSE;
	time(&tmNow);
	localtime_s(&tm, &tmNow);
	_stprintf_s(g.szTime, _T("%04d/%02d/%02d %02d:%02d:%02d"),
		tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
		tm.tm_hour, tm.tm_min, tm.tm_sec);
 
	// 印刷開始
	ZeroMemory(&di, sizeof di);
	di.cbSize	= sizeof di;
	di.lpszDocName	= _T("a2pr");	// 最大32文字か
	nr = StartDoc(g.hdc, &di);
 
	// ページ処理
	while (PageProc() == 0) {
		g.nPhyPageNo++;
	}
 
	// 印刷終了
	nr = EndDoc(g.hdc);
 
	// 後処理
	for (n = 0; n < 4; n++) {
		br = DeleteObject(g.hFont[n]);
	}
	return 0;
}
 
//------------------------------------------------------------------------------
// 印刷準備・座標計算
int PreparePrint(void)
{
	RECT rcMarginDev;	// デバイス余白
	RECT rcMargin;		// 物理ページ余白
	int nFootHeight;	// 物理ページフッタの高さ
	int nTitleHeight;	// 見出しの高さ
 
	// プリンタ能力の取得
	g.nHorzRes		= GetDeviceCaps(g.hdc, HORZRES);
	g.nVertRes		= GetDeviceCaps(g.hdc, VERTRES);
	g.nPhysicalWidth	= GetDeviceCaps(g.hdc, PHYSICALWIDTH);
	g.nPhysicalHeight	= GetDeviceCaps(g.hdc, PHYSICALHEIGHT);
	g.nPhysicalOffsetX	= GetDeviceCaps(g.hdc, PHYSICALOFFSETX);
	g.nPhysicalOffsetY	= GetDeviceCaps(g.hdc, PHYSICALOFFSETY);
	g.nDpiX			= GetDeviceCaps(g.hdc, LOGPIXELSX);
	g.nDpiY			= GetDeviceCaps(g.hdc, LOGPIXELSY);
 
	// デバイス余白
	rcMarginDev.left	= g.nPhysicalOffsetX;
	rcMarginDev.top		= g.nPhysicalOffsetY;
	rcMarginDev.right	= g.nPhysicalWidth - g.nHorzRes - g.nPhysicalOffsetX;
	rcMarginDev.bottom	= g.nPhysicalHeight - g.nVertRes - g.nPhysicalOffsetY;
 
	// 物理ページ余白
	rcMargin.left	= max(lmtopx(g.rcMargin.left,	g.nDpiX), rcMarginDev.left);
	rcMargin.top	= max(lmtopx(g.rcMargin.top,	g.nDpiY), rcMarginDev.top);
	rcMargin.right	= max(lmtopx(g.rcMargin.right,	g.nDpiX), rcMarginDev.right);
	rcMargin.bottom	= max(lmtopx(g.rcMargin.bottom,	g.nDpiY), rcMarginDev.bottom);
 
	// 印刷範囲
	g.rcPrint.left		= rcMargin.left;
	g.rcPrint.top		= rcMargin.top;
	g.rcPrint.right		= g.nPhysicalWidth - rcMargin.right;
	g.rcPrint.bottom	= g.nPhysicalHeight - rcMargin.bottom;
	OffsetRect(&g.rcPrint, -g.nPhysicalOffsetX, -g.nPhysicalOffsetY);
 
	// 物理ページフッタ
	nFootHeight	= lmtopx((g.nPageNum == 1) ? 0 : 50, g.nDpiY);
 
	// 論理ページ
	g.nLogPageWidth	= (WIDTH(g.rcPrint) - lmtopx(g.nMarginWidth, g.nDpiX)) / g.nPageNum;
	g.nLogPageHeight	= HEIGHT(g.rcPrint) - nFootHeight;
	CopyRect(&g.rcLogPage[0], &g.rcPrint);
	g.rcLogPage[0].bottom	= g.rcPrint.bottom - nFootHeight;
	if (g.nPageNum == 2) {
		CopyRect(&g.rcLogPage[1], &g.rcLogPage[0]);
		g.rcLogPage[0].right	= g.rcPrint.left + g.nLogPageWidth;
		g.rcLogPage[1].left	= g.rcPrint.right - g.nLogPageWidth;
	}
 
	// 論理ページ見出し
	nTitleHeight	= lmtopx(60, g.nDpiY);
 
	// 本文
	g.nBodyTop	= g.rcLogPage[0].top + nTitleHeight;
	g.nBodyHeight	= g.nLogPageHeight - nTitleHeight;
 
	// 行
	g.nLineHeight	= g.nBodyHeight / (g.nLineNum + 1);
 
	return 0;
}
 
//------------------------------------------------------------------------------
// ページ処理
// 戻り値:0=継続 1=終了
int PageProc(void)
{
	LOGBRUSH lb;
	HPEN hPen;
	HPEN hPen2;
	HGDIOBJ hPenOld;
	HGDIOBJ hFontOld;
	TCHAR szBuf[5+1];	// "P.999"
	RECT rc;
	UINT uFormat = DT_SINGLELINE | DT_VCENTER;
	int nPage;
	int nLine;
	int nr;
	BOOL br;
 
	// ペン
	hPen = CreatePen(PS_INSIDEFRAME, lmtopx(3, g.nDpiY), RGB(0x00,0x00,0x00));
	lb.lbStyle	= BS_SOLID;
	lb.lbColor	= RGB(0x00,0x00,0x00);
	hPen2 = ExtCreatePen(PS_GEOMETRIC | PS_SOLID | PS_ENDCAP_FLAT | PS_JOIN_BEVEL,
		lmtopx(3, g.nDpiY), &lb, 0, NULL);
 
	// ページ開始
	nr = StartPage(g.hdc);
 
	// 物理ページ番号
	hFontOld = SelectObject(g.hdc, g.hFont[2]);
	if (g.nPageNum != 1) {
		_stprintf_s(szBuf, _T("P.%d"), g.nPhyPageNo + 1);
		CopyRect(&rc, &g.rcPrint);
		rc.top = g.rcLogPage[0].bottom;
		DrawText(g.hdc, szBuf, -1, &rc, uFormat | DT_RIGHT);
	}
 
	for (nPage = 0; nPage < g.nPageNum; nPage++) {
		// 枠
		hPenOld = SelectObject(g.hdc, hPen);
		br = Rectangle(g.hdc, g.rcLogPage[nPage].left, g.rcLogPage[nPage].top,
			g.rcLogPage[nPage].right, g.rcLogPage[nPage].bottom);
		// 見出し線
		SelectObject(g.hdc, hPen2);
		BeginPath(g.hdc);
		MoveToEx(g.hdc, g.rcLogPage[nPage].left, g.nBodyTop, NULL);
		LineTo(g.hdc, g.rcLogPage[nPage].right, g.nBodyTop);
		EndPath(g.hdc);
		StrokePath(g.hdc);
		// 見出し
		rc.left		= g.rcLogPage[nPage].left + lmtopx(50, g.nDpiX);
		rc.top		= g.rcLogPage[nPage].top;
		rc.right	= g.rcLogPage[nPage].right - lmtopx(50, g.nDpiX);
		rc.bottom	= g.nBodyTop;
		SelectObject(g.hdc, g.hFont[3]);
		DrawText(g.hdc, g.szTime, -1, &rc, uFormat | DT_LEFT);
		SelectObject(g.hdc, g.hFont[2]);
		DrawText(g.hdc, g.szFile, -1, &rc, uFormat | DT_CENTER);
		_stprintf_s(szBuf, _T("P.%d"), g.nPhyPageNo * g.nPageNum + 1 + nPage);
		DrawText(g.hdc, szBuf, -1, &rc, uFormat | DT_RIGHT);
 
		for (nLine = 0; nLine < g.nLineNum; nLine++) {
			// 行処理
			nr = LineProc(nPage, nLine);
			if (nr) {
				goto Exit;
			}
		}
	}
Exit:
	SelectObject(g.hdc, hPenOld);
	SelectObject(g.hdc, hFontOld);
	EndPage(g.hdc);
	br = DeleteObject(hPen2);
	br = DeleteObject(hPen);
	return nr;
}
 
//------------------------------------------------------------------------------
// 行処理
// 戻り値:0=継続 1=終了
int LineProc(int nPage, int nLine)
{
	TCHAR szLine[100+7];	// 行バッファ
	TCHAR szBuf[100+2];	// バッファ
	LPBYTE pby;
	BYTE by;
	BOOL bLineCont = FALSE;	// 行継続フラグ
	int nCol;
	int nByte;
	int nr = 0;
 
	for (nCol = 0; ; ) {
		// EOF
		if (g.dwFileSize <= g.dwPos) {
			if (nCol == 0) return 1;
			break;
		}
		pby = g.pBaseAddr + g.dwPos;
		by = *pby;
		// 改行
		if (by == _T('\r')) {
			g.dwPos += 2;
			break;
		}
		// 1行の列数
		if (g.nColNum <= nCol) {
			bLineCont = TRUE;
			break;
		}
		// マルチバイト文字判定
		nByte = _ismbblead(by) ? 2 : 1;
		// Tab
		if (by == _T('\t')) {
			do {
				szBuf[nCol++] = _T(' ');
			} while ((nCol % g.nTabStop) && nCol < g.nColNum);
		} else {
			memcpy(szBuf + nCol, pby, nByte);
			nCol += nByte;
		}
		g.dwPos += nByte;
	}
	szBuf[nCol] = _T('\0');
	// 行継続
	if (g.bLineCont) {
		_stprintf_s(szLine, _T("     %s"), szBuf);
	} else {
		_stprintf_s(szLine, _T("%4d %s"), ++g.nLineNo, szBuf);
	}
	g.bLineCont = bLineCont;
	// 行印刷
	PrintLine(szLine, 5 + nCol, nPage, nLine);
	// EOF
	if (g.dwFileSize <= g.dwPos) {
		nr = 1;
	}
	return nr;
}
 
//------------------------------------------------------------------------------
// 行印刷
// 全角文字が左寄りになるのでDrawText,nColWidthを検討
int PrintLine(LPCTSTR pszLine, int nLen, int nPage, int nLine)
{
	LPCTSTR psz;
	int nFontCurr;	// カレントフォント
	int nFont;
	int nCol;
	int nByte;
	int nX;
	int nY = g.nBodyTop + g.nLineHeight / 2 + (nLine * g.nBodyHeight / (g.nLineNum + 1));
 
	nFontCurr = 0;
	SelectObject(g.hdc, g.hFont[nFontCurr]);
 
	for (nCol = 0; nCol < nLen; nCol += nByte) {
		psz = pszLine + nCol;
		// マルチバイト文字判定
		nByte = _ismbblead(psz[0]) ? 2 : 1;	// 簡易
		// フォント選択
		nFont = __isascii(psz[0]) ? 0 : 1;
		if (nFont != nFontCurr) {
			SelectObject(g.hdc, g.hFont[nFont]);
			nFontCurr = nFont;
		}
		nX = g.rcLogPage[nPage].left + (1 + nCol) * g.nLogPageWidth / (g.nColNum + 7);
		TextOut(g.hdc, nX, nY, psz, nByte);
	}
	return 0;
}
 

resource.h
#define IDD_DIALOG	100
 
#define IDC_STATIC	-1
#define IDC_DIR		1000
#define IDC_FILE	1001
#define IDC_TABSTOP	1002
#define IDC_RADIO1	1011
#define IDC_RADIO2	1012
 

a2pr.rc
// resource script
#include <windows.h>
#include "resource.h"
 
IDD_DIALOG DIALOGEX 0, 0, 366, 200
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW | WS_EX_ACCEPTFILES
CAPTION "a2pr"
FONT 9, "MS Pゴシック"
BEGIN
	GROUPBOX	"印刷するファイル",IDC_STATIC,8,8,264,64
	RTEXT		"ディレクトリ:",IDC_STATIC,20,20,36,12
	EDITTEXT	IDC_DIR,60,20,204,12,ES_AUTOHSCROLL
	RTEXT		"ファイル:",IDC_STATIC,20,36,36,12
	EDITTEXT	IDC_FILE,60,36,204,12,ES_AUTOHSCROLL
 
	CONTROL		"横置き 2面",IDC_RADIO1,"button",BS_AUTORADIOBUTTON | WS_GROUP,
			280,24,64,12
	CONTROL		"縦置き 1面",IDC_RADIO2,"button",BS_AUTORADIOBUTTON,
			280,36,64,12
	LTEXT		"帳票形式:",IDC_STATIC,280,12,44,12,WS_GROUP
 
	RTEXT		"タブのサイズ:",IDC_STATIC,280,96,48,12,0
	EDITTEXT	IDC_TABSTOP,332,96,24,12,ES_RIGHT
 
	PUSHBUTTON	"印刷(&P)",IDOK,244,176,52,16
	PUSHBUTTON	"終了(&X)",IDCANCEL,304,176,52,16
END
 
最終更新:2012年10月11日 09:52