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

C言語/C++/PrnAddr - (2012/10/31 (水) 18:06:04) の1つ前との変更点

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

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

|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|PrnAddr| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|マルチバイト| 注意 元のファイルが失われる恐れがあるので、必要なファイルは必ずバックアップを取ってください。 PrnAddr.cpp #highlight(cpp){{ // マルチバイト #include <Windows.h> #include <CommCtrl.h> #include <tchar.h> #include <sqlext.h> #include <stdio.h> #include "resource.h" #define WIDTH(rect) ((rect).right - (rect).left) #define HEIGHT(rect) ((rect).bottom - (rect).top) #define LTRB(rect) (rect).left, (rect).top, (rect).right, (rect).bottom #define DRIVER _T("Microsoft Text Driver (*.txt; *.csv)") #define APPNAME _T("PrnAddr") // 関数プロトタイプ宣言 BOOL SplitPath(LPCTSTR pszPath); void Trace(LPCTSTR format, ...); void DigitOnly(LPTSTR pszStr); INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnInitDialog(HWND hDlg); void OnDropFiles(HWND hDlg, WPARAM wParam); BOOL OnClose(HWND hDlg); BOOL CheckRecMod(HWND hWnd); void OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam); void OnUpdate(void); void OnDrawItem(WPARAM wParam, LPARAM lParam); void OnDraw(HDC hdc, int nRec, BOOL bGuide); void DrawField(HDC hdc, PRECT prc, int nRow, int nCol, BOOL bGuide, LPCTSTR pszSuffix); void OnPrint(HWND hDlg, int nMode); void CopyRecord(void); void ShowSubDlg(void); int lmpx(int lm); int lmpy(int lm); int lmpw(int lm); int lmph(int lm); INT_PTR CALLBACK SubDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnSubInitDialog(HWND hDlg); void OnCheck(HWND hDlg); void OnSave(HWND hDlg); void OnSubPrint(HWND hDlg); void InitAddress(HWND hWnd); void LoadTable(HWND hWnd); BOOL SaveTable(HWND hWnd); BOOL CreateCsvFile(HWND hWnd, LPCTSTR pszPath); // 外部変数構造体 static struct { HINSTANCE hInstance; HWND hMainDlg; // メインダイアログ HWND hSubDlg; // 住所録ダイアログ HWND hRec; // レコードエディットハンドル HWND hSpin; // スピンコントロールハンドル HWND hUpdate; // 更新ボタンハンドル HWND hList; // リストビューハンドル HGLOBAL hDevMode; // デバイスモード構造体ハンドル HGLOBAL hDevNames; // デバイス名構造体ハンドル SQLHENV henv; // 環境ハンドル TCHAR szDbq[MAX_PATH]; // データベースディレクトリ TCHAR szTable[MAX_PATH];// CSVファイル int nRecNum; // レコード数 int nRec; // 対象レコード BOOL bRecMod; // レコード変更フラグ BOOL bTableMod; // テーブル変更フラグ // デバイス能力 int nHorzRes; int nVertRes; int nPhysicalWidth; int nPhysicalHeight; int nPhysicalOffsetX; int nPhysicalOffsetY; int nLogPixelsX; int nLogPixelsY; } g; //============================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { g.hInstance = hInstance; // ODBC環境ハンドルの確保 SQLRETURN rc; // retcode rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &g.henv); rc = SQLSetEnvAttr(g.henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0); // コマンド引数の取得 LPWSTR pszCmdLine = GetCommandLineW(); int argc; LPWSTR *argv = CommandLineToArgvW(pszCmdLine, &argc); if (2 <= argc) { TCHAR szPath[MAX_PATH]; wcstombs_s(NULL, szPath, argv[1], _TRUNCATE); SplitPath(szPath); } LocalFree(argv); DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc); HGLOBAL hr; hr = GlobalFree(g.hDevMode); hr = GlobalFree(g.hDevNames); rc = SQLFreeHandle(SQL_HANDLE_ENV, g.henv); return 0; } //------------------------------------------------------------------------------ BOOL SplitPath(LPCTSTR pszPath) { TCHAR szDrive [_MAX_DRIVE]; TCHAR szDir [_MAX_DIR]; TCHAR szFName [_MAX_FNAME]; TCHAR szExt [_MAX_EXT]; _splitpath_s(pszPath, szDrive, szDir, szFName, szExt); _makepath_s(g.szDbq, szDrive, szDir, NULL, NULL); _makepath_s(g.szTable, NULL, NULL, szFName, szExt); return TRUE; } //------------------------------------------------------------------------------ void Trace(LPCTSTR format, ...) { va_list arg_ptr; TCHAR buffer[256]; int size; va_start(arg_ptr, format); size = _vsntprintf_s(buffer, _TRUNCATE, format, arg_ptr); va_end(arg_ptr); OutputDebugString(buffer); if (size < 0) { OutputDebugString(_T("...\n")); } } //------------------------------------------------------------------------------ void DigitOnly(LPTSTR pszStr) { LPTSTR psz; TCHAR c; for (psz = pszStr; c = *pszStr; pszStr++) { if (_istdigit(c)) { *psz++ = c; } } *psz = c; } //============================================================================== INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nRet = TRUE; // メッセージを処理した switch (uMsg) { case WM_COMMAND: OnCommand(hDlg, wParam, lParam); break; case WM_DRAWITEM: OnDrawItem(wParam, lParam); break; case WM_DROPFILES: OnDropFiles(hDlg, wParam); DragFinish((HDROP)wParam); break; case WM_INITDIALOG: OnInitDialog(hDlg); nRet = TRUE; // SetFocusでフォーカスを設定した場合はFALSE break; case WM_CLOSE: if (OnClose(hDlg)) { EndDialog(hDlg, 0); } break; default: nRet = FALSE; // メッセージを処理しなかった } return nRet; } //------------------------------------------------------------------------------ void OnInitDialog(HWND hDlg) { g.hMainDlg = hDlg; g.hRec = GetDlgItem(hDlg, IDC_RECORD); g.hSpin = GetDlgItem(hDlg, IDC_SPIN); g.hUpdate = GetDlgItem(hDlg, IDC_UPDATE); SendMessage(g.hSpin, UDM_SETBUDDY, (WPARAM)g.hRec, 0); g.hSubDlg = CreateDialog(g.hInstance, MAKEINTRESOURCE(IDD_SUB), hDlg, SubDlgProc); } //------------------------------------------------------------------------------ void OnDropFiles(HWND hDlg, WPARAM wParam) { HDROP hDrop = (HDROP)wParam; TCHAR szPath[MAX_PATH]; UINT ur = DragQueryFile(hDrop, 0, szPath, _countof(szPath)); SplitPath(szPath); ListView_DeleteAllItems(g.hList); InitAddress(hDlg); InvalidateRect(GetDlgItem(hDlg, IDC_PREVIEW), NULL, FALSE); } //------------------------------------------------------------------------------ BOOL OnClose(HWND hDlg) { BOOL bRet = TRUE; // レコード変更の確認 if (CheckRecMod(hDlg) == FALSE) return FALSE; // テーブル変更の確認 if (g.bTableMod == FALSE) return TRUE; int nr = MessageBox(hDlg, _T("住所録の内容は変更されています。\n\n保存しますか?"), APPNAME, MB_YESNOCANCEL | MB_ICONWARNING); switch (nr) { case IDYES: bRet = SaveTable(hDlg); break; case IDNO: break; default: bRet = FALSE; } return bRet; } //------------------------------------------------------------------------------ BOOL CheckRecMod(HWND hWnd) { if (g.bRecMod == FALSE) return TRUE; int nr = MessageBox(hWnd, _T("レコードの内容は変更されています。\n\n更新しますか?"), APPNAME, MB_YESNOCANCEL | MB_ICONWARNING); switch (nr) { case IDYES: OnUpdate(); break; case IDNO: break; default: return FALSE; } return TRUE; } //------------------------------------------------------------------------------ void OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) { WORD wNotifyCode = HIWORD(wParam); WORD wID = LOWORD(wParam); HWND hwndCtl = (HWND)lParam; switch (wID) { case IDC_ADDRESS: // 住所録 ShowSubDlg(); break; case IDC_PRINT: // 単票印刷 if (CheckRecMod(hDlg)) { OnPrint(hDlg, 0); } break; case IDC_UPDATE: // 更新 OnUpdate(); break; case IDCANCEL: // 終了 SendMessage(hDlg, WM_CLOSE, 0, 0); break; } if (wNotifyCode == EN_CHANGE) { if (hwndCtl == g.hRec) { int nRec = max(SendMessage(g.hSpin, UDM_GETPOS, 0, 0) - 1, 0); if (nRec == g.nRec) return; if (CheckRecMod(hDlg)) { g.nRec = nRec; CopyRecord(); InvalidateRect(GetDlgItem(hDlg, IDC_PREVIEW), NULL, FALSE); } else { SendMessage(g.hSpin, UDM_SETPOS, 0, g.nRec + 1); } } else { if (g.bRecMod == FALSE) { g.bRecMod = TRUE; EnableWindow(g.hUpdate, g.bRecMod); } } } } //------------------------------------------------------------------------------ void OnUpdate(void) { TCHAR szBuf[256]; if (g.nRecNum <= g.nRec) return; for (int n = 0; n < 6; n++) { GetDlgItemText(g.hMainDlg, IDC_FIELD0 + n, szBuf, _countof(szBuf)); ListView_SetItemText(g.hList, g.nRec, n, szBuf); } g.bTableMod = TRUE; g.bRecMod = FALSE; EnableWindow(g.hUpdate, g.bRecMod); InvalidateRect(GetDlgItem(g.hMainDlg, IDC_PREVIEW), NULL, FALSE); } //------------------------------------------------------------------------------ void OnDrawItem(WPARAM wParam, LPARAM lParam) { LPDRAWITEMSTRUCT pdi = (LPDRAWITEMSTRUCT)lParam; HDC hdc = pdi->hDC; // 背景塗り潰し RECT rc; GetClientRect(pdi->hwndItem, &rc); FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); Trace(_T("OnDrawItem(%u) %d, %d, %d, %d\n"), wParam, LTRB(rc)); // デバイス能力 g.nPhysicalWidth = WIDTH(rc); g.nPhysicalHeight = HEIGHT(rc); g.nPhysicalOffsetX = 0; g.nPhysicalOffsetY = 0; // 背景 SetRect(&rc, lmpx(0), lmpy(0), lmpx(300), lmpy(570)); FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE)); SetRect(&rc, lmpx(0), lmpy(1250), lmpx(1000), lmpy(1480)); FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE)); int nRec = SendMessage(g.hSpin, UDM_GETPOS, 0, 0); OnDraw(hdc, nRec - 1, TRUE); } //------------------------------------------------------------------------------ void OnDraw(HDC hdc, int nRec, BOOL bGuide) { TCHAR szBuf[256]; HFONT hFont[3]; RECT rc; SetBkMode(hdc, TRANSPARENT); // 背景透過モード Trace(_T("OnDraw(%d)\n"), nRec); // 補助線 HPEN hPen = CreatePen(PS_SOLID, 0, RGB(0xff,0x00,0x00)); HGDIOBJ hPenOld = SelectObject(hdc, hPen); // 郵便番号 LOGFONT lf; ZeroMemory(&lf, sizeof lf); lf.lfCharSet = DEFAULT_CHARSET; lf.lfHeight = -lmph(60); _tcscpy_s(lf.lfFaceName, _T("MS ゴシック")); hFont[0] = CreateFontIndirect(&lf); HGDIOBJ hFontOld = SelectObject(hdc, hFont[0]); SetRect(&rc, lmpx(440), lmpy(120), lmpx(930), lmpy(200)); if (bGuide) { Rectangle(hdc, LTRB(rc)); } if (nRec < g.nRecNum) { ListView_GetItemText(g.hList, nRec, 2, szBuf, _countof(szBuf)); DigitOnly(szBuf); // 440, 510, 580, 650, 720, 790, 860 for (size_t n = 0; n < _tcslen(szBuf); n++) { rc.right = rc.left + lmpw(70); DrawText(hdc, szBuf + n, 1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); rc.left = rc.right; } } // 住所 lf.lfEscapement = 2700; lf.lfOrientation= 2700; lf.lfHeight = -lmph(60); _tcscpy_s(lf.lfFaceName, _T("@MS 明朝")); hFont[1] = CreateFontIndirect(&lf); SelectObject(hdc, hFont[1]); SetRect(&rc, lmpx(850-70), lmpy(300), lmpx(850), lmpy(1230)); DrawField(hdc, &rc, nRec, 3, bGuide, NULL); SetRect(&rc, lmpx(780-70), lmpy(400), lmpx(780), lmpy(1230)); DrawField(hdc, &rc, nRec, 4, bGuide, NULL); SetRect(&rc, lmpx(710-70), lmpy(400), lmpx(710), lmpy(1230)); DrawField(hdc, &rc, nRec, 5, bGuide, NULL); // 氏名・連名 lf.lfHeight = -lmph(90); hFont[2] = CreateFontIndirect(&lf); SelectObject(hdc, hFont[2]); SetRect(&rc, lmpx(520-100), lmpy(400), lmpx(520), lmpy(1230)); DrawField(hdc, &rc, nRec, 0, bGuide, _T("様")); SetRect(&rc, lmpx(420-100), lmpy(400), lmpx(420), lmpy(1230)); DrawField(hdc, &rc, nRec, 1, bGuide, _T("様")); // 終了処理 SelectObject(hdc, hFontOld); for (int n = 0; n < _countof(hFont); n++) { DeleteObject(hFont[n]); } SelectObject(hdc, hPenOld); DeleteObject(hPen); } //------------------------------------------------------------------------------ void DrawField(HDC hdc, PRECT prc, int nRow, int nCol, BOOL bGuide, LPCTSTR pszSuffix) { TCHAR szText[64]; if (bGuide) { Rectangle(hdc, LTRB(*prc)); } if (g.nRecNum <= nRow) return; ListView_GetItemText(g.hList, nRow, nCol, szText, _countof(szText)); if (szText[0]) { if (pszSuffix) { _tcscat_s(szText, pszSuffix); } TextOut(hdc, prc->right, prc->top, szText, _tcslen(szText)); } } //------------------------------------------------------------------------------ void OnPrint(HWND hDlg, int nMode) { PRINTDLGEX pd; LPDEVMODE pdm; LPDEVNAMES pdn; HRESULT hr; BOOL br; HDC hdc = NULL; // 印刷ダイアログ 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; } // プリンタ準備 pdm = (LPDEVMODE)GlobalLock(g.hDevMode); pdn = (LPDEVNAMES)GlobalLock(g.hDevNames); pdm->dmOrientation = DMORIENT_PORTRAIT; hdc = CreateDC(NULL, (LPCTSTR)pdn + pdn->wDeviceOffset, NULL, pdm); br = GlobalUnlock(g.hDevNames); br = GlobalUnlock(g.hDevMode); // デバイス能力の取得 g.nHorzRes = GetDeviceCaps(hdc, HORZRES); g.nVertRes = GetDeviceCaps(hdc, VERTRES); g.nPhysicalWidth = GetDeviceCaps(hdc, PHYSICALWIDTH); g.nPhysicalHeight = GetDeviceCaps(hdc, PHYSICALHEIGHT); g.nPhysicalOffsetX = GetDeviceCaps(hdc, PHYSICALOFFSETX); g.nPhysicalOffsetY = GetDeviceCaps(hdc, PHYSICALOFFSETY); g.nLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX); g.nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); // 用紙サイズを確認 SIZE size; size.cx = g.nPhysicalWidth * 254 / g.nLogPixelsX; size.cy = g.nPhysicalHeight * 254 / g.nLogPixelsY; Trace(_T("OnPrint %d %d\n"), size.cx, size.cy); if (100 < abs(size.cx - 1000) || 100 < abs(size.cy - 1480)) { MessageBox(hDlg, _T("用紙サイズを確認してください。"), NULL, MB_OK); goto Exit; } // 印刷開始 DOCINFO di; ZeroMemory(&di, sizeof di); di.cbSize = sizeof di; di.lpszDocName = APPNAME; int nr = StartDoc(hdc, &di); switch (nMode) { case 0: // 単票 nr = StartPage(hdc); int nRec; nRec = SendMessage(g.hSpin, UDM_GETPOS, 0, 0); OnDraw(hdc, nRec - 1, TRUE); nr = EndPage(hdc); break; case 1: // 連続 for (int n = 0; n < g.nRecNum; n++) { br = ListView_GetCheckState(g.hList, n); if (br) { nr = StartPage(hdc); OnDraw(hdc, n, TRUE); nr = EndPage(hdc); } } break; } // 印刷終了 nr = EndDoc(hdc); Exit: if (hdc) { DeleteDC(hdc); } } //------------------------------------------------------------------------------ void CopyRecord(void) { TCHAR szBuf[256]; Trace(_T("CopyRecord %d %d\n"), g.nRec, g.nRecNum); if (g.nRecNum <= g.nRec) return; for (int n = 0; n < 6; n++) { ListView_GetItemText(g.hList, g.nRec, n, szBuf, _countof(szBuf)); SetDlgItemText(g.hMainDlg, IDC_FIELD0 + n, szBuf); } g.bRecMod = FALSE; EnableWindow(g.hUpdate, g.bRecMod); } //------------------------------------------------------------------------------ void ShowSubDlg(void) { ShowWindow(g.hSubDlg, IsWindowVisible(g.hSubDlg) ? SW_HIDE : SW_SHOW); } //------------------------------------------------------------------------------ // 0.1mm単位をピクセルに変換 // LoMetric to Pixel X int lmpx(int lm) { return lmpw(lm) - g.nPhysicalOffsetX; } // LoMetric to Pixel Y int lmpy(int lm) { return lmph(lm) - g.nPhysicalOffsetY; } // LoMetric to Pixel Width int lmpw(int lm) { return lm * g.nPhysicalWidth / 1000; } // LoMetric to Pixel Height int lmph(int lm) { return lm * g.nPhysicalHeight / 1480; } //============================================================================== INT_PTR CALLBACK SubDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nRet = TRUE; // メッセージを処理した switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CHECK: // 全てチェック/解除 OnCheck(hDlg); break; case IDC_SAVE: // 保存 OnSave(hDlg); break; case IDC_PRINT: // 連続印刷 OnSubPrint(hDlg); break; case IDCANCEL: // 閉じる ShowSubDlg(); break; } break; case WM_INITDIALOG: OnSubInitDialog(hDlg); nRet = TRUE; // SetFocusでフォーカスを設定した場合はFALSE break; case WM_CLOSE: ShowSubDlg(); break; default: nRet = FALSE; // メッセージを処理しなかった } return nRet; } //------------------------------------------------------------------------------ void OnSubInitDialog(HWND hDlg) { RECT rc; GetClientRect(hDlg, &rc); Trace(_T("OnInitDialog %d, %d, %d, %d\n"), LTRB(rc)); // リストビュー拡張スタイル g.hList = GetDlgItem(hDlg, IDC_LIST); DWORD dwExStyle = ListView_GetExtendedListViewStyle(g.hList); dwExStyle |= LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES; ListView_SetExtendedListViewStyle(g.hList, dwExStyle); InitAddress(hDlg); } //------------------------------------------------------------------------------ void OnCheck(HWND hDlg) { UINT ur = IsDlgButtonChecked(hDlg, IDC_CHECK); BOOL bCheck = (ur == BST_CHECKED); for (int n = 0; n < g.nRecNum; n++) { ListView_SetCheckState(g.hList, n, bCheck); } } //------------------------------------------------------------------------------ void OnSave(HWND hDlg) { if (g.bTableMod == FALSE) return; int nr = MessageBox(hDlg, _T("住所録を保存しますか?"), APPNAME, MB_YESNO | MB_ICONQUESTION); if (nr == IDYES) { SaveTable(hDlg); } } //------------------------------------------------------------------------------ void OnSubPrint(HWND hDlg) { BOOL br = FALSE; for (int n = 0; n < g.nRecNum; n++) { br = ListView_GetCheckState(g.hList, n); if (br) break; } if (br == FALSE) { MessageBox(hDlg, _T("印刷するレコードにチェックを付けてください。"), APPNAME, MB_OK); return; } OnPrint(hDlg, 1); } //------------------------------------------------------------------------------ void InitAddress(HWND hWnd) { // テーブルの読み込み LoadTable(hWnd); g.nRecNum = ListView_GetItemCount(g.hList); g.nRec = 0; CopyRecord(); SendMessage(g.hSpin, UDM_SETRANGE32, 1, g.nRecNum); SendMessage(g.hSpin, UDM_SETPOS, 0, MAKELONG(1, 0)); } //------------------------------------------------------------------------------ void LoadTable(HWND hWnd) { TCHAR buf[256]; SQLHDBC hdbc; // 接続ハンドル SQLHSTMT hstmt; // 命令ハンドル SQLSMALLINT col; SQLSMALLINT n; SQLSMALLINT datatype; SQLLEN len; SQLRETURN rc; // retcode // データベースへの接続 _stprintf_s(buf, _T("driver={%s}; dbq=%s"), DRIVER, g.szDbq); rc = SQLAllocHandle(SQL_HANDLE_DBC, g.henv, &hdbc); rc = SQLDriverConnect(hdbc, NULL, (SQLTCHAR *)buf, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if (!SQL_SUCCEEDED(rc)) { goto Exit; } // 検索 _stprintf_s(buf, _T("select * from %s"), g.szTable); rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); rc = SQLExecDirect(hstmt, (SQLTCHAR *)buf, SQL_NTS); if (!SQL_SUCCEEDED(rc)) { goto Exit; } // 列情報 LV_COLUMN lvCol; lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvCol.fmt = LVCFMT_LEFT; lvCol.cx = 100; rc = SQLNumResultCols(hstmt, &col); for (n = 0; n < col; n++) { rc = SQLDescribeCol(hstmt, n+1, (SQLTCHAR *)buf, _countof(buf), NULL, &datatype, NULL, NULL, NULL); lvCol.pszText = buf; lvCol.iSubItem = n; ListView_InsertColumn(g.hList, n, &lvCol); // Text 12 SQL_VARCHAR Char // Byte -6 SQL_TINYINT } // 行情報 LV_ITEM lvItem; lvItem.mask = LVIF_TEXT; lvItem.iItem = 0; while (1) { rc = SQLFetch(hstmt); if (rc == SQL_NO_DATA) break; if (rc == SQL_ERROR) break; for (n = 0; n < col; n++) { SQLGetData(hstmt, n+1, SQL_C_TCHAR, buf, _countof(buf), &len); if (len == SQL_NULL_DATA) { buf[0] = _T('\0'); } lvItem.pszText = buf; lvItem.iSubItem = n; if (n == 0) { ListView_InsertItem(g.hList, &lvItem); } else { ListView_SetItem(g.hList, &lvItem); } } lvItem.iItem++; } SQLFreeHandle(SQL_HANDLE_STMT, hstmt); Exit: SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); } //------------------------------------------------------------------------------ BOOL SaveTable(HWND hWnd) { TCHAR szNew[MAX_PATH]; _stprintf_s(szNew, _T("%s%s_"), g.szDbq, g.szTable); if (CreateCsvFile(hWnd, szNew) == FALSE) { return FALSE; } // CSVファイルの削除とリネーム TCHAR szOld[MAX_PATH]; _stprintf_s(szOld, _T("%s%s"), g.szDbq, g.szTable); BOOL br; br = DeleteFile(szOld); br = MoveFile(szNew, szOld); if (br == FALSE) { MessageBox(hWnd, _T("CSVファイルのリネームに失敗しました。"), NULL, MB_OK); return FALSE; } g.bTableMod = FALSE; return TRUE; } //------------------------------------------------------------------------------ BOOL CreateCsvFile(HWND hWnd, LPCTSTR pszPath) { TCHAR szBuf[MAX_PATH]; int nColNum = 6; // ファイルのオープン FILE *pFile; errno_t er = _tfopen_s(&pFile, pszPath, _T("wt")); if (er) { MessageBox(hWnd, _T("ファイルのオープンに失敗しました。"), NULL, MB_OK); return FALSE; } // ヘッダ行 _stprintf_s(szBuf, _T("%s%s"), g.szDbq, _T("schema.ini")); DWORD dw = GetPrivateProfileString(g.szTable, _T("ColNameHeader"), NULL, szBuf, _countof(szBuf), szBuf); if (_tcsicmp(szBuf, _T("true")) == 0) { LVCOLUMN lvcol; lvcol.mask = LVCF_TEXT; lvcol.pszText = szBuf; lvcol.cchTextMax= _countof(szBuf); for (int nCol = 0; ; ) { ListView_GetColumn(g.hList, nCol, &lvcol); _ftprintf_s(pFile, _T("%s"), lvcol.pszText); if (nColNum <= ++nCol) { break; } _ftprintf_s(pFile, _T(",")); } _ftprintf_s(pFile, _T("\n")); } // 書き込み int nRowNum = ListView_GetItemCount(g.hList); for (int nRow = 0; nRow < nRowNum; nRow++) { for (int nCol = 0; ; ) { ListView_GetItemText(g.hList, nRow, nCol, szBuf, _countof(szBuf)); _ftprintf_s(pFile, _T("%s"), szBuf); if (nColNum <= ++nCol) { break; } _ftprintf_s(pFile, _T(",")); } _ftprintf_s(pFile, _T("\n")); } fclose(pFile); return TRUE; } }} resource.h #highlight(c){{ #define IDD_MAIN 100 #define IDD_SUB 101 #define IDC_STATIC -1 #define IDC_PREVIEW 1000 #define IDC_ADDRESS 1001 #define IDC_PRINT 1002 #define IDC_RECORD 1003 #define IDC_SPIN 1004 #define IDC_UPDATE 1005 #define IDC_FIELD0 1010 #define IDC_FIELD1 1011 #define IDC_FIELD2 1012 #define IDC_FIELD3 1013 #define IDC_FIELD4 1014 #define IDC_FIELD5 1015 #define IDC_LIST 1100 #define IDC_CHECK 1101 #define IDC_SAVE 1102 }} PrnAddr.rc #highlight(c){{ // resource script #include <windows.h> #include "resource.h" //------------------------------------------------------------------------------ IDD_MAIN DIALOGEX 100, 50, 400, 304 STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX EXSTYLE WS_EX_APPWINDOW | WS_EX_ACCEPTFILES CAPTION "PrnAddr" FONT 10, "MS ゴシック" BEGIN LTEXT "",IDC_PREVIEW,4,4,200,296,WS_BORDER | SS_OWNERDRAW LTEXT "氏名",IDC_STATIC,212,8,32,12 EDITTEXT IDC_FIELD0,248,8,144,12,ES_AUTOHSCROLL LTEXT "連名",IDC_STATIC,212,28,32,12 EDITTEXT IDC_FIELD1,248,28,144,12,ES_AUTOHSCROLL LTEXT "郵便番号",IDC_STATIC,212,48,32,12 EDITTEXT IDC_FIELD2,248,48,144,12,ES_AUTOHSCROLL LTEXT "住所1",IDC_STATIC,212,68,32,12 EDITTEXT IDC_FIELD3,248,68,144,12,ES_AUTOHSCROLL LTEXT "住所2",IDC_STATIC,212,88,32,12 EDITTEXT IDC_FIELD4,248,88,144,12,ES_AUTOHSCROLL LTEXT "住所3",IDC_STATIC,212,108,32,12 EDITTEXT IDC_FIELD5,248,108,144,12,ES_AUTOHSCROLL EDITTEXT IDC_RECORD,248,128,48,16 CONTROL "",IDC_SPIN,"msctls_updown32", UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_ALIGNRIGHT, 280,128,32,16 PUSHBUTTON "更新(&U)",IDC_UPDATE,336,128,56,24 PUSHBUTTON "住所録(&A)",IDC_ADDRESS,212,276,56,24 PUSHBUTTON "単票印刷(&P)",IDC_PRINT,276,276,56,24 PUSHBUTTON "終了(&X)",IDCANCEL,340,276,56,24 END //------------------------------------------------------------------------------ IDD_SUB DIALOG 0, 350, 384, 200 STYLE WS_POPUPWINDOW CAPTION "住所録" FONT 9, "MS Pゴシック" BEGIN CONTROL "",IDC_LIST,"SysListView32", WS_BORDER | WS_TABSTOP | LVS_REPORT,8,8,368,160 CONTROL "全てチェック/解除(&A)",IDC_CHECK,"button", BS_AUTOCHECKBOX | WS_TABSTOP,8,176,80,16 PUSHBUTTON "保存(&S)",IDC_SAVE,216,176,48,16 PUSHBUTTON "連続印刷(&P)",IDC_PRINT,272,176,48,16 PUSHBUTTON "閉じる(&X)",IDCANCEL,328,176,48,16 END }} schema.ini [address.csv] ColNameHeader=True CharacterSet=932 Format=CSVDelimited Col1=氏名 Char Col2=連名 Char Col3=郵便番号 Char Width 8 Col4=住所1 Char Col5=住所2 Char Col6=住所3 Char address.csv 氏名,連名,郵便番号,住所1,住所2,住所3 国会 議事堂,   花子 ,100-0014,東京都千代田区,永田町一丁目七番一号, 東京 タワー,,105-0011,東京都港区,芝公園四丁目二―八,
|開発環境|Microsoft Visual C++ 2010 Express (SP1)| |実行環境|Microsoft Windows XP Home Edition (SP3)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|PrnAddr| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト| |文字セット|マルチバイト| 注意 元のファイルが失われる恐れがあるので、必要なファイルは必ずバックアップを取ってください。 PrnAddr.cpp #highlight(cpp){{ // マルチバイト #include <Windows.h> #include <CommCtrl.h> #include <tchar.h> #include <sqlext.h> #include <stdio.h> #include "resource.h" #define WIDTH(rect) ((rect).right - (rect).left) #define HEIGHT(rect) ((rect).bottom - (rect).top) #define LTRB(rect) (rect).left, (rect).top, (rect).right, (rect).bottom #define DRIVER _T("Microsoft Text Driver (*.txt; *.csv)") #define APPNAME _T("PrnAddr") // 関数プロトタイプ宣言 BOOL SplitPath(LPCTSTR pszPath); void Trace(LPCTSTR format, ...); void DigitOnly(LPTSTR pszStr); INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnInitDialog(HWND hDlg); void OnDropFiles(HWND hDlg, WPARAM wParam); BOOL OnClose(HWND hDlg); BOOL CheckRecMod(HWND hWnd); void OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam); void OnUpdate(void); void OnDrawItem(WPARAM wParam, LPARAM lParam); void OnDraw(HDC hdc, int nRec, BOOL bGuide); void DrawField(HDC hdc, PRECT prc, int nRow, int nCol, BOOL bGuide, LPCTSTR pszSuffix); void OnPrint(HWND hDlg, int nMode); void CopyRecord(void); void ShowSubDlg(void); int lmpx(int lm); int lmpy(int lm); int lmpw(int lm); int lmph(int lm); INT_PTR CALLBACK SubDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); void OnCheck(HWND hDlg); void OnSave(HWND hDlg); void OnSubPrint(HWND hDlg); void OnSubInitDialog(HWND hDlg); void InitAddress(HWND hWnd); void LoadTable(HWND hWnd); BOOL SaveTable(HWND hWnd); BOOL CreateCsvFile(HWND hWnd, LPCTSTR pszPath); // 外部変数構造体 static struct { HINSTANCE hInstance; HWND hMainDlg; // メインダイアログ HWND hSubDlg; // 住所録ダイアログ HWND hRec; // レコードエディットハンドル HWND hSpin; // スピンコントロールハンドル HWND hUpdate; // 更新ボタンハンドル HWND hList; // リストビューハンドル HGLOBAL hDevMode; // デバイスモード構造体ハンドル HGLOBAL hDevNames; // デバイス名構造体ハンドル SQLHENV henv; // 環境ハンドル TCHAR szDbq[MAX_PATH]; // データベースディレクトリ TCHAR szTable[MAX_PATH];// CSVファイル int nRecNum; // レコード数 int nRec; // 対象レコード BOOL bRecMod; // レコード変更フラグ BOOL bTableMod; // テーブル変更フラグ // デバイス能力 int nHorzRes; int nVertRes; int nPhysicalWidth; int nPhysicalHeight; int nPhysicalOffsetX; int nPhysicalOffsetY; int nLogPixelsX; int nLogPixelsY; } g; //============================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { g.hInstance = hInstance; // ODBC環境ハンドルの確保 SQLRETURN rc; // retcode rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &g.henv); rc = SQLSetEnvAttr(g.henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0); // コマンド引数の取得 LPWSTR pszCmdLine = GetCommandLineW(); int argc; LPWSTR *argv = CommandLineToArgvW(pszCmdLine, &argc); if (2 <= argc) { TCHAR szPath[MAX_PATH]; wcstombs_s(NULL, szPath, argv[1], _TRUNCATE); SplitPath(szPath); } LocalFree(argv); DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc); HGLOBAL hr; hr = GlobalFree(g.hDevMode); hr = GlobalFree(g.hDevNames); rc = SQLFreeHandle(SQL_HANDLE_ENV, g.henv); return 0; } //------------------------------------------------------------------------------ BOOL SplitPath(LPCTSTR pszPath) { TCHAR szDrive [_MAX_DRIVE]; TCHAR szDir [_MAX_DIR]; TCHAR szFName [_MAX_FNAME]; TCHAR szExt [_MAX_EXT]; _splitpath_s(pszPath, szDrive, szDir, szFName, szExt); _makepath_s(g.szDbq, szDrive, szDir, NULL, NULL); _makepath_s(g.szTable, NULL, NULL, szFName, szExt); return TRUE; } //------------------------------------------------------------------------------ void Trace(LPCTSTR format, ...) { va_list arg_ptr; TCHAR buffer[256]; int size; va_start(arg_ptr, format); size = _vsntprintf_s(buffer, _TRUNCATE, format, arg_ptr); va_end(arg_ptr); OutputDebugString(buffer); if (size < 0) { OutputDebugString(_T("...\n")); } } //------------------------------------------------------------------------------ void DigitOnly(LPTSTR pszStr) { LPTSTR psz; TCHAR c; for (psz = pszStr; c = *pszStr; pszStr++) { if (_istdigit(c)) { *psz++ = c; } } *psz = c; } //============================================================================== INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nRet = TRUE; // メッセージを処理した switch (uMsg) { case WM_COMMAND: OnCommand(hDlg, wParam, lParam); break; case WM_DRAWITEM: OnDrawItem(wParam, lParam); break; case WM_DROPFILES: OnDropFiles(hDlg, wParam); DragFinish((HDROP)wParam); break; case WM_INITDIALOG: OnInitDialog(hDlg); nRet = TRUE; // SetFocusでフォーカスを設定した場合はFALSE break; case WM_CLOSE: if (OnClose(hDlg)) { EndDialog(hDlg, 0); } break; default: nRet = FALSE; // メッセージを処理しなかった } return nRet; } //------------------------------------------------------------------------------ void OnInitDialog(HWND hDlg) { g.hMainDlg = hDlg; g.hRec = GetDlgItem(hDlg, IDC_RECORD); g.hSpin = GetDlgItem(hDlg, IDC_SPIN); g.hUpdate = GetDlgItem(hDlg, IDC_UPDATE); SendMessage(g.hSpin, UDM_SETBUDDY, (WPARAM)g.hRec, 0); g.hSubDlg = CreateDialog(g.hInstance, MAKEINTRESOURCE(IDD_SUB), hDlg, SubDlgProc); } //------------------------------------------------------------------------------ void OnDropFiles(HWND hDlg, WPARAM wParam) { HDROP hDrop = (HDROP)wParam; TCHAR szPath[MAX_PATH]; UINT ur = DragQueryFile(hDrop, 0, szPath, _countof(szPath)); SplitPath(szPath); ListView_DeleteAllItems(g.hList); InitAddress(hDlg); InvalidateRect(GetDlgItem(hDlg, IDC_PREVIEW), NULL, FALSE); } //------------------------------------------------------------------------------ BOOL OnClose(HWND hDlg) { BOOL bRet = TRUE; // レコード変更の確認 if (CheckRecMod(hDlg) == FALSE) return FALSE; // テーブル変更の確認 if (g.bTableMod == FALSE) return TRUE; int nr = MessageBox(hDlg, _T("住所録の内容は変更されています。\n\n保存しますか?"), APPNAME, MB_YESNOCANCEL | MB_ICONWARNING); switch (nr) { case IDYES: bRet = SaveTable(hDlg); break; case IDNO: break; default: bRet = FALSE; } return bRet; } //------------------------------------------------------------------------------ BOOL CheckRecMod(HWND hWnd) { if (g.bRecMod == FALSE) return TRUE; int nr = MessageBox(hWnd, _T("レコードの内容は変更されています。\n\n更新しますか?"), APPNAME, MB_YESNOCANCEL | MB_ICONWARNING); switch (nr) { case IDYES: OnUpdate(); break; case IDNO: break; default: return FALSE; } return TRUE; } //------------------------------------------------------------------------------ void OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) { WORD wNotifyCode = HIWORD(wParam); WORD wID = LOWORD(wParam); HWND hwndCtl = (HWND)lParam; switch (wID) { case IDC_ADDRESS: // 住所録 ShowSubDlg(); break; case IDC_PRINT: // 単票印刷 if (CheckRecMod(hDlg)) { OnPrint(hDlg, 0); } break; case IDC_UPDATE: // 更新 OnUpdate(); break; case IDCANCEL: // 終了 SendMessage(hDlg, WM_CLOSE, 0, 0); break; } if (wNotifyCode == EN_CHANGE) { if (hwndCtl == g.hRec) { int nRec = max(SendMessage(g.hSpin, UDM_GETPOS, 0, 0) - 1, 0); if (nRec == g.nRec) return; if (CheckRecMod(hDlg)) { g.nRec = nRec; CopyRecord(); InvalidateRect(GetDlgItem(hDlg, IDC_PREVIEW), NULL, FALSE); } else { SendMessage(g.hSpin, UDM_SETPOS, 0, g.nRec + 1); } } else { if (g.bRecMod == FALSE) { g.bRecMod = TRUE; EnableWindow(g.hUpdate, g.bRecMod); } } } } //------------------------------------------------------------------------------ void OnUpdate(void) { TCHAR szBuf[256]; if (g.nRecNum <= g.nRec) return; for (int n = 0; n < 6; n++) { GetDlgItemText(g.hMainDlg, IDC_FIELD0 + n, szBuf, _countof(szBuf)); ListView_SetItemText(g.hList, g.nRec, n, szBuf); } g.bTableMod = TRUE; g.bRecMod = FALSE; EnableWindow(g.hUpdate, g.bRecMod); InvalidateRect(GetDlgItem(g.hMainDlg, IDC_PREVIEW), NULL, FALSE); } //------------------------------------------------------------------------------ void OnDrawItem(WPARAM wParam, LPARAM lParam) { LPDRAWITEMSTRUCT pdi = (LPDRAWITEMSTRUCT)lParam; HDC hdc = pdi->hDC; // 背景塗り潰し RECT rc; GetClientRect(pdi->hwndItem, &rc); FillRect(hdc, &rc, GetSysColorBrush(COLOR_WINDOW)); Trace(_T("OnDrawItem(%u) %d, %d, %d, %d\n"), wParam, LTRB(rc)); // デバイス能力 g.nPhysicalWidth = WIDTH(rc); g.nPhysicalHeight = HEIGHT(rc); g.nPhysicalOffsetX = 0; g.nPhysicalOffsetY = 0; // 背景 SetRect(&rc, lmpx(0), lmpy(0), lmpx(300), lmpy(570)); FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE)); SetRect(&rc, lmpx(0), lmpy(1250), lmpx(1000), lmpy(1480)); FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNFACE)); int nRec = SendMessage(g.hSpin, UDM_GETPOS, 0, 0); OnDraw(hdc, nRec - 1, TRUE); } //------------------------------------------------------------------------------ void OnDraw(HDC hdc, int nRec, BOOL bGuide) { TCHAR szBuf[256]; HFONT hFont[3]; RECT rc; SetBkMode(hdc, TRANSPARENT); // 背景透過モード Trace(_T("OnDraw(%d)\n"), nRec); // 補助線 HPEN hPen = CreatePen(PS_SOLID, 0, RGB(0xff,0x00,0x00)); HGDIOBJ hPenOld = SelectObject(hdc, hPen); // 郵便番号 LOGFONT lf; ZeroMemory(&lf, sizeof lf); lf.lfCharSet = DEFAULT_CHARSET; lf.lfHeight = -lmph(60); _tcscpy_s(lf.lfFaceName, _T("MS ゴシック")); hFont[0] = CreateFontIndirect(&lf); HGDIOBJ hFontOld = SelectObject(hdc, hFont[0]); SetRect(&rc, lmpx(440), lmpy(120), lmpx(930), lmpy(200)); if (bGuide) { Rectangle(hdc, LTRB(rc)); } if (nRec < g.nRecNum) { ListView_GetItemText(g.hList, nRec, 2, szBuf, _countof(szBuf)); DigitOnly(szBuf); // 440, 510, 580, 650, 720, 790, 860 for (size_t n = 0; n < _tcslen(szBuf); n++) { rc.right = rc.left + lmpw(70); DrawText(hdc, szBuf + n, 1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); rc.left = rc.right; } } // 住所 lf.lfEscapement = 2700; lf.lfOrientation= 2700; lf.lfHeight = -lmph(60); _tcscpy_s(lf.lfFaceName, _T("@MS 明朝")); hFont[1] = CreateFontIndirect(&lf); SelectObject(hdc, hFont[1]); SetRect(&rc, lmpx(850-70), lmpy(300), lmpx(850), lmpy(1230)); DrawField(hdc, &rc, nRec, 3, bGuide, NULL); SetRect(&rc, lmpx(780-70), lmpy(400), lmpx(780), lmpy(1230)); DrawField(hdc, &rc, nRec, 4, bGuide, NULL); SetRect(&rc, lmpx(710-70), lmpy(400), lmpx(710), lmpy(1230)); DrawField(hdc, &rc, nRec, 5, bGuide, NULL); // 氏名・連名 lf.lfHeight = -lmph(90); hFont[2] = CreateFontIndirect(&lf); SelectObject(hdc, hFont[2]); SetRect(&rc, lmpx(520-100), lmpy(400), lmpx(520), lmpy(1230)); DrawField(hdc, &rc, nRec, 0, bGuide, _T("様")); SetRect(&rc, lmpx(420-100), lmpy(400), lmpx(420), lmpy(1230)); DrawField(hdc, &rc, nRec, 1, bGuide, _T("様")); // 終了処理 SelectObject(hdc, hFontOld); for (int n = 0; n < _countof(hFont); n++) { DeleteObject(hFont[n]); } SelectObject(hdc, hPenOld); DeleteObject(hPen); } //------------------------------------------------------------------------------ void DrawField(HDC hdc, PRECT prc, int nRow, int nCol, BOOL bGuide, LPCTSTR pszSuffix) { TCHAR szText[64]; if (bGuide) { Rectangle(hdc, LTRB(*prc)); } if (g.nRecNum <= nRow) return; ListView_GetItemText(g.hList, nRow, nCol, szText, _countof(szText)); if (szText[0]) { if (pszSuffix) { _tcscat_s(szText, pszSuffix); } TextOut(hdc, prc->right, prc->top, szText, _tcslen(szText)); } } //------------------------------------------------------------------------------ void OnPrint(HWND hDlg, int nMode) { PRINTDLGEX pd; LPDEVMODE pdm; LPDEVNAMES pdn; HRESULT hr; BOOL br; HDC hdc = NULL; // 印刷ダイアログ 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; } // プリンタ準備 pdm = (LPDEVMODE)GlobalLock(g.hDevMode); pdn = (LPDEVNAMES)GlobalLock(g.hDevNames); pdm->dmOrientation = DMORIENT_PORTRAIT; hdc = CreateDC(NULL, (LPCTSTR)pdn + pdn->wDeviceOffset, NULL, pdm); br = GlobalUnlock(g.hDevNames); br = GlobalUnlock(g.hDevMode); // デバイス能力の取得 g.nHorzRes = GetDeviceCaps(hdc, HORZRES); g.nVertRes = GetDeviceCaps(hdc, VERTRES); g.nPhysicalWidth = GetDeviceCaps(hdc, PHYSICALWIDTH); g.nPhysicalHeight = GetDeviceCaps(hdc, PHYSICALHEIGHT); g.nPhysicalOffsetX = GetDeviceCaps(hdc, PHYSICALOFFSETX); g.nPhysicalOffsetY = GetDeviceCaps(hdc, PHYSICALOFFSETY); g.nLogPixelsX = GetDeviceCaps(hdc, LOGPIXELSX); g.nLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY); // 用紙サイズを確認 SIZE size; size.cx = g.nPhysicalWidth * 254 / g.nLogPixelsX; size.cy = g.nPhysicalHeight * 254 / g.nLogPixelsY; Trace(_T("OnPrint %d %d\n"), size.cx, size.cy); if (100 < abs(size.cx - 1000) || 100 < abs(size.cy - 1480)) { MessageBox(hDlg, _T("用紙サイズを確認してください。"), NULL, MB_OK); goto Exit; } // 印刷開始 DOCINFO di; ZeroMemory(&di, sizeof di); di.cbSize = sizeof di; di.lpszDocName = APPNAME; int nr = StartDoc(hdc, &di); switch (nMode) { case 0: // 単票 nr = StartPage(hdc); int nRec; nRec = SendMessage(g.hSpin, UDM_GETPOS, 0, 0); OnDraw(hdc, nRec - 1, TRUE); nr = EndPage(hdc); break; case 1: // 連続 for (int n = 0; n < g.nRecNum; n++) { br = ListView_GetCheckState(g.hList, n); if (br) { nr = StartPage(hdc); OnDraw(hdc, n, TRUE); nr = EndPage(hdc); } } break; } // 印刷終了 nr = EndDoc(hdc); Exit: if (hdc) { DeleteDC(hdc); } } //------------------------------------------------------------------------------ void CopyRecord(void) { TCHAR szBuf[256]; Trace(_T("CopyRecord %d %d\n"), g.nRec, g.nRecNum); if (g.nRecNum <= g.nRec) return; for (int n = 0; n < 6; n++) { ListView_GetItemText(g.hList, g.nRec, n, szBuf, _countof(szBuf)); SetDlgItemText(g.hMainDlg, IDC_FIELD0 + n, szBuf); } g.bRecMod = FALSE; EnableWindow(g.hUpdate, g.bRecMod); } //------------------------------------------------------------------------------ void ShowSubDlg(void) { ShowWindow(g.hSubDlg, IsWindowVisible(g.hSubDlg) ? SW_HIDE : SW_SHOW); } //------------------------------------------------------------------------------ // 0.1mm単位をピクセルに変換 // LoMetric to Pixel X int lmpx(int lm) { return lmpw(lm) - g.nPhysicalOffsetX; } // LoMetric to Pixel Y int lmpy(int lm) { return lmph(lm) - g.nPhysicalOffsetY; } // LoMetric to Pixel Width int lmpw(int lm) { return lm * g.nPhysicalWidth / 1000; } // LoMetric to Pixel Height int lmph(int lm) { return lm * g.nPhysicalHeight / 1480; } //============================================================================== INT_PTR CALLBACK SubDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { INT_PTR nRet = TRUE; // メッセージを処理した switch (uMsg) { case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_CHECK: // 全てチェック/解除 OnCheck(hDlg); break; case IDC_SAVE: // 保存 OnSave(hDlg); break; case IDC_PRINT: // 連続印刷 OnSubPrint(hDlg); break; case IDCANCEL: // 閉じる ShowSubDlg(); break; } break; case WM_INITDIALOG: OnSubInitDialog(hDlg); nRet = TRUE; // SetFocusでフォーカスを設定した場合はFALSE break; case WM_CLOSE: ShowSubDlg(); break; default: nRet = FALSE; // メッセージを処理しなかった } return nRet; } //------------------------------------------------------------------------------ void OnCheck(HWND hDlg) { UINT ur = IsDlgButtonChecked(hDlg, IDC_CHECK); BOOL bCheck = (ur == BST_CHECKED); for (int n = 0; n < g.nRecNum; n++) { ListView_SetCheckState(g.hList, n, bCheck); } } //------------------------------------------------------------------------------ void OnSave(HWND hDlg) { if (g.bTableMod == FALSE) return; int nr = MessageBox(hDlg, _T("住所録を保存しますか?"), APPNAME, MB_YESNO | MB_ICONQUESTION); if (nr == IDYES) { SaveTable(hDlg); } } //------------------------------------------------------------------------------ void OnSubPrint(HWND hDlg) { BOOL br = FALSE; for (int n = 0; n < g.nRecNum; n++) { br = ListView_GetCheckState(g.hList, n); if (br) break; } if (br == FALSE) { MessageBox(hDlg, _T("印刷するレコードにチェックを付けてください。"), APPNAME, MB_OK); return; } OnPrint(hDlg, 1); } //------------------------------------------------------------------------------ void OnSubInitDialog(HWND hDlg) { RECT rc; GetClientRect(hDlg, &rc); Trace(_T("OnInitDialog %d, %d, %d, %d\n"), LTRB(rc)); // リストビュー拡張スタイル g.hList = GetDlgItem(hDlg, IDC_LIST); DWORD dwExStyle = ListView_GetExtendedListViewStyle(g.hList); dwExStyle |= LVS_EX_CHECKBOXES | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES; ListView_SetExtendedListViewStyle(g.hList, dwExStyle); InitAddress(hDlg); } //------------------------------------------------------------------------------ void InitAddress(HWND hWnd) { // テーブルの読み込み LoadTable(hWnd); g.nRecNum = ListView_GetItemCount(g.hList); g.nRec = 0; CopyRecord(); SendMessage(g.hSpin, UDM_SETRANGE32, 1, g.nRecNum); SendMessage(g.hSpin, UDM_SETPOS, 0, MAKELONG(1, 0)); } //------------------------------------------------------------------------------ void LoadTable(HWND hWnd) { TCHAR buf[256]; SQLHDBC hdbc; // 接続ハンドル SQLHSTMT hstmt; // 命令ハンドル SQLSMALLINT col; SQLSMALLINT n; SQLSMALLINT datatype; SQLLEN len; SQLRETURN rc; // retcode // データベースへの接続 _stprintf_s(buf, _T("driver={%s}; dbq=%s"), DRIVER, g.szDbq); rc = SQLAllocHandle(SQL_HANDLE_DBC, g.henv, &hdbc); rc = SQLDriverConnect(hdbc, NULL, (SQLTCHAR *)buf, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT); if (!SQL_SUCCEEDED(rc)) { goto Exit; } // 検索 _stprintf_s(buf, _T("select * from %s"), g.szTable); rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); rc = SQLExecDirect(hstmt, (SQLTCHAR *)buf, SQL_NTS); if (!SQL_SUCCEEDED(rc)) { goto Exit; } // 列情報 LV_COLUMN lvCol; lvCol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; lvCol.fmt = LVCFMT_LEFT; lvCol.cx = 100; rc = SQLNumResultCols(hstmt, &col); for (n = 0; n < col; n++) { rc = SQLDescribeCol(hstmt, n+1, (SQLTCHAR *)buf, _countof(buf), NULL, &datatype, NULL, NULL, NULL); lvCol.pszText = buf; lvCol.iSubItem = n; ListView_InsertColumn(g.hList, n, &lvCol); // Text 12 SQL_VARCHAR Char // Byte -6 SQL_TINYINT } // 行情報 LV_ITEM lvItem; lvItem.mask = LVIF_TEXT; lvItem.iItem = 0; while (1) { rc = SQLFetch(hstmt); if (rc == SQL_NO_DATA) break; if (rc == SQL_ERROR) break; for (n = 0; n < col; n++) { SQLGetData(hstmt, n+1, SQL_C_TCHAR, buf, _countof(buf), &len); if (len == SQL_NULL_DATA) { buf[0] = _T('\0'); } lvItem.pszText = buf; lvItem.iSubItem = n; if (n == 0) { ListView_InsertItem(g.hList, &lvItem); } else { ListView_SetItem(g.hList, &lvItem); } } lvItem.iItem++; } SQLFreeHandle(SQL_HANDLE_STMT, hstmt); Exit: SQLDisconnect(hdbc); SQLFreeHandle(SQL_HANDLE_DBC, hdbc); } //------------------------------------------------------------------------------ BOOL SaveTable(HWND hWnd) { TCHAR szNew[MAX_PATH]; _stprintf_s(szNew, _T("%s%s_"), g.szDbq, g.szTable); if (CreateCsvFile(hWnd, szNew) == FALSE) { return FALSE; } // CSVファイルの削除とリネーム TCHAR szOld[MAX_PATH]; _stprintf_s(szOld, _T("%s%s"), g.szDbq, g.szTable); BOOL br; br = DeleteFile(szOld); br = MoveFile(szNew, szOld); if (br == FALSE) { MessageBox(hWnd, _T("CSVファイルのリネームに失敗しました。"), NULL, MB_OK); return FALSE; } g.bTableMod = FALSE; return TRUE; } //------------------------------------------------------------------------------ BOOL CreateCsvFile(HWND hWnd, LPCTSTR pszPath) { TCHAR szBuf[MAX_PATH]; int nColNum = 6; // ファイルのオープン FILE *pFile; errno_t er = _tfopen_s(&pFile, pszPath, _T("wt")); if (er) { MessageBox(hWnd, _T("ファイルのオープンに失敗しました。"), NULL, MB_OK); return FALSE; } // ヘッダ行 _stprintf_s(szBuf, _T("%s%s"), g.szDbq, _T("schema.ini")); DWORD dw = GetPrivateProfileString(g.szTable, _T("ColNameHeader"), NULL, szBuf, _countof(szBuf), szBuf); if (_tcsicmp(szBuf, _T("true")) == 0) { LVCOLUMN lvcol; lvcol.mask = LVCF_TEXT; lvcol.pszText = szBuf; lvcol.cchTextMax= _countof(szBuf); for (int nCol = 0; ; ) { ListView_GetColumn(g.hList, nCol, &lvcol); _ftprintf_s(pFile, _T("%s"), lvcol.pszText); if (nColNum <= ++nCol) { break; } _ftprintf_s(pFile, _T(",")); } _ftprintf_s(pFile, _T("\n")); } // 書き込み int nRowNum = ListView_GetItemCount(g.hList); for (int nRow = 0; nRow < nRowNum; nRow++) { for (int nCol = 0; ; ) { ListView_GetItemText(g.hList, nRow, nCol, szBuf, _countof(szBuf)); _ftprintf_s(pFile, _T("%s"), szBuf); if (nColNum <= ++nCol) { break; } _ftprintf_s(pFile, _T(",")); } _ftprintf_s(pFile, _T("\n")); } fclose(pFile); return TRUE; } }} resource.h #highlight(c){{ #define IDD_MAIN 100 #define IDD_SUB 101 #define IDC_STATIC -1 #define IDC_PREVIEW 1000 #define IDC_ADDRESS 1001 #define IDC_PRINT 1002 #define IDC_RECORD 1003 #define IDC_SPIN 1004 #define IDC_UPDATE 1005 #define IDC_FIELD0 1010 #define IDC_FIELD1 1011 #define IDC_FIELD2 1012 #define IDC_FIELD3 1013 #define IDC_FIELD4 1014 #define IDC_FIELD5 1015 #define IDC_LIST 1100 #define IDC_CHECK 1101 #define IDC_SAVE 1102 }} PrnAddr.rc #highlight(c){{ // resource script #include <windows.h> #include "resource.h" //------------------------------------------------------------------------------ IDD_MAIN DIALOGEX 100, 50, 400, 304 STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX EXSTYLE WS_EX_APPWINDOW | WS_EX_ACCEPTFILES CAPTION "PrnAddr" FONT 10, "MS ゴシック" BEGIN LTEXT "",IDC_PREVIEW,4,4,200,296,WS_BORDER | SS_OWNERDRAW LTEXT "氏名",IDC_STATIC,212,8,32,12 EDITTEXT IDC_FIELD0,248,8,144,12,ES_AUTOHSCROLL LTEXT "連名",IDC_STATIC,212,28,32,12 EDITTEXT IDC_FIELD1,248,28,144,12,ES_AUTOHSCROLL LTEXT "郵便番号",IDC_STATIC,212,48,32,12 EDITTEXT IDC_FIELD2,248,48,144,12,ES_AUTOHSCROLL LTEXT "住所1",IDC_STATIC,212,68,32,12 EDITTEXT IDC_FIELD3,248,68,144,12,ES_AUTOHSCROLL LTEXT "住所2",IDC_STATIC,212,88,32,12 EDITTEXT IDC_FIELD4,248,88,144,12,ES_AUTOHSCROLL LTEXT "住所3",IDC_STATIC,212,108,32,12 EDITTEXT IDC_FIELD5,248,108,144,12,ES_AUTOHSCROLL EDITTEXT IDC_RECORD,248,128,48,16 CONTROL "",IDC_SPIN,"msctls_updown32", UDS_ARROWKEYS | UDS_SETBUDDYINT | UDS_ALIGNRIGHT, 280,128,32,16 PUSHBUTTON "更新(&U)",IDC_UPDATE,336,128,56,24 PUSHBUTTON "住所録(&A)",IDC_ADDRESS,212,276,56,24 PUSHBUTTON "単票印刷(&P)",IDC_PRINT,276,276,56,24 PUSHBUTTON "終了(&X)",IDCANCEL,340,276,56,24 END //------------------------------------------------------------------------------ IDD_SUB DIALOG 0, 350, 384, 200 STYLE WS_POPUPWINDOW CAPTION "住所録" FONT 9, "MS Pゴシック" BEGIN CONTROL "",IDC_LIST,"SysListView32", WS_BORDER | WS_TABSTOP | LVS_REPORT,8,8,368,160 CONTROL "全てチェック/解除(&A)",IDC_CHECK,"button", BS_AUTOCHECKBOX | WS_TABSTOP,8,176,80,16 PUSHBUTTON "保存(&S)",IDC_SAVE,216,176,48,16 PUSHBUTTON "連続印刷(&P)",IDC_PRINT,272,176,48,16 PUSHBUTTON "閉じる(&X)",IDCANCEL,328,176,48,16 END }} schema.ini [address.csv] ColNameHeader=True CharacterSet=932 Format=CSVDelimited Col1=氏名 Char Col2=連名 Char Col3=郵便番号 Char Width 8 Col4=住所1 Char Col5=住所2 Char Col6=住所3 Char address.csv 氏名,連名,郵便番号,住所1,住所2,住所3 国会 議事堂,   花子 ,100-0014,東京都千代田区,永田町一丁目七番一号, 東京 タワー,,105-0011,東京都港区,芝公園四丁目二―八,

表示オプション

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