// LvEdit.cpp - リストビューの項目編集ダイアログ

#include "stdafx.h"
#include "Rnsf7.h"
#include "LvEdit.h"
#include "opendlg.h"
#include "filetypes.h"
#include "addctrl.h"

static LRESULT CALLBACK lv2eDialog( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );	// ValueList(key:1-value:1)
static LRESULT CALLBACK lvmeDialog( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );	// ValueList(key:1-value:1 ただし、複数行展開)
static LRESULT CALLBACK lvneDialog( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );	// ValueList(key:1-value:n)
static char *ml_itemname, *ml_itemdata, *ml_col1, *ml_col2;
static HWND ml_hListView, ml_hWnd;

// ------------------------------------------------------------------------------------------------
// ValueList(key:1-value:1)
// ------------------------------------------------------------------------------------------------
// ValueListの追加・編集
bool lv_edititem(HWND hWnd, char **itemname, char **itemdata, HWND hListView, char *col1, char *col2)
{
	ml_hWnd = hWnd;
	ml_itemname = *itemname;
	ml_itemdata = *itemdata;
	ml_col1 = col1;
	ml_col2 = col2;
	ml_hListView = hListView;

	if ( IDOK == DialogBox(hInst, (LPCTSTR)IDD_EDIT_LV2, hWnd, (DLGPROC)lv2eDialog) ) {
		*itemname = ml_itemname;
		*itemdata = ml_itemdata;
        return true;
	}
	else {
		return false;
	}
}

// ダイアログのアンカー等に関する情報
const DLGITEM dlgitems[] = {
	{IDC_EDIT1,					ANCHOR_TOPLEFTRIGHT},
	{IDC_EDIT2,					ANCHOR_TOPLEFTRIGHT},
	{IDC_FILE_BROWSE0,			ANCHOR_TOPRIGHT},
	{IDC_FILE_BROWSE,			ANCHOR_TOPRIGHT},
	{IDC_FOLDER_BROWSE0,		ANCHOR_TOPRIGHT},
	{IDC_FOLDER_BROWSE,			ANCHOR_TOPRIGHT},
	{IDOK,						ANCHOR_BOTTOMRIGHT},
	{IDCANCEL,					ANCHOR_BOTTOMRIGHT},
	{0,0}
};

// ValueListの追加・編集ダイアログ
static LRESULT CALLBACK lv2eDialog( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	static SIZEDLG *sizedlg;

	switch( message ) {
		case WM_INITDIALOG:
			// 現在は、ダイアログは MS P ゴシックで固定
			// SetChildWindowFont( hDlg );

			// ダイアログのアイコン設定
			SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIconInputText);

			if ( ml_itemname == NULL ) {
				SetWindowText(hDlg, "新規");
			}
			else {
				SetDlgItemText(hDlg, IDC_EDIT1, ml_itemname);
				SetDlgItemText(hDlg, IDC_EDIT2, ml_itemdata);
			}
			SetDlgItemText(hDlg, IDC_STATIC1, ml_col1);
			SetDlgItemText(hDlg, IDC_STATIC2, ml_col2);
			SendDlgItemMessage(hDlg, IDC_FILE_BROWSE0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);
			SendDlgItemMessage(hDlg, IDC_FOLDER_BROWSE0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);
			SendDlgItemMessage(hDlg, IDC_FILE_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);
			SendDlgItemMessage(hDlg, IDC_FOLDER_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);
			{
				HWND hTooltip;
				TOOLINFO ti;

				if (NULL == (hTooltip=CreateWindow(TOOLTIPS_CLASS,"",TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hDlg,NULL,hInst,NULL)))
					return NULL;

				ZeroMemory(&ti, sizeof(ti));
				ti.cbSize = sizeof(TOOLINFO);
				ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;// uIDはツールチップを表示するウィンドウを識別するハンドル / サブクラス化もお任せ
				ti.hwnd = hDlg;	// ツールチップを持つウィンドウ

				ti.lpszText = ml_col1;// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_EDIT1);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_STATIC1);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = ml_col2;// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_EDIT2);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_STATIC2);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "ファイルを一覧の中から選び、左の編集ボックスに代入します";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FILE_BROWSE0);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FILE_BROWSE);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "フォルダを一覧の中から選び、左の編集ボックスに代入します";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FOLDER_BROWSE0);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FOLDER_BROWSE);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "入力した内容で決定し、ダイアログを閉じます";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDOK);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "入力した内容をキャンセルし、ダイアログを閉じます";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDCANCEL);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
			}

			// ダイアログのコントロールのアンカーを登録
			sizedlg = new SIZEDLG(hDlg, dlgitems);
			sizedlg->SetMinMaxInfo(sizedlg->GetDefWidth(), sizedlg->GetDefHeight(), -1, sizedlg->GetDefHeight());
			return TRUE;

		case WM_DESTROY:
			// アイコンが書かれているボタンを破棄
			DestroyWindow(GetDlgItem(hDlg, IDC_FILE_BROWSE0));
			DestroyWindow(GetDlgItem(hDlg, IDC_FOLDER_BROWSE0));
			DestroyWindow(GetDlgItem(hDlg, IDC_FILE_BROWSE));
			DestroyWindow(GetDlgItem(hDlg, IDC_FOLDER_BROWSE));

			// リサイズのための情報を破棄
			if (sizedlg) {
				delete sizedlg;
				sizedlg = NULL;
			}
			return TRUE;

		case WM_GETMINMAXINFO:
			// ダイアログの最小サイズを決める
			if (sizedlg) {
				sizedlg->GetMinMaxInfo(lParam);
			}
			return TRUE;

		case WM_SIZE:
			// リサイズ
			if (sizedlg) {
				sizedlg->Resize(1);
			}
			return TRUE;

		case WM_DROPFILES: // 編集ボックスがファイルをドロップされた
			{
				int n; // ドロップされたファイルの数
				int i; // カウンタ
				int len; // 編集ボックス内にすでに存在する文字列のバイト数
				char fname[MAX_PATH*2];
				char *buf;
				POINT pt;
				HWND hEdit; // これから代入しようとする編集ボックス
				RECT rt;

				GetCursorPos( &pt );
				GetWindowRect(GetDlgItem(hDlg, IDC_STATIC2), &rt);

				// ドロップしたときのマウスの位置が、２つめのスタティックテキストよりも上だったら
				if ( pt.y < rt.top ) { // １つめの編集ボックスへのドロップとみなす
					hEdit = GetDlgItem(hDlg, IDC_EDIT1);
				}
				else {  // そうでなければ、２つめの編集ボックスへのドロップとみなす
					hEdit = GetDlgItem(hDlg, IDC_EDIT2);
				}

				n = DragQueryFile((HDROP)wParam, (UINT)-1, NULL, 0);
				for(i=0 ; i<n ; i++) {
					if (_countof(fname) > DragQueryFile((HDROP)wParam, i, fname, _countof(fname))) {
                        len = GetWindowTextLength( hEdit );
						if ( len > 0 ) { // すでに文字列が入っていた場合は、そこにスペースを加えてから追加
							buf = (char *)malloc( len + lstrlen(fname) + 2 );
							if ( buf ) {
								GetWindowText( hEdit, buf, len+1 );
								lstrcat(buf, " ");
								lstrcat(buf, fname);
								SetWindowText(hEdit, buf);
								safefree( buf );
							}
						}
						else { // まだ文字列が入っていない場合は、そのまま設定
                            SetWindowText(hEdit, fname);
						}
					}
				}
				DragFinish((HDROP)wParam);
			}
			break;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDOK:
					{
						char *ml2_itemname = NULL, *ml2_itemdata = NULL;
						int len;

						// 第1項目の値がなければエラー
						len = GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT1));
						if ( len == 0 ) {
							MessageBox(hDlg, "第1項目に何も入力されていません。", "チェック", MB_OK | MB_ICONSTOP);
							return TRUE;
						}

						// 第1項目のデータを取得
						ml2_itemname = (char *)malloc( len+1 );
						if ( ml2_itemname == NULL ) {
							MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
							return TRUE;
						}
                        GetDlgItemText(hDlg, IDC_EDIT1, ml2_itemname, len+1);

						if ( ml_itemname != NULL && _stricmp(ml2_itemname, ml_itemname) == 0 )
							; // 第1項目に変化がなければ、第1項目についてはそのまま
						else { // 変化がある場合は、他の第1項目との重複がないかチェックする
							int i, n;
							char *iname = (char *)malloc( len+2 ); // 現在の第1項目より一文字多めに調べればよい

							if ( iname ) {
								n = ListView_GetItemCount( ml_hListView );
								
								for(i=0 ; i<n ; i++) {
									ListView_GetItemText( ml_hListView, i, 0, iname, len+2 );
									if ( _stricmp(iname, ml2_itemname) == 0 ) {
										MessageBox(hDlg, "第1項目が、リスト内の他の項目と重複しています。","チェック",MB_OK | MB_ICONSTOP);
										safefree( iname );
										safefree( ml2_itemname );
										return TRUE;
									}
								}

								safefree( iname );
							}
							else {
								safefree( ml2_itemname );
								MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
								return TRUE;
							}
						}

						// 万事OKならばバッファのポインタをコピー(その前に旧バッファは解放)
						safefree( ml_itemname );
						ml_itemname = ml2_itemname;

						len = GetWindowTextLength( GetDlgItem(hDlg, IDC_EDIT2) );
						ml2_itemdata = (char *)malloc( len+1 );
						if ( ml2_itemdata ) {
                            GetDlgItemText(hDlg, IDC_EDIT2, ml2_itemdata, len+1);
							safefree( ml_itemdata );
							ml_itemdata = ml2_itemdata;
							EndDialog( hDlg, IDOK );
						}
						else {
							MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
						}
						return TRUE;
					}

				case IDCANCEL:
					EndDialog( hDlg, IDCANCEL );
					return TRUE;

				case IDC_FILE_BROWSE0:
					{
						char fname[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT1, fname, _countof(fname));
						if ( openDialog( hDlg, FILETYPES, fname, _countof(fname), "ファイルの選択", NULL ) ) {
							SetDlgItemText(hDlg, IDC_EDIT1, fname);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT1) );
						}
						return TRUE;
					}

				case IDC_FOLDER_BROWSE0:
					{
						char chPutFolder[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT1, chPutFolder, _countof(chPutFolder));
						if ( browseFolder( hDlg, chPutFolder, "フォルダの選択" ) ) {
							SetDlgItemText(hDlg, IDC_EDIT1, chPutFolder);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT1) );
						}
						return TRUE;
					}

				case IDC_FILE_BROWSE:
					{
						char fname[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT2, fname, _countof(fname));
						if ( openDialog( hDlg, FILETYPES, fname, _countof(fname), "ファイルの選択", NULL ) ) {
							SetDlgItemText(hDlg, IDC_EDIT2, fname);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT2) );
						}
						return TRUE;
					}

				case IDC_FOLDER_BROWSE:
					{
						char chPutFolder[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT2, chPutFolder, _countof(chPutFolder));
						if ( browseFolder( hDlg, chPutFolder, "フォルダの選択" ) ) {
							SetDlgItemText(hDlg, IDC_EDIT2, chPutFolder);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT2) );
						}
						return TRUE;
					}
			}
			break;
	}
    return FALSE;
}

// ------------------------------------------------------------------------------------------------
// ValueList(key:1-value:1 ただし、複数行展開)
// ------------------------------------------------------------------------------------------------
BOOL lv_edititem_m(HWND hWnd, char **itemname, char **itemdata, char *col1, char *col2, char* pcDelim)
{
	ml_hWnd = hWnd;
	ml_itemname = *itemname;
	ml_col1 = col1;				// col1==NULL:１項目編集モード
	ml_col2 = col2 ? col2 : "";
	ml_hListView = NULL;

	// ml_itemdata内にpcDelim[i]があったら、改行文字に置き換える
	if (pcDelim[0]) {
		// 置換後の文字数をカウント(pcDelim[i]を\r\nにするので、pcDelim[i]の文字数が2倍になるとして計算)
		int i1 = 0, i2 = 0, n1 = 0, n2 = 0;

		for(n1=0 ; (*itemdata)[n1] ; ++n1) {
			if (strchr(pcDelim, (*itemdata)[n1])) {
				++n2;
			}
			++n2;
		}

		ml_itemdata = zalloc(n2+2);

		for(i1=0 ; i1<n1 ; ++i1) {
			if (strchr(pcDelim, (*itemdata)[i1]) && !(i1 > 0 && isKanji1(*itemdata, i1-1)) ) {
				ml_itemdata[i2] = '\r';
				ml_itemdata[++i2] = '\n';
			}
			else {
				ml_itemdata[i2] = (*itemdata)[i1];
			}
			++i2;
		}

		free(*itemdata);
		*itemdata = ml_itemdata;
	}
	else {
		ml_itemdata = *itemdata;
	}

	if ( IDOK == DialogBox(hInst, (LPCTSTR)IDD_EDIT_LVM, hWnd, (DLGPROC)lvmeDialog) ) {
		*itemname = ml_itemname;

		// ml_itemdata内に改行があったら、pcDelim[0]に置き換える
		if (pcDelim[0]) {
			int i1 = 0, i2 = 0;

			for(i1=0 ; ml_itemdata[i1] ; ++i1) {
				if (ml_itemdata[i1] == '\r' && ml_itemdata[i1+1] == '\n') {
					ml_itemdata[i2] = pcDelim[0];
					++i1;
				}
				else {
					if (i1 != i2) {
						ml_itemdata[i2] = ml_itemdata[i1];
					}
				}
				++i2;
			}
			ml_itemdata[i2] = 0;
		}
		*itemdata = ml_itemdata;
        return TRUE;
	}
	else {
		return FALSE;
	}
}


// ダイアログのアンカー等に関する情報
const DLGITEM dlgitems_ml[] = {
	{IDC_EDIT1,					ANCHOR_TOPLEFTRIGHT},
	{IDC_EDIT2,					ANCHOR_CENTER},
	{IDC_FILE_BROWSE0,			ANCHOR_TOPRIGHT},
	{IDC_FILE_BROWSE,			ANCHOR_TOPRIGHT},
	{IDC_FOLDER_BROWSE0,		ANCHOR_TOPRIGHT},
	{IDC_FOLDER_BROWSE,			ANCHOR_TOPRIGHT},
	{IDOK,						ANCHOR_BOTTOMRIGHT},
	{IDCANCEL,					ANCHOR_BOTTOMRIGHT},
	{0,0}
};

// ValueListの追加・編集ダイアログ（複数行編集ボックス用）
static LRESULT CALLBACK lvmeDialog( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	static SIZEDLG *sizedlg;

	switch( message ) {
		case WM_INITDIALOG:
			// 現在は、ダイアログは MS P ゴシックで固定
			// SetChildWindowFont( hDlg );

			// ダイアログのアイコン設定
			SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIconInputText);

			if ( ml_itemname == NULL ) {
				SetWindowText(hDlg, "新規");
			}
			else {
				if (ml_col1) SetDlgItemText(hDlg, IDC_EDIT1, ml_itemname);
				SetDlgItemText(hDlg, IDC_EDIT2, ml_itemdata);
			}

			if (ml_col1) {
				SetDlgItemText(hDlg, IDC_STATIC1, ml_col1);
				SendDlgItemMessage(hDlg, IDC_FILE_BROWSE0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);
				SendDlgItemMessage(hDlg, IDC_FOLDER_BROWSE0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);
			}
			else { // １項目編集モード
				ShowWindow(GetDlgItem(hDlg, IDC_STATIC1), SW_HIDE);
				ShowWindow(GetDlgItem(hDlg, IDC_EDIT1), SW_HIDE);
				ShowWindow(GetDlgItem(hDlg, IDC_FILE_BROWSE0), SW_HIDE);
				ShowWindow(GetDlgItem(hDlg, IDC_FOLDER_BROWSE0), SW_HIDE);
			}

			SetDlgItemText(hDlg, IDC_STATIC2, ml_col2);
			SendDlgItemMessage(hDlg, IDC_FILE_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);
			SendDlgItemMessage(hDlg, IDC_FOLDER_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);
			{
				HWND hTooltip;
				TOOLINFO ti;

				if (NULL == (hTooltip=CreateWindow(TOOLTIPS_CLASS,"",TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hDlg,NULL,hInst,NULL)))
					return NULL;

				ZeroMemory(&ti, sizeof(ti));
				ti.cbSize = sizeof(TOOLINFO);
				ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;// uIDはツールチップを表示するウィンドウを識別するハンドル / サブクラス化もお任せ
				ti.hwnd = hDlg;	// ツールチップを持つウィンドウ

				ti.lpszText = ml_col1;// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_EDIT1);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_STATIC1);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = ml_col2;// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_EDIT2);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_STATIC2);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "ファイルを一覧の中から選び、左の編集ボックスに代入します";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FILE_BROWSE0);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FILE_BROWSE);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "フォルダを一覧の中から選び、左の編集ボックスに代入します";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FOLDER_BROWSE0);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FOLDER_BROWSE);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "入力した内容で決定し、ダイアログを閉じます";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDOK);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "入力した内容をキャンセルし、ダイアログを閉じます";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDCANCEL);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
			}

			// ダイアログのコントロールのアンカーを登録
			sizedlg = new SIZEDLG(hDlg, dlgitems_ml);
			sizedlg->SetMinMaxInfo(sizedlg->GetDefWidth(), sizedlg->GetDefHeight(), -1, -1);
			return TRUE;

		case WM_DESTROY:
			// アイコンが書かれているボタンを破棄
			DestroyWindow(GetDlgItem(hDlg, IDC_FILE_BROWSE0));
			DestroyWindow(GetDlgItem(hDlg, IDC_FOLDER_BROWSE0));
			DestroyWindow(GetDlgItem(hDlg, IDC_FILE_BROWSE));
			DestroyWindow(GetDlgItem(hDlg, IDC_FOLDER_BROWSE));

			// リサイズのための情報を破棄
			if (sizedlg) {
				delete sizedlg;
				sizedlg = NULL;
			}
			return TRUE;

		case WM_GETMINMAXINFO:
			// ダイアログの最小サイズを決める
			if (sizedlg) {
				sizedlg->GetMinMaxInfo(lParam);
			}
			return TRUE;

		case WM_SIZE:
			// リサイズ
			if (sizedlg) {
				sizedlg->Resize(1);
			}
			return TRUE;

		case WM_DROPFILES: // 編集ボックスがファイルをドロップされた
			{
				int n; // ドロップされたファイルの数
				int i; // カウンタ
				int len; // 編集ボックス内にすでに存在する文字列のバイト数
				char fname[MAX_PATH*2];
				char *buf;
				POINT pt;
				HWND hEdit; // これから代入しようとする編集ボックス
				RECT rt;
				int nBox; // 何番目の編集ボックスへのドロップか？

				GetCursorPos( &pt );
				GetWindowRect(GetDlgItem(hDlg, IDC_STATIC2), &rt);

				// ドロップしたときのマウスの位置が、２つめのスタティックテキストよりも上だったら
				if ( pt.y < rt.top ) { // １つめの編集ボックスへのドロップとみなす
					hEdit = GetDlgItem(hDlg, IDC_EDIT1);
					nBox = 0;
				}
				else {  // そうでなければ、２つめの編集ボックスへのドロップとみなす
					hEdit = GetDlgItem(hDlg, IDC_EDIT2);
					nBox = 1;
				}

				n = DragQueryFile((HDROP)wParam, (UINT)-1, NULL, 0);
				for(i=0 ; i<n ; i++) {
					if (_countof(fname) > DragQueryFile((HDROP)wParam, i, fname, _countof(fname))) {
                        len = GetWindowTextLength( hEdit );
						if ( len > 0 ) { // すでに文字列が入っていた場合は、そこにスペースor改行を加えてから追加
							buf = (char *)malloc( len + lstrlen(fname) + 3 );
							if ( buf ) {
								GetWindowText( hEdit, buf, len+1 );
								lstrcat(buf, nBox == 1 ? "\r\n" : " ");
								lstrcat(buf, fname);
								SetWindowText(hEdit, buf);
								safefree( buf );
							}
						}
						else { // まだ文字列が入っていない場合は、そのまま設定
                            SetWindowText(hEdit, fname);
						}
					}
				}
				DragFinish((HDROP)wParam);
			}
			break;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDOK:
					{
						char *ml2_itemname = NULL, *ml2_itemdata = NULL;
						int len;

						// 第1項目の値がなければエラー
						len = GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT1));
						if ( ml_col1 != NULL && len == 0 ) {
							MessageBox(hDlg, "第1項目に何も入力されていません。", "チェック", MB_OK | MB_ICONSTOP);
							return TRUE;
						}

						// 第1項目のデータを取得
						ml2_itemname = (char *)malloc( len+1 );
						if ( ml2_itemname == NULL ) {
							MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
							return TRUE;
						}
                        GetDlgItemText(hDlg, IDC_EDIT1, ml2_itemname, len+1);

						// バッファのポインタをコピー(その前に旧バッファは解放)
						safefree( ml_itemname );
						ml_itemname = ml2_itemname;

						len = GetWindowTextLength( GetDlgItem(hDlg, IDC_EDIT2) );
						ml2_itemdata = (char *)malloc( len+1 );
						if ( ml2_itemdata ) {
                            GetDlgItemText(hDlg, IDC_EDIT2, ml2_itemdata, len+1);
							safefree( ml_itemdata );
							ml_itemdata = ml2_itemdata;
							EndDialog( hDlg, IDOK );
						}
						else {
							MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
						}
						return TRUE;
					}

				case IDCANCEL:
					EndDialog( hDlg, IDCANCEL );
					return TRUE;

				case IDC_FILE_BROWSE0:
					{
						char fname[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT1, fname, _countof(fname));
						if ( openDialog( hDlg, FILETYPES, fname, _countof(fname), "ファイルの選択", NULL ) ) {
							SetDlgItemText(hDlg, IDC_EDIT1, fname);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT1) );
						}
						return TRUE;
					}

				case IDC_FOLDER_BROWSE0:
					{
						char chPutFolder[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT1, chPutFolder, _countof(chPutFolder));
						if ( browseFolder( hDlg, chPutFolder, "フォルダの選択" ) ) {
							SetDlgItemText(hDlg, IDC_EDIT1, chPutFolder);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT1) );
						}
						return TRUE;
					}

				case IDC_FILE_BROWSE:
					{
						char fname[MAX_PATH*2] = "";
						HWND hEdit = GetDlgItem(hDlg, IDC_EDIT2);
						
						GetWindowText(hEdit, fname, _countof(fname));
						if ( openDialog( hDlg, FILETYPES, fname, _countof(fname), "ファイルの選択", NULL ) ) {
	                        int len = GetWindowTextLength( hEdit );
							if ( len > 0 ) { // すでに文字列が入っていた場合は、そこに改行を加えてから追加
								char *buf = (char *)malloc( len + lstrlen(fname) + 3 );
								if ( buf ) {
									GetWindowText( hEdit, buf, len+1 );
									lstrcat(buf, "\r\n");
									lstrcat(buf, fname);
									SetWindowText(hEdit, buf);
									safefree( buf );
								}
							}
							else { // まだ文字列が入っていない場合は、そのまま設定
								SetWindowText(hEdit, fname);
							}

							SetFocus(hEdit);
						}
						return TRUE;
					}

				case IDC_FOLDER_BROWSE:
					{
						char chPutFolder[MAX_PATH*2] = "";
						HWND hEdit = GetDlgItem(hDlg, IDC_EDIT2);

						GetWindowText(hEdit, chPutFolder, _countof(chPutFolder));
						if ( browseFolder( hDlg, chPutFolder, "フォルダの選択" ) ) {
	                        int len = GetWindowTextLength( hEdit );
							if ( len > 0 ) { // すでに文字列が入っていた場合は、そこに改行を加えてから追加
								char *buf = (char *)malloc( len + lstrlen(chPutFolder) + 3 );
								if ( buf ) {
									GetWindowText( hEdit, buf, len+1 );
									lstrcat(buf, "\r\n");
									lstrcat(buf, chPutFolder);
									SetWindowText(hEdit, buf);
									safefree( buf );
								}
							}
							else { // まだ文字列が入っていない場合は、そのまま設定
								SetWindowText(hEdit, chPutFolder);
							}

							SetFocus(hEdit);
						}
						return TRUE;
					}
			}
			break;
	}
    return FALSE;
}

// ------------------------------------------------------------------------------------------------
// ValueList(key:1-value:n)
// ------------------------------------------------------------------------------------------------
int m_n, m_columns;
char **m_means;

// KeyListの追加・編集 ( n:編集したい項目番号。-1を指定すると新規作成 )
bool lv_edititem_n( HWND hWndParent, HWND hwndListView, int n, char **means )
{
	ml_hListView = hwndListView;
	m_n = n;
	m_means = means;

	for(m_columns=0 ; means[m_columns] ; ++m_columns)
		;

	return (IDOK == DialogBox(hInst, (LPCTSTR)IDD_EDIT_LV2, hWndParent, (DLGPROC)lvneDialog));
}

// KeyListの追加・編集ダイアログ
static LRESULT CALLBACK lvneDialog( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	static HWND *edit_controls = NULL;
	static HWND *hBrowseButtons = NULL;
	static SIZEDLG *sizedlg;

	switch( message ) {
		case WM_INITDIALOG:
			edit_controls = NULL;
			hBrowseButtons = NULL;
			ml_itemname = NULL;

			// 現在は、ダイアログは MS P ゴシックで固定
			// SetChildWindowFont( hDlg );

			// ダイアログのアイコン設定
			SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIconInputText);

			if ( m_n == -1 ) {
				SetWindowText(hDlg, "新規");
			}
			{
				HWND hTooltip;
				TOOLINFO ti;

				if (NULL == (hTooltip=CreateWindow(TOOLTIPS_CLASS,"",TTS_ALWAYSTIP,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,hDlg,NULL,hInst,NULL)))
					return NULL;

				ZeroMemory(&ti, sizeof(ti));
				ti.cbSize = sizeof(TOOLINFO);
				ti.uFlags = TTF_IDISHWND | TTF_SUBCLASS;// uIDはツールチップを表示するウィンドウを識別するハンドル / サブクラス化もお任せ
				ti.hwnd = hDlg;	// ツールチップを持つウィンドウ

				ti.lpszText = "ファイルを一覧の中から選び、左の編集ボックスに代入します";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FILE_BROWSE0);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FILE_BROWSE);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "フォルダを一覧の中から選び、左の編集ボックスに代入します";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FOLDER_BROWSE0);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDC_FOLDER_BROWSE);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "入力した内容で決定し、ダイアログを閉じます";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDOK);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				ti.lpszText = "入力した内容をキャンセルし、ダイアログを閉じます";// チップ
				ti.uId=(UINT_PTR)GetDlgItem(hDlg, IDCANCEL);
				SendMessage(hTooltip,TTM_ADDTOOL,0,(LPARAM)&ti);

				if ( m_n >= 0 ) { // 「新規作成」でないことを確認
					char *pbuf = lvGetItemString( ml_hListView, m_n, 0 );

					if ( pbuf ) {
						SetDlgItemText( hDlg, IDC_EDIT1, pbuf ); // edit controlに編集する文字列をセット
						ml_itemname = pbuf; // [OK]が押されたときに比較するのでとっておく
					}
					else {
						MessageBox( hDlg, "編集を開始するためのメモリが足りません。", "エラー", MB_OK | MB_ICONSTOP );
						EndDialog( hDlg, IDCANCEL );
                        return TRUE;
					}
				}
				else {
					ml_itemname = NULL;
				}
				SetDlgItemText( hDlg, IDC_STATIC1, m_means[0] ); // static controlに意味をセット

				ti.lpszText = m_means[0];// チップ
				ti.uId = (UINT_PTR)GetDlgItem(hDlg, IDC_EDIT1);
				SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
				ti.uId = (UINT_PTR)GetDlgItem(hDlg, IDC_STATIC1);
				SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);

				SendDlgItemMessage(hDlg, IDC_FILE_BROWSE0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);
				SendDlgItemMessage(hDlg, IDC_FOLDER_BROWSE0, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);
				SendDlgItemMessage(hDlg, IDC_FILE_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);
				SendDlgItemMessage(hDlg, IDC_FOLDER_BROWSE, BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);

				if ( m_columns == 1 ) { // 1 staticとeditを一つずつ消す
					DestroyWindow( GetDlgItem(hDlg, IDC_STATIC2) );
					DestroyWindow( GetDlgItem(hDlg, IDC_EDIT2) );
					DestroyWindow( GetDlgItem(hDlg, IDC_FILE_BROWSE) );
					DestroyWindow( GetDlgItem(hDlg, IDC_FOLDER_BROWSE) );
				}
				else if ( m_columns == 2 ) {
					// 編集ボックス・チューザのための配列は、特に作らない(NULLになっているので、それを利用)
					if ( m_n >= 0 ) { // 「新規作成」でないことを確認
						char *pbuf = lvGetItemString( ml_hListView, m_n, 1 );

						if ( pbuf ) {
							SetDlgItemText( hDlg, IDC_EDIT2, pbuf ); // edit controlに編集する文字列をセット
							safefree( pbuf );
						}
						else {
							MessageBox( hDlg, "編集を開始するためのメモリが足りません。", "エラー", MB_OK | MB_ICONSTOP );
							EndDialog( hDlg, IDCANCEL );
							return TRUE;
						}
					}
					SetDlgItemText( hDlg, IDC_STATIC2, m_means[1] ); // static controlに意味をセット

					ti.lpszText = m_means[1];// チップ
					ti.uId = (UINT_PTR)GetDlgItem(hDlg, IDC_EDIT2);
					SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
					ti.uId = (UINT_PTR)GetDlgItem(hDlg, IDC_STATIC2);
					SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
				}
				else { // 3以上（新しくstaticとeditを作らなければならない）
					RECT  rc, rc2, rc3, rc4;
					POINT pt;	// ScreenToClient() 用
					int   height; // 1つのアイテムが占める高さ（static+edit+空白）
					int   height_static; // static control の高さ
					int   height_edit;	// edit control の高さ
					int   width; // edit controlの横幅
					int   width_static; // static controlの横幅
					int   x_control; // 各編集コントロールの左の座標
					int   x_control_static; // 各スタティックコントロールの左の座標
					int   y_control; // 2番目のstatic controlの上の座標
					int   x_button1; // ファイル参照ボタンの左座標
					int   x_button2; // フォルダ参照ボタンの左座標
					int   width_button; // 参照ボタンの幅
					int   y_edit; // 2番目のstatic controlとedit controlの上の座標の差
					LONG_PTR  lEditStyle; // 編集コントロールのスタイル
					LONG_PTR  lEditStyleEx; // 編集コントロールの拡張スタイル


					// 2番目のstaticとeditの設定
					if ( m_n >= 0 ) { // 「新規作成」でないことを確認
						char *pbuf = lvGetItemString( ml_hListView, m_n, 1 );

						if ( pbuf ) {
							SetDlgItemText( hDlg, IDC_EDIT2, pbuf ); // edit controlに編集する文字列をセット
							safefree( pbuf );

							ti.lpszText = m_means[1];// チップ
							ti.uId = (UINT_PTR)GetDlgItem(hDlg, IDC_EDIT2);
							SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
							ti.uId = (UINT_PTR)GetDlgItem(hDlg, IDC_STATIC2);
							SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
						}
						else {
							MessageBox( hDlg, "編集を開始するためのメモリが足りません。", "エラー", MB_OK | MB_ICONSTOP );
							EndDialog( hDlg, IDCANCEL );
							return TRUE;
						}
					}
					SetDlgItemText( hDlg, IDC_STATIC2, m_means[1] ); // static controlに意味をセット

					// ウィンドウの高さを必要な分だけ縦に伸ばす。
					// 伸ばすサイズを算出
					// まずは、static1とstatic2の間の大きさを測定
					GetWindowRect( GetDlgItem(hDlg, IDC_STATIC1), &rc );
					GetWindowRect( GetDlgItem(hDlg, IDC_STATIC2), &rc2 );
					GetWindowRect( GetDlgItem(hDlg, IDC_FILE_BROWSE), &rc3 );
					GetWindowRect( GetDlgItem(hDlg, IDC_FOLDER_BROWSE), &rc4 );
					height = rc2.top - rc.top;

					// static controlの高さを計算
					height_static = rc.bottom - rc.top;

					// static controlの左側の座標
					pt.x = rc.left;
					pt.y = rc.top;
					ScreenToClient(hDlg, &pt);
					x_control_static = pt.x;

					// edit controlの高さを計算
					GetWindowRect( GetDlgItem(hDlg, IDC_EDIT2), &rc );
					height_edit = rc.bottom - rc.top;

					// 各コントロールの幅を計算
					width = rc.right - rc.left;				// 編集コントロールの幅
					width_static = rc2.right - rc2.left;		// 説明用のコントロールの幅
					width_button = rc3.right - rc3.left;

					// 各編集コントロールの左側の座標
					pt.x = rc.left;
					pt.y = rc.top;
					ScreenToClient(hDlg, &pt);
					x_control = pt.x;

					pt.x = rc3.left;
					pt.y = rc3.top;
					ScreenToClient(hDlg, &pt);
					x_button1 = pt.x;

					pt.x = rc4.left;
					pt.y = rc4.top;
					ScreenToClient(hDlg, &pt);
					x_button2 = pt.x;

					// 2番目のstatic controlの上の座標
					pt.x = rc2.left;
					pt.y = rc2.top;
					ScreenToClient(hDlg, &pt);
					y_control = pt.y;

					// 2番目のstatic controlとedit controlの上の座標の差
					GetWindowRect( GetDlgItem(hDlg, IDC_EDIT2), &rc );
					y_edit = rc.top - rc2.top;

					// 編集コントロールのスタイル・拡張スタイルを読み出し
					lEditStyle = GetWindowLongPtr(GetDlgItem(hDlg, IDC_EDIT2), GWL_STYLE);
					lEditStyleEx = GetWindowLongPtr(GetDlgItem(hDlg, IDC_EDIT2), GWL_EXSTYLE);

					// 3番目以降のstatic controlとedit control
					int i;

					edit_controls = (HWND *)calloc( sizeof(HWND), m_columns-2 );
					hBrowseButtons = (HWND *)calloc( sizeof(HWND), (m_columns-1)*2 );
					if ( edit_controls && hBrowseButtons ) {
						hBrowseButtons[0] = GetDlgItem( hDlg, IDC_FILE_BROWSE );
						hBrowseButtons[1] = GetDlgItem( hDlg, IDC_FOLDER_BROWSE ); 
						HWND hStaticCtrl;

						for(i=0 ; i<m_columns-2 ; i++) {
							// static controlの作成
							hStaticCtrl = CreateWindow( WC_EDIT, m_means[i+2], ES_AUTOHSCROLL|ES_READONLY|WS_CHILD|WS_VISIBLE|SS_LEFT, x_control_static, y_control+height*(i+1), width_static, height_static, hDlg, (HMENU)IDNO, hInst, NULL);
							if ( hStaticCtrl )
								SendMessage(hStaticCtrl, WM_SETFONT, (WPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)FALSE);

							char *pbuf = NULL;

							if (m_n >= 0) { // 新規項目の作成でなかったら
								pbuf = lvGetItemString( ml_hListView, m_n, i+2 );
								if ( pbuf == NULL ) {
									MessageBox( hDlg, "編集を開始するためのメモリが足りません。", "エラー", MB_OK | MB_ICONSTOP );
									EndDialog( hDlg, IDCANCEL );
									return TRUE;				
								}
							}
								
							// edit controlの作成
							edit_controls[i] = CreateWindowEx( (DWORD)lEditStyleEx, WC_EDIT, pbuf?pbuf:"", (DWORD)lEditStyle, x_control, y_control+height*(i+1)+y_edit, width, height_edit, hDlg, (HMENU)IDNO, hInst, NULL);
							if ( edit_controls[i] ) {
								SendMessage(edit_controls[i], WM_SETFONT, (WPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)FALSE);

								ti.lpszText = m_means[i+2];// チップ
								ti.uId = (UINT_PTR)edit_controls[i];
								SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
								ti.uId = (UINT_PTR)hStaticCtrl;
								SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);

								// BS_ICON スタイル付きでCreateWindow
								hBrowseButtons[2+i*2] = CreateWindow( WC_BUTTON, "ファイルの参照...", WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_ICON, x_button1, y_control+height*(i+1)+y_edit, width_button, height_edit, hDlg, (HMENU)IDC_FILE_BROWSE, hInst, NULL);
								if ( hBrowseButtons[i*2] ) {
									SendMessage(hBrowseButtons[2+i*2], WM_SETFONT, (WPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)FALSE);
									SendMessage(hBrowseButtons[2+i*2], BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFileBrowse);

									ti.uId = (UINT_PTR)hBrowseButtons[2+i*2];
									ti.lpszText = "ファイルを一覧の中から選び、左の編集ボックスに代入します";// チップ
									SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
								}

								hBrowseButtons[2+i*2+1] = CreateWindow( WC_BUTTON, "フォルダの参照...", WS_CHILD|WS_VISIBLE|WS_TABSTOP|BS_PUSHBUTTON|BS_ICON, x_button2, y_control+height*(i+1)+y_edit, width_button, height_edit, hDlg, (HMENU)IDC_FOLDER_BROWSE, hInst, NULL);
								if ( hBrowseButtons[i*2+1] ) {
									SendMessage(hBrowseButtons[2+i*2+1], WM_SETFONT, (WPARAM)(HFONT)GetStockObject(DEFAULT_GUI_FONT), (LPARAM)FALSE);
									SendMessage(hBrowseButtons[2+i*2+1], BM_SETIMAGE, IMAGE_ICON, (LPARAM)hIconFolderBrowse);

									ti.uId = (UINT_PTR)hBrowseButtons[2+i*2+1];
									ti.lpszText = "フォルダを一覧の中から選び、左の編集ボックスに代入します";// チップ
									SendMessage(hTooltip, TTM_ADDTOOL, 0, (LPARAM)&ti);
								}
							}
						}
						GetWindowRect(hDlg, &rc);
						SetWindowPos(hDlg, 0, 0, 0, rc.right-rc.left, rc.bottom-rc.top + height*i, SWP_NOMOVE | SWP_NOOWNERZORDER);

						// OKボタンの移動
						GetWindowRect( GetDlgItem( hDlg, IDOK ), &rc );
						pt.x = rc.left;
						pt.y = rc.top;
						ScreenToClient( hDlg, &pt );
						SetWindowPos(GetDlgItem( hDlg, IDOK ), HWND_BOTTOM, pt.x, pt.y + height*i, 0, 0, SWP_NOSIZE );
						
						// Caneclボタンの移動
						GetWindowRect( GetDlgItem( hDlg, IDCANCEL ), &rc );
						pt.x = rc.left;
						pt.y = rc.top;
						ScreenToClient( hDlg, &pt );
						SetWindowPos(GetDlgItem( hDlg, IDCANCEL ), HWND_BOTTOM, pt.x, pt.y + height*i, 0, 0, SWP_NOSIZE );
					}
				}
			}

			// ウィンドウをクライアントエリア中央へ移動する
			{ // 画面中央にダイアログを移動させる
				RECT rct;

				GetWindowRect(hDlg, &rct);	// 現在のダイアログの位置を得て、サイズを計算する
				rct.right -= rct.left;
				rct.bottom -= rct.top;
				rct.left = (GetSystemMetrics(SM_CXMAXIMIZED) - rct.right) / 2;
				rct.top = (GetSystemMetrics(SM_CYMAXIMIZED) - rct.bottom) / 2;
				MoveWindow(hDlg, rct.left, rct.top, rct.right, rct.bottom, TRUE);
			}

			// ダイアログのコントロールのアンカーを登録
			sizedlg = new SIZEDLG(hDlg, dlgitems);
			if (sizedlg) {
				int i;
				// 追加の編集ボックス・選択ボタンをリサイズクラスに登録する
				for(i=0 ; i<m_columns-2 ; ++i) {
					sizedlg->Add(edit_controls [i], ANCHOR_TOPLEFTRIGHT);
				}
				for(i=1 ; i<m_columns-1 ; ++i) {
					sizedlg->Add(hBrowseButtons[i*2  ], ANCHOR_TOPRIGHT);
					sizedlg->Add(hBrowseButtons[i*2+1], ANCHOR_TOPRIGHT);
				}

				// 縦サイズはリサイズしないように設定
				sizedlg->SetMinMaxInfo(sizedlg->GetDefWidth(), sizedlg->GetDefHeight(), -1, sizedlg->GetDefHeight());
			}
			return TRUE;

		case WM_DESTROY:
			// 編集ボックスのハンドルが並べられたメモリを破棄
			safefree( edit_controls );
			// アイコンが書かれているボタンを破棄
			DestroyWindow(GetDlgItem(hDlg, IDC_FILE_BROWSE0));
			DestroyWindow(GetDlgItem(hDlg, IDC_FOLDER_BROWSE0));
			if ( hBrowseButtons ) {
				for(int i=0 ; i<(m_columns-1)*2 ; ++i) {
					if ( hBrowseButtons[i] ) {
						DestroyWindow( hBrowseButtons[i] );
					}
				}
				safefree( hBrowseButtons );
			}

			// リサイズのための情報を破棄
			if (sizedlg) {
				delete sizedlg;
				sizedlg = NULL;
			}
			return TRUE;

		case WM_GETMINMAXINFO:
			// ダイアログの最小サイズを決める
			if (sizedlg) {
				sizedlg->GetMinMaxInfo(lParam);
			}
			return TRUE;

		case WM_SIZE:
			// リサイズ
			if (sizedlg) {
				sizedlg->Resize(1);
			}
			return TRUE;

		case WM_DROPFILES: // 編集ボックスがファイルをドロップされた
			{
				int n; // ドロップされたファイルの数
				int i; // カウンタ
				int len; // 編集ボックス内にすでに存在する文字列のバイト数
				char fname[MAX_PATH*2];
				char *buf;
				POINT pt;
				HWND hEdit = NULL; // これから代入しようとする編集ボックス
				RECT rt;

				GetCursorPos( &pt );

				// ドロップしたときのマウスの位置で、どのエディットボックスへのドロップかを判定
				if ( m_columns == 1 ) {
					// １つしか編集ボックスがない場合
					hEdit = GetDlgItem(hDlg, IDC_EDIT1);
				}
				else if ( m_columns == 2 ) { // ２つの編集ボックスがある場合
					GetWindowRect(GetDlgItem(hDlg, IDC_STATIC2), &rt);
					// ドロップしたときのマウスの位置が、２つめのスタティックテキストよりも上だったら
					if ( pt.y < rt.top ) { // １つめの編集ボックスへのドロップとみなす
						hEdit = GetDlgItem(hDlg, IDC_EDIT1);
					}
					else {  // そうでなければ、２つめの編集ボックスへのドロップとみなす
						hEdit = GetDlgItem(hDlg, IDC_EDIT2);
					}
				}
				else { // ３つ以上の編集ボックスがある場合
					// スタティックテキストの位置を基準に、どの編集ボックスへのドロップかを判定する
					for(i=m_columns-2-1 ; i>=0 ; i--) {
						GetWindowRect(edit_controls[i], &rt);
						if ( pt.y >= rt.top ) {
							hEdit = edit_controls[i];
                            break;
						}
					}
					if ( !hEdit ) {
						GetWindowRect(GetDlgItem(hDlg, IDC_STATIC2), &rt);
						// ドロップしたときのマウスの位置が、２つめのスタティックテキストよりも上だったら
						if ( pt.y < rt.top ) { // １つめの編集ボックスへのドロップとみなす
							hEdit = GetDlgItem(hDlg, IDC_EDIT1);
						}
						else {  // そうでなければ、２つめの編集ボックスへのドロップとみなす
							hEdit = GetDlgItem(hDlg, IDC_EDIT2);
						}
					}
				}

				n = DragQueryFile((HDROP)wParam, (UINT)-1, NULL, 0);
				for(i=0 ; i<n ; i++) {
					if (_countof(fname) > DragQueryFile((HDROP)wParam, i, fname, MAX_PATH)) {
                        len = GetWindowTextLength( hEdit );
						if ( len > 0 ) { // すでに文字列が入っていた場合は、そこにスペースを加えてから追加
							buf = (char *)malloc( len + lstrlen(fname) + 2 );
							if ( buf ) {
								GetWindowText( hEdit, buf, len+1 );
								lstrcat(buf, " ");
								lstrcat(buf, fname);
								SetWindowText(hEdit, buf);
								safefree( buf );
							}
						}
						else { // まだ文字列が入っていない場合は、そのまま設定
                            SetWindowText(hEdit, fname);
						}
					}
				}
				SetFocus(hEdit);

				DragFinish((HDROP)wParam);
			}
			break;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDOK:
					{
						char *ml2_itemname;
						int len;

						len = GetWindowTextLength(GetDlgItem(hDlg, IDC_EDIT1));
						if ( len == 0 ) {
							MessageBox(hDlg, "第1項目に何も入力されていません。","チェック",MB_OK | MB_ICONSTOP);
							return TRUE;
						}

						// 第1項目を読み出し
						ml2_itemname = (char *)calloc( len+1, 1 );
						if ( ml2_itemname == NULL ) {
							MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
							return TRUE;
						}
						GetDlgItemText(hDlg, IDC_EDIT1, ml2_itemname, len+1);

						if ( ml_itemname && _stricmp(ml2_itemname, ml_itemname) == 0 )
							;// 第1項目に変化がなければ、第1項目についてはそのまま
						else {// 変化がある場合は、他の第1項目との重複がないかチェックする
							int i, n;
							char *iname;

							iname = (char *)malloc( len+2 );// 現在の第1項目より一文字多めに調べればよい
							if ( iname ) {
								n = ListView_GetItemCount( ml_hListView );
								
								for(i=0 ; i<n ; i++) {
									ListView_GetItemText( ml_hListView, i, 0, iname, len+2 );
									if ( _stricmp(iname, ml2_itemname) == 0 ) {
										MessageBox(hDlg, "第1項目が、リスト内の他の項目と重複しています。","チェック",MB_OK | MB_ICONSTOP);
										safefree(ml2_itemname);
										safefree(iname);
										return TRUE;
									}
								}
							}
							else {
								safefree(ml2_itemname);
								MessageBox(hDlg, "データの保存に必要なメモリを確保できません。", "エラー", MB_OK | MB_ICONSTOP);
								return TRUE;
							}
						}

						// 旧バッファ・新バッファは解放
						safefree(ml_itemname);
						safefree(ml2_itemname);
						{
							int i;

							if ( m_n == -1 ) { // 新規作成
								LVITEM lvitem;

								m_n = ListView_GetItemCount( ml_hListView );
								ListView_SetItemCount(ml_hListView, m_n+1);
								lvitem.mask = LVIF_TEXT;
								lvitem.iItem = m_n;
								lvitem.iSubItem = 0;
								lvitem.pszText = "";
								ListView_InsertItem(ml_hListView, &lvitem);
								ListView_SetItemState(ml_hListView, m_n, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
							}

							for(i=0 ; i<m_columns ; i++) {
								HWND hEdit;
								int  bufsize;
								char *pbuf;

								if ( i == 0 ) {
									hEdit = GetDlgItem(hDlg, IDC_EDIT1);
								}
								else if ( i == 1 ) {
									hEdit = GetDlgItem(hDlg, IDC_EDIT2);
								}
								else {
									hEdit = edit_controls[i-2];
								}

								bufsize = GetWindowTextLength(hEdit);
								pbuf = (char *)malloc( bufsize+1 );
								if ( pbuf ) {
									GetWindowText(hEdit, pbuf, bufsize+1);
									ListView_SetItemText( ml_hListView, m_n, i, pbuf);
									safefree(pbuf);
								}
								else {
									MessageBox(hDlg, "データの保存に必要なメモリを確保できませんでした。一部のデータは失われます。", "エラー", MB_OK | MB_ICONSTOP);
									return TRUE;
								}
							}
						}

						EndDialog( hDlg, IDOK );
						return TRUE;
					}

				case IDCANCEL:
					EndDialog( hDlg, IDCANCEL );
					return TRUE;

				case IDC_FILE_BROWSE0:
					{
						char fname[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT1, fname, _countof(fname));
						if ( openDialog( hDlg, FILETYPES, fname, _countof(fname), "ファイルの選択", NULL ) ) {
							SetDlgItemText(hDlg, IDC_EDIT1, fname);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT1) );
						}
						return TRUE;
					}

				case IDC_FOLDER_BROWSE0:
					{
						char chPutFolder[MAX_PATH*2] = "";

						GetDlgItemText(hDlg, IDC_EDIT1, chPutFolder, _countof(chPutFolder));
						if ( browseFolder( hDlg, chPutFolder, "フォルダの選択" ) ) {
							SetDlgItemText(hDlg, IDC_EDIT1, chPutFolder);
							SetFocus( GetDlgItem(hDlg, IDC_EDIT1) );
						}
						return TRUE;
					}

				case IDC_FILE_BROWSE:
					{
						char fname[MAX_PATH*2] = "";
						int  i=0;
						HWND hEdit = NULL;

						if ( hBrowseButtons == NULL || hBrowseButtons[0] == (HWND)lParam ) {
							hEdit = GetDlgItem(hDlg, IDC_EDIT2);
							i = 0;
						}
						else {
							for(i=1 ; i<m_columns-1 ; i++) {
								if ( hBrowseButtons[i*2] == (HWND)lParam ) {
									hEdit = edit_controls[i-1];
									break;
								}
							}
						}
						if ( i < m_columns-1 ) {
							GetWindowText(hEdit, fname, _countof(fname)); // デフォルトを取得
							if ( openDialog( hDlg, FILETYPES, fname, _countof(fname), "ファイルの選択", NULL ) ) {
								SetWindowText( hEdit, fname );
								SetFocus( hEdit );
							}
						}
						return TRUE;
					}

				case IDC_FOLDER_BROWSE:
					{
						char chPutFolder[MAX_PATH*2] = "";
						HWND hEdit = NULL;
						int i = 0;

						if ( hBrowseButtons == NULL || hBrowseButtons[1] == (HWND)lParam ) {
							hEdit = GetDlgItem(hDlg, IDC_EDIT2);
						}
						else {
							for(i=1 ; i<m_columns-1 ; i++) {
								if ( hBrowseButtons[i*2+1] == (HWND)lParam ) {
									hEdit = edit_controls[i-1];
									break;
								}
							}
						}

						if ( i < m_columns-1 ) {
							GetWindowText(hEdit, chPutFolder, _countof(chPutFolder)); // デフォルトを取得
							if( browseFolder( hDlg, chPutFolder, "フォルダの選択" ) ) {
								SetWindowText(hEdit, chPutFolder);
								SetFocus( hEdit );
							}
						}
						return TRUE;
					}
			}
			break;
	}
    return FALSE;
}
