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