「C言語/C++/a2pr」の編集履歴(バックアップ)一覧はこちら

C言語/C++/a2pr - (2012/10/11 (木) 09:52:48) の1つ前との変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|a2pr| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|マルチバイト| 参考 -[[フォント設定ダイアログを作る>http://www.geocities.jp/midorinopage/Beginner/beginner29.html]] a2pr.cpp #highlight(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); // 物理ページ番号 if (g.nPageNum != 1) { _stprintf_s(szBuf, _T("P.%d"), g.nPhyPageNo + 1); CopyRect(&rc, &g.rcPrint); rc.top = g.rcLogPage[0].bottom; hFontOld = SelectObject(g.hdc, g.hFont[2]); 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 #highlight(c){{ #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 #highlight(c){{ // 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 }}
|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|a2pr| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|マルチバイト| 参考 -[[フォント設定ダイアログを作る>http://www.geocities.jp/midorinopage/Beginner/beginner29.html]] a2pr.cpp #highlight(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 #highlight(c){{ #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 #highlight(c){{ // 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 }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: