// マルチバイト文字セット
#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 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