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

注意
元のファイルが失われる恐れがあるので、必要なファイルは必ずバックアップを取ってください。

参考

ListView.cpp
// Unicode
#include <Windows.h>
#include <CommCtrl.h>
#include <sqlext.h>
#include <vector>
#include <string>
#include "resource.h"
 
#define DRIVER TEXT("Microsoft Text Driver (*.txt; *.csv)")
#define DATABASE TEXT("C:\\tmp")
#define TABLE TEXT("09TOCHIG.CSV")
#define TABLE2 TEXT("09TOCHIG_.CSV")
 
// 型定義
struct ColInfo {	// 列情報
	std::wstring strName;	// 列名
	SQLSMALLINT datatype;	// データ型
};
typedef std::vector<ColInfo> VecCI;
 
// 関数プロトタイプ宣言
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnNmDblClk(HWND hDlg, LPARAM lParam);
void OnInitDialog(HWND hDlg);
void LoadTable(HWND hDlg);
void SaveTable(HWND hDlg);
BOOL CreateTable(void);
BOOL InsertRecord(void);
 
INT_PTR CALLBACK SubDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void OnSubInitDialog(HWND hDlg);
void OnOK(HWND hDlg);
 
// 外部変数構造体
static struct {
	HINSTANCE hInstance;
	HWND hList;	// リストビュー
	SQLHENV henv;	// 環境ハンドル
	SQLHDBC hdbc;	// 接続ハンドル
	VecCI vecci;	// 列情報
	int iItem;	// 指定された行
} g;
 
//==============================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int)
{
	// 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);
 
	g.hInstance = hInstance;
	DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc);
 
	SQLFreeHandle(SQL_HANDLE_ENV, g.henv);
	return 0;
}
 
//------------------------------------------------------------------------------
INT_PTR CALLBACK MainDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	INT_PTR nRet = TRUE;	// メッセージを処理した
 
	switch (uMsg) {
	case WM_NOTIFY:
		switch (((LPNMHDR)lParam)->idFrom) {
		case IDC_LIST:
			switch (((LPNMLISTVIEW)lParam)->hdr.code) {
			case NM_DBLCLK:
				OnNmDblClk(hDlg, lParam);
				break;
			}
			break;
		}
		break;
	case WM_COMMAND:
		switch (LOWORD(wParam)) {
		case IDC_UPDATE:
			int nr;
			nr = MessageBox(hDlg, L"CSVファイルを更新しますか?", L"確認", MB_OKCANCEL);
			if (nr == IDOK) {
				SaveTable(hDlg);
				MessageBox(hDlg, L"完了しました。", L"報告", MB_OK);
			}
			break;
		case IDCANCEL:
			EndDialog(hDlg, IDCANCEL);
			break;
		}
		break;
	case WM_INITDIALOG:
		OnInitDialog(hDlg);
		nRet = TRUE;	// SetFocusでフォーカスを設定した場合はFALSE
		break;
	case WM_CLOSE:
		EndDialog(hDlg, 0);
		break;
	case WM_DESTROY:
		SQLDisconnect(g.hdbc);
		SQLFreeHandle(SQL_HANDLE_DBC, g.hdbc);
		break;
	default:
		nRet = FALSE;	// メッセージを処理しなかった
	}
	return nRet;
}
 
//------------------------------------------------------------------------------
void OnNmDblClk(HWND hDlg, LPARAM lParam)
{
	LPNMLISTVIEW plv = (LPNMLISTVIEW)lParam;
	g.iItem = plv->iItem;
	DialogBox(g.hInstance, MAKEINTRESOURCE(IDD_SUB), hDlg, SubDlgProc);
}
 
//------------------------------------------------------------------------------
void OnInitDialog(HWND hDlg)
{
	// リストビュー拡張スタイル
	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);
 
	// テーブルの読み込み
	LoadTable(hDlg);
}
 
//------------------------------------------------------------------------------
void LoadTable(HWND hDlg)
{
	SQLHSTMT hstmt;	// 命令ハンドル
	SQLSMALLINT col;
	SQLSMALLINT n;
	SQLSMALLINT datatype;
	SQLTCHAR buf[256];
	SQLLEN len;
	SQLRETURN rc;	// retcode
 
	// データベースへの接続
	rc = SQLAllocHandle(SQL_HANDLE_DBC, g.henv, &g.hdbc);
	rc = SQLDriverConnect(g.hdbc, NULL,
		(SQLTCHAR *) TEXT("driver={") DRIVER TEXT("}; dbq=") DATABASE,
		SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT);
	if (!SQL_SUCCEEDED(rc)) {
		return;
	}
 
	// 検索
	rc = SQLAllocHandle(SQL_HANDLE_STMT, g.hdbc, &hstmt);
	rc = SQLExecDirect(hstmt, (SQLTCHAR *) TEXT("select * from ") TABLE, SQL_NTS);
	if (!SQL_SUCCEEDED(rc)) {
		return;
	}
	// 列情報
	LV_COLUMN lvCol;
	lvCol.mask	= LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
	lvCol.fmt	= LVCFMT_LEFT;
	lvCol.cx	= 100;
	rc = SQLNumResultCols(hstmt, &col);
	g.vecci.reserve(col);
	for (n = 0; n < col; n++) {
		rc = SQLDescribeCol(hstmt, n+1, buf, _countof(buf), NULL,
			&datatype, NULL, NULL, NULL);
		lvCol.pszText	= buf;
		lvCol.iSubItem	= n;
		ListView_InsertColumn(g.hList, n, &lvCol);
		// 列情報
		ColInfo ci;
		ci.strName	= buf;
		ci.datatype	= datatype;
		g.vecci.push_back(ci);
		// Text 12 SQL_VARCHAR
		// 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);
			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);
}
 
//------------------------------------------------------------------------------
void SaveTable(HWND hDlg)
{
	// テーブルの作成
	if (CreateTable() == FALSE) {
		MessageBox(hDlg, L"テーブルの作成に失敗しました。", NULL, MB_OK);
		return;
	}
 
	// レコードの挿入
	if (InsertRecord() == FALSE) {
		MessageBox(hDlg, L"レコードの挿入に失敗しました。", NULL, MB_OK);
		return;
	}
 
	// CSVファイルの削除とリネーム
	TCHAR szOld[MAX_PATH];
	TCHAR szNew[MAX_PATH];
	swprintf_s(szOld, L"%s\\%s", DATABASE, TABLE);
	swprintf_s(szNew, L"%s\\%s", DATABASE, TABLE2);
	BOOL br;
	br = DeleteFile(szOld);
	br = MoveFile(szNew, szOld);
	if (br == FALSE) {
		MessageBox(hDlg, L"CSVファイルのリネームに失敗しました。", NULL, MB_OK);
	}
}
 
//------------------------------------------------------------------------------
BOOL CreateTable(void)
{
	TCHAR stmttext[512];
	SQLHSTMT hstmt;	// 命令ハンドル
	SQLRETURN rc;	// retcode
 
	rc = SQLAllocHandle(SQL_HANDLE_STMT, g.hdbc, &hstmt);
 
	// テーブルの削除
	wcscpy_s(stmttext, L"drop table ");
	wcscat_s(stmttext, TABLE2);
	rc = SQLExecDirect(hstmt, stmttext, SQL_NTS);
	// 失敗してもテーブルの作成が成功すれば問題ない
 
	// テーブルの作成
	wcscpy_s(stmttext, L"create table ");
	wcscat_s(stmttext, TABLE2);
	wcscat_s(stmttext, L"(");
	VecCI::iterator it = g.vecci.begin();
	while (TRUE) {
		wcscat_s(stmttext, (*it).strName.c_str());
		switch ((*it).datatype) {
		case SQL_VARCHAR:
			wcscat_s(stmttext, L" Text");
			break;
		case SQL_TINYINT:
			wcscat_s(stmttext, L" Byte");
			break;
		}
		if (++it == g.vecci.end()) {
			break;
		}
		wcscat_s(stmttext, L",");
	}
	wcscat_s(stmttext, L")");
	rc = SQLExecDirect(hstmt, stmttext, SQL_NTS);
 
	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
	return SQL_SUCCEEDED(rc);
}
 
//------------------------------------------------------------------------------
BOOL InsertRecord(void)
{
	SQLHSTMT hstmt;	// 命令ハンドル
	SQLRETURN rc;	// retcode
	BOOL bRet = TRUE;
 
	rc = SQLAllocHandle(SQL_HANDLE_STMT, g.hdbc, &hstmt);
	int nColNum = g.vecci.size();
	int nRowNum = ListView_GetItemCount(g.hList);
 
	for (int nRow = 0; nRow < nRowNum; nRow++) {
		TCHAR stmttext[512];
		wcscpy_s(stmttext, L"insert into ");
		wcscat_s(stmttext, TABLE2);
		wcscat_s(stmttext, L" values (");
 
		for (int nCol = 0; ; ) {
			TCHAR szBuf[256];
			ListView_GetItemText(g.hList, nRow, nCol, szBuf, _countof(szBuf));
			switch (g.vecci[nCol].datatype) {
			case SQL_VARCHAR:
				wcscat_s(stmttext, L"'");
				wcscat_s(stmttext, szBuf);
				wcscat_s(stmttext, L"'");
				break;
			case SQL_TINYINT:
				wcscat_s(stmttext, szBuf);
				break;
			}
			if (nColNum <= ++nCol) {
				break;
			}
			wcscat_s(stmttext, L",");
		}
		wcscat_s(stmttext, L")");
		rc = SQLExecDirect(hstmt, stmttext, SQL_NTS);
		if (!SQL_SUCCEEDED(rc)) {
			bRet = FALSE;
			break;
		}
	}
	SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
 
	// トランザクション終了
	rc = SQLEndTran(SQL_HANDLE_ENV, g.henv, SQL_COMMIT);
	return bRet;
}
 
//==============================================================================
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 IDOK:
			OnOK(hDlg);
			EndDialog(hDlg, IDOK);
			break;
		case IDCANCEL:
			EndDialog(hDlg, IDCANCEL);
			break;
		}
		break;
	case WM_INITDIALOG:
		OnSubInitDialog(hDlg);
		nRet = TRUE;	// SetFocusでフォーカスを設定した場合はFALSE
		break;
	case WM_CLOSE:
		EndDialog(hDlg, 0);
		break;
	default:
		nRet = FALSE;	// メッセージを処理しなかった
	}
	return nRet;
}
 
//------------------------------------------------------------------------------
void OnSubInitDialog(HWND hDlg)
{
	int nFieldNum = g.vecci.size();
	for (int n = 0; n < nFieldNum; n++) {
		int y = 8 + 28 * n;
		TCHAR szBuf[256];
		ListView_GetItemText(g.hList, g.iItem, n, szBuf, _countof(szBuf));
		DWORD dwStyle = (g.vecci[n].datatype == SQL_TINYINT) ? ES_NUMBER : 0;
 
		CreateWindow(L"static", g.vecci[n].strName.c_str(), WS_CHILD | WS_VISIBLE,
			8, y, 192, 24, hDlg, (HMENU)IDC_STATIC, g.hInstance, 0);
		CreateWindowEx(WS_EX_CLIENTEDGE, L"edit", szBuf,
			WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_AUTOHSCROLL | dwStyle,
			208, y, 192, 24, hDlg, (HMENU)(IDC_FIELD + n), g.hInstance, 0);
	}
}
 
//------------------------------------------------------------------------------
void OnOK(HWND hDlg)
{
	int nFieldNum = g.vecci.size();
	for (int n = 0; n < nFieldNum; n++) {
		TCHAR szBuf[256];
		GetDlgItemText(hDlg, IDC_FIELD + n, szBuf, _countof(szBuf));
		ListView_SetItemText(g.hList, g.iItem, n, szBuf);
	}
}
 

resource.h
#define IDD_MAIN	100
#define IDD_SUB		101
 
#define IDC_STATIC	-1
#define IDC_LIST	1000
#define IDC_UPDATE	1001
 
#define IDC_FIELD	1100
 

ListView.rc
// resource script
#include <windows.h>
#include "resource.h"
 
//------------------------------------------------------------------------------
IDD_MAIN DIALOGEX 100, 100, 320, 200
STYLE WS_POPUPWINDOW | WS_MINIMIZEBOX
EXSTYLE WS_EX_APPWINDOW
CAPTION "ListView"
FONT 9, "MS Pゴシック"
BEGIN
	CONTROL		"",IDC_LIST,"SysListView32",
			WS_BORDER | WS_TABSTOP | LVS_REPORT,8,8,304,160
	PUSHBUTTON	"更新",IDC_UPDATE,212,176,48,16
	PUSHBUTTON	"終了",IDCANCEL,264,176,48,16
END
 
//------------------------------------------------------------------------------
IDD_SUB DIALOG 100, 100, 320, 400
STYLE WS_POPUPWINDOW
CAPTION "SubDlg"
FONT 9, "MS Pゴシック"
BEGIN
	DEFPUSHBUTTON	"OK",IDOK,212,376,48,16
	PUSHBUTTON	"Cancel",IDCANCEL,264,376,48,16
END
 
最終更新:2012年10月26日 15:52