#include "stdafx.h"

#include "context.h"
#include "openarc.h"

// 選択中DLLの情報
static const char *dllexts[] = {".lzh", ".zip", ".7z", NULL};

// ダイアログのアンカー等に関する情報
const DLGITEM dlgitems[] = {
	{IDC_STATIC1,    ANCHOR_TOPLEFT},
	{IDC_RADIO_LZH,  ANCHOR_TOPLEFT},
	{IDC_RADIO_ZIP,  ANCHOR_TOPLEFT},
	{IDC_RADIO_7Z,   ANCHOR_TOPLEFT},
	{IDC_STATIC2,    ANCHOR_TOPLEFT},
	{IDC_STATIC4,    ANCHOR_TOPRIGHT},
	{IDC_STATIC5,    ANCHOR_TOPRIGHT},
	{IDC_SELFORM_LZH,ANCHOR_TOPRIGHT},
	{IDC_SELFORM_ZIP,ANCHOR_TOPRIGHT},
	{IDC_SELFORM_7Z, ANCHOR_TOPRIGHT},
	{IDC_CHECK_MT,   ANCHOR_TOPRIGHT},
	{IDC_EDIT1,      ANCHOR_TOPLEFTRIGHT},
	{IDC_BUTTON_BROWSE,   ANCHOR_TOPRIGHT},
	{IDC_STATIC3,    ANCHOR_TOPLEFT},
	{IDC_EDIT_FILES, ANCHOR_CENTER},
	{IDC_BUTTON_CLEAR,ANCHOR_TOPRIGHT},
	{IDC_BUTTON_BROWSE_FILE,   ANCHOR_BOTTOMRIGHT},
	{IDC_BUTTON_BROWSE_FOLDER, ANCHOR_BOTTOMRIGHT},
	{IDC_CHECK_NOTCLOSE, ANCHOR_BOTTOMLEFT},
	{IDC_CHECK_FINISHMESSAGE, ANCHOR_BOTTOMLEFT},
	{IDC_COMBO_SHUTDOWN, ANCHOR_BOTTOMLEFT},
	{IDC_STATIC_PASSWORD, ANCHOR_BOTTOMLEFTRIGHT},
	{IDC_EDIT_PASSWORD, ANCHOR_BOTTOMLEFTRIGHT},
	{IDOK,   ANCHOR_BOTTOMRIGHT},
	{IDCANCEL, ANCHOR_BOTTOMRIGHT},
	{IDHELP, ANCHOR_BOTTOMRIGHT},
	{0,0}
};

// ボタン等の上にマウスを乗せたときの情報
static const struct DEFTOOLTIP oa_tooltips[] = {
	{IDC_RADIO_LZH, "Unlha32.dllを用いて、lzh形式の圧縮ファイルの作成を行います。圧縮後のファイル名の拡張子をexeにすれば、自己解凍書庫も作成可能です"},
	{IDC_RADIO_ZIP, "zip32j.dll, zip32.dllを用いて、zip形式の圧縮ファイルの作成を行います。圧縮後のファイル名の拡張子をexeにすれば、自己解凍書庫も作成可能です"},
	{IDC_RADIO_7Z,  "7-zip32.dllを用いて、7-zipたはzip形式の圧縮ファイルの作成を行います。圧縮後のファイル名の拡張子をexeにすれば、自己解凍書庫も作成可能です"},
	{IDC_SELFORM_LZH,"圧縮形式を選択します。通常は「lh5(標準)」のみを選んでください。特別な事情があるときのみ、他を選択して下さい"},
	{IDC_SELFORM_ZIP,"圧縮率を選択します。一般的に圧縮率が高くなれば、処理時間も長くなります"},
	{IDC_SELFORM_7Z, "圧縮率を選択します。一般的に圧縮率が高くなれば、処理時間も長くなります"},
	{IDC_CHECK_MT,  "利用可能であれば、マルチスレッドでの圧縮処理を行います"},
	{IDC_BUTTON_BROWSE, "圧縮後のファイル名入力するためのをダイアログを開きます"},
	{IDC_BUTTON_CLEAR,         "圧縮対象ファイルの入力欄をクリアします"},
	{IDC_BUTTON_BROWSE_FILE,   "圧縮対象のファイルを一覧から選択できます"},
	{IDC_BUTTON_BROWSE_FOLDER, "圧縮対象のフォルダを一覧から選択できます"},
	{IDC_EDIT_PASSWORD, "zipまたは7-zip形式のファイル(自己解凍書庫を除く)をパスワード付きで作成する場合に、パスワードを入力します"},
	{IDC_CHECK_NOTCLOSE, "圧縮完了後に、ダイアログの入力内容を再利用して次の実行ができます"},
	{IDC_CHECK_FINISHMESSAGE, "圧縮処理が正常終了した場合もメッセージダイアログを表示します"},
	{IDC_COMBO_SHUTDOWN, "圧縮終了時の動作を設定します"},
	{IDOK,     "圧縮処理を開始します"},
	{IDCANCEL, "このダイアログを閉じます"},
	{IDHELP,   "このダイアログに関するヘルプを表示します"},
	{0,0}};

// 圧縮ダイアログの圧縮先ファイル名の履歴管理
static ComboboxQueue *cbq;

// OpenArchiverのダイアログ中で、現在選択中のDLLを返す
static int selectedDll( HWND hDlg )
{
	if ( BST_CHECKED == SendDlgItemMessage(hDlg, IDC_RADIO_ZIP, BM_GETCHECK, 0, NULL) ) {
		return OET_ZIP;
	}
	else if ( BST_CHECKED == SendDlgItemMessage(hDlg, IDC_RADIO_7Z, BM_GETCHECK, 0, NULL) ) {
		return OET_7Z;
	}
	return OET_LZH;
}

// 選択中のアーカイバにより、コンボボックスの内容を変えたり、MultiThreadチェックを消したりする
static void hide_listbox_change_ext( HWND hDlg )
{
	int iDll = selectedDll(hDlg);

	switch( iDll ) {
		case OET_LZH:
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_LZH), SW_SHOW);
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_ZIP), SW_HIDE);
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_7Z ), SW_HIDE);
			EnableWindow(GetDlgItem(hDlg, IDC_CHECK_MT), FALSE);
			break;

		case OET_ZIP:
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_LZH), SW_HIDE);
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_ZIP), SW_SHOW);
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_7Z ), SW_HIDE);
			EnableWindow(GetDlgItem(hDlg, IDC_CHECK_MT), FALSE);
			break;

		case OET_7Z:
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_LZH), SW_HIDE);
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_ZIP), SW_HIDE);
			ShowWindow(GetDlgItem(hDlg, IDC_SELFORM_7Z ), SW_SHOW);
			EnableWindow(GetDlgItem(hDlg, IDC_CHECK_MT), TRUE);
			break;

		default:
			return;
	}

	// 圧縮後ファイル名が入力されていて、拡張子が、
	// ・.exe,
	// ・現在選択中のdll対応拡張子(.lzh, .zip, 7z)
	// のどちらでもない場合、拡張子を補正する。
	{
		char arcname[MAX_PATH*2];
		char drv[_MAX_DRIVE*2], dir[_MAX_DIR*2], fnamebase[_MAX_FNAME*2], fext[_MAX_EXT*2];
		const char *c_ext = dllexts[iDll];

		if ( 1 < GetDlgItemText(hDlg, IDC_EDIT1, arcname, _countof(arcname)) ) {
			_splitpath_s(arcname, drv, _countof(drv), dir, _countof(dir), fnamebase, _countof(fnamebase), fext, _countof(fext));
			if (lstrcmpi(fext, ".exe") != 0 && lstrcmpi(fext, c_ext) != 0) {
				// 拡張子取り替え
				_makepath_s(arcname, _countof(arcname), drv, dir, fnamebase, c_ext);
				SetDlgItemText(hDlg, IDC_EDIT1, arcname);
			}
		}
	}
}

static LPCSTR DlgProc_ShowOutputDlg_szMessage;
static LPCSTR DlgProc_ShowOutputDlg_szTitle;
static LPCSTR DlgProc_ShowOutputDlg_szOutput;
static int    DlgProc_ShowOutputDlg_flag;

// アーカイバDLLの出力メッセージを表示するためのダイアログ
static LRESULT CALLBACK DlgProc_ShowOutputDlg( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	switch( message ) {
		case WM_INITDIALOG:
			{
				LPSTR iKindIcon = 0;

				// flagから表示すべきアイコンの種類を確定
				if ( DlgProc_ShowOutputDlg_flag & MB_ICONINFORMATION ) {
					iKindIcon = IDI_INFORMATION;
				}
				else if ( DlgProc_ShowOutputDlg_flag & MB_ICONQUESTION ) {
					iKindIcon = IDI_QUESTION;
				}
				else if ( DlgProc_ShowOutputDlg_flag & MB_ICONEXCLAMATION ) {
					iKindIcon = IDI_WARNING;
				}
				else if ( DlgProc_ShowOutputDlg_flag & MB_ICONSTOP ) {
					iKindIcon = IDI_ERROR;
				}

				// 標準アイコンを読み出して設定
				if ( iKindIcon ) {
					HICON hIcon = LoadIcon(NULL, iKindIcon);
					if ( hIcon ) {
						SendDlgItemMessage(hDlg, IDC_STATIC_ICON, STM_SETICON, (WPARAM)hIcon, NULL);
					}
				}

				// メッセージを表示
				SetWindowText(GetDlgItem(hDlg, IDC_STATIC_TEXT), DlgProc_ShowOutputDlg_szMessage);

				// タイトルバーを設定
				SetWindowText(hDlg, DlgProc_ShowOutputDlg_szTitle);

				// 出力メッセージを設定
				SetWindowText(GetDlgItem(hDlg, IDC_OUTPUTLOG), DlgProc_ShowOutputDlg_szOutput);

				// カーソルを一番最後に移動
				SendDlgItemMessage(hDlg, IDC_OUTPUTLOG, EM_LINESCROLL, 0, lstrlen(DlgProc_ShowOutputDlg_szOutput));
				SendDlgItemMessage(hDlg, IDC_OUTPUTLOG, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
			}
			break;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDCANCEL:
					EndDialog(hDlg, LOWORD(wParam));
					return TRUE;
			}
			break;
	}
    return FALSE;	
}

// 出力ダイアログの表示
INT_PTR ShowOutputDlg( HWND hDlg, LPCSTR szMessage, LPCSTR szTitle, LPCSTR szOutput, int flag )
{
	DlgProc_ShowOutputDlg_szMessage = szMessage ? szMessage : "";
	DlgProc_ShowOutputDlg_szTitle   = szTitle   ? szTitle   : "";
	DlgProc_ShowOutputDlg_szOutput  = szOutput  ? szOutput  : "";
	DlgProc_ShowOutputDlg_flag      = flag;

	return DialogBox(hInst, (LPCTSTR)IDD_OUTPUTDLG, NULL, (DLGPROC)DlgProc_ShowOutputDlg);
}

// あとxx秒…のダイアログのメッセージカスタマイズ
static char *shutdown_countdown_message = "?";
static char *shutdown_button_message = "?";

// あとxx秒ダイアログのプロシージャ
LRESULT CALLBACK DlgProc_sleepBeforeShutdown( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	static UINT uCount;

	switch( message ) {
		case WM_INITDIALOG:
			{
				char buf[100];

				uCount = 20;
				wsprintf( buf, shutdown_countdown_message, uCount );
				SetDlgItemText( hDlg, IDC_STATIC_SLEEP, buf );
				SetDlgItemText( hDlg, IDOK, shutdown_button_message );

				SetTimer( hDlg, SLP_TIMERID, 1000, NULL );
			}
			return TRUE;

		case WM_TIMER:
			if ( (int)wParam == SLP_TIMERID ) {
				if ( uCount-- > 0 ) {
					char buf[100];

					wsprintf( buf, shutdown_countdown_message, uCount );
					SetDlgItemText( hDlg, IDC_STATIC_SLEEP, buf );
				}
				else {
					KillTimer( hDlg, SLP_TIMERID );
					EndDialog( hDlg, IDOK );
				}
			}
			return TRUE;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDOK:
					KillTimer( hDlg, SLP_TIMERID );
					EndDialog( hDlg, IDOK );
					return TRUE;

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

				case IDC_PAUSE: // 一時停止
					if ( SendDlgItemMessage(hDlg, IDC_PAUSE, BM_GETCHECK, 0, 0) == BST_CHECKED ) {
						KillTimer( hDlg, SLP_TIMERID );
					}
					else {
						SetTimer( hDlg, SLP_TIMERID, 1000, NULL );
					}
					return TRUE;
			}
			break;
	}
    return FALSE;
}

// ドラッグ＆ドロップ圧縮用ウィンドウ用ダイアログプロシージャのチェックボックスの活性／非活性管理
void DlgProc_OpenArchiver_CheckDisable( HWND hDlg )
{
	BOOL bFlag;

	// ダイアログを閉じないとき、シャットダウンはできない
	// 終了メッセージを表示するとき、シャットダウンはできない
	if (SendDlgItemMessage(hDlg, IDC_CHECK_NOTCLOSE, BM_GETCHECK, 0, 0) == BST_CHECKED ||
		SendDlgItemMessage(hDlg, IDC_CHECK_FINISHMESSAGE, BM_GETCHECK, 0, 0) == BST_CHECKED ) {
		bFlag = FALSE;
	}
	else {
		bFlag = TRUE;
	}
	EnableWindow(GetDlgItem(hDlg, IDC_COMBO_SHUTDOWN), bFlag);
	if ( bFlag == TRUE ) {
		// シャットダウン等するとき、ダイアログを閉じない／メッセージの表示はできない
		if (SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_GETCURSEL, 0, 0) != 0) {
			bFlag = FALSE;
		}
		else {
			bFlag = TRUE;
		}
		EnableWindow(GetDlgItem(hDlg, IDC_CHECK_NOTCLOSE), bFlag);
		EnableWindow(GetDlgItem(hDlg, IDC_CHECK_FINISHMESSAGE), bFlag);
	}
}

// 圧縮後ファイル名が入力されていない場合は、被圧縮ファイル名から自動生成
// hWnd  : ダイアログウインドウハンドル
// fname : 圧縮対象のファイル郡のうち、代表のもの。このファイルの拡張子を取り替えて、
//         圧縮後ファイルの名称を作成する。
static bool automake_compressedfilename(HWND hWnd, const char *fname)
{
	// 圧縮後ファイル名が入力されていない場合
	if ( GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT1)) == 0 ) {
		// 圧縮ファイル名（ベース）・ドライブ・ディレクトリ
		char compname[_MAX_FNAME*2];
		char drv[_MAX_DRIVE*2], dir[_MAX_DIR*2];
		char compressedfname[MAX_PATH*2];

		// 選択されている圧縮用DLLの標準拡張子は何？
		const char *ext = dllexts[selectedDll(hWnd)];
	
		// 圧縮ファイル名の生成と編集ボックスへの代入
		_splitpath_s(fname, drv, _countof(drv), dir, _countof(dir), compname, _countof(compname), NULL, 0);
		_makepath_s(compressedfname, _countof(compressedfname), drv, dir, compname, ext);
        SetDlgItemText(hWnd, IDC_EDIT1, compressedfname);

		return true;
	}

	return false;
}

// エクスプローラからファイルをドロップ
// (ドロップされたファイルを、編集ボックス(IDC_EDIT_FILES)に流し込む)
static bool oa_DropFiles(HWND hWnd, HDROP hDrop)
{
	char fname[MAX_PATH*2];	// 圧縮対象ファイル名を格納するワークエリア用変数

	// ドロップされたウィンドウが背面に隠れるといけないので、まずは強制的に表へ
	SetForegroundWindow(hWnd);

	// 編集ボックスより、現在の被圧縮ファイルのリストを取得する
	// (今回投入されたファイルのリストは、その後ろに追加する)
	int iFileListSize = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_FILES)) + 1;
	char *pszFileList = (char *)calloc(iFileListSize, sizeof(char)); // リスト取得用メモリ確保

	if ( !pszFileList ) {
		DragFinish(hDrop);
		MessageBox(hWnd, "作業を続行するためのメモリが足りません。", "-圧縮-", MB_OK | MB_ICONSTOP);
		return false;
	}
	GetDlgItemText(hWnd, IDC_EDIT_FILES, pszFileList, iFileListSize);
	string strFileList(pszFileList);

	// pszFileListが空でないか、最後の文字が\nで終わっていない場合は、\r\nを追加する
	if (iFileListSize > 1 && pszFileList[iFileListSize-2] != '\n') {
		strFileList.append("\r\n");
	}

	safefree(pszFileList);

	// ドラッグ＆ドロップされたファイルの数を得る
	UINT n = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);

	// ドラッグ＆ドロップされたファイルを、pszFileListに追加していく（区切りは\r\n）
	for(UINT i=0 ; i<n ; ++i) {
		DragQueryFile(hDrop, i, fname, _countof(fname));
		strFileList.append(fname);
		strFileList.append("\r\n");

		if (i == 0) {
			// 圧縮後ファイル名が入力されていない場合は、1番目の被圧縮ファイル名から自動生成
			// (ドロップされた最初のファイルの名前より、拡張子を取り替える形で圧縮後ファイル名を生成)
			automake_compressedfilename(hWnd, fname);
		}
	}

	// ドロップに際する処理の終了
	DragFinish(hDrop);

	// 編集ボックスに、ファイル群の文字列を戻す
	SetDlgItemText(hWnd, IDC_EDIT_FILES, strFileList.c_str());
	// カーソルを一番最後に移動
	SendDlgItemMessage(hWnd, IDC_EDIT_FILES, EM_LINESCROLL, 0, strFileList.length()-1);
	SendDlgItemMessage(hWnd, IDC_EDIT_FILES, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
	// フォーカスを編集ボックスへ移動
	SetFocus(GetDlgItem(hWnd, IDC_EDIT_FILES));

	return true;
}

// 「ファイル参照」ボタン押下
static bool oa_SelectFiles(HWND hWnd)
{
	OPENFILENAME ofn;
	char fname[MAX_PATH*2*64];

	ZeroMemory(fname, _countof(fname));

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = NULL;
	ofn.lpstrFilter = "すべてのファイル(*.*)\0*.*\0\0";
	ofn.nFilterIndex = 1;
	ofn.lpstrCustomFilter = (LPSTR) NULL;
	ofn.nMaxCustFilter = 0L;
	ofn.lpstrFile = fname;
	ofn.nMaxFile = _countof(fname);
	ofn.lpstrFileTitle = NULL;
	ofn.nMaxFileTitle = 0;
	ofn.lpstrInitialDir = NULL;
	ofn.lpstrTitle = "圧縮対象のファイルを選択";
	ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_ALLOWMULTISELECT | OFN_EXPLORER;
	ofn.nFileOffset = 0;
	ofn.nFileExtension = 0;
	ofn.lpstrDefExt = NULL; 

	if ( GetOpenFileName(&ofn) ) {
		// 編集ボックスより、現在の被圧縮ファイルのリストを取得する
		int iFileListSize = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_FILES)) + 1;
		char *pszFileList = (char *)calloc(iFileListSize, sizeof(char)); // リスト取得用メモリ確保

		if ( !pszFileList ) {
			MessageBox(hWnd, "作業を続行するためのメモリが足りません。", "-圧縮-", MB_OK | MB_ICONSTOP);
			return false;
		}
		GetDlgItemText(hWnd, IDC_EDIT_FILES, pszFileList, iFileListSize);
		string strFileList(pszFileList);

		// pszFileListが空でないか、最後の文字が\nで終わっていない場合は、\r\nを追加する
		if (iFileListSize > 1 && pszFileList[iFileListSize-2] != '\n') {
			strFileList.append("\r\n");
		}

		safefree(pszFileList);

		// ファイル名を追加する処理

		// ファイル名は複数選択されることがあり、単一選択か複数選択かで処理が分かれる。
		//   単一選択の場合 …… フルパス\0\0
		//   複数選択の場合 …… フォルダ\0ファイル１\0ファイル２\0...ファイルｎ\0\0
		// また、フォルダ名は、ルートフォルダなら後ろに\がつくが、それ以外では付かない

		// p を、第１要素のすぐ後ろを指させる。これが\0ならば、フルパス１つで終わると見なす
		char *p = fname + lstrlen(fname) + 1;

		if ( *p == '\0' ) {
			// 単一のフルパス
			strFileList.append(fname);
			strFileList.append("\r\n");

			// 圧縮後ファイル名が入力されていない場合は、被圧縮ファイル名から自動生成
			// (参照入力されたファイルの名前より、拡張子を取り替える形で圧縮後ファイル名を生成)
			automake_compressedfilename(hWnd, fname);
		}
		else {
			// 複数のパス … fname:フォルダ, p:ファイル名
			char fullpath[MAX_PATH*2];
			bool firstflag = true;

			while(*p) {
				_makepath_s(fullpath, _countof(fullpath), NULL, fname, p, NULL);
				strFileList.append(fullpath);
				strFileList.append("\r\n");
				p += (lstrlen(p)+1);

				if (firstflag) {
					// 圧縮後ファイル名が入力されていない場合は、1番目の被圧縮ファイル名から自動生成
					// (参照入力された最初のファイルの名前より、拡張子を取り替える形で圧縮後ファイル名を生成)
					automake_compressedfilename(hWnd, fullpath);
					firstflag = false;
				}
			}
		}

		// 文字列を編集ボックスへ
		SetDlgItemText(hWnd, IDC_EDIT_FILES, strFileList.c_str()); 
		// カーソルを一番最後に移動
		SendDlgItemMessage(hWnd, IDC_EDIT_FILES, EM_LINESCROLL, 0, strFileList.length()-1);
		SendDlgItemMessage(hWnd, IDC_EDIT_FILES, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
		// フォーカスを編集ボックスへ移動
		SetFocus(GetDlgItem(hWnd, IDC_EDIT_FILES));
	}

	return true;
}

// 「フォルダ参照」ボタン押下
static bool oa_SelectFolder(HWND hWnd)
{
	BOOL         bRes;
	LPITEMIDLIST pidlRetFolder;
	BROWSEINFO   stBInfo;
	char         foldername[MAX_PATH*2];

	//　構造体を初期化します。
	stBInfo.pidlRoot = NULL;	// ルートフォルダ
	stBInfo.hwndOwner = hWnd;	// 表示するダイアログの親ウィンドウのハンドル
	stBInfo.pszDisplayName = foldername;	// フォルダ名を取得するバッファのポインタ
	stBInfo.lpszTitle = "フォルダ選択";	// ダイアログの中に表示される文字列
	stBInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;	//表示フラグ
	stBInfo.lpfn = NULL;
	stBInfo.lParam = 0L;

	//　ダイアログボックスを表示します。
	pidlRetFolder = SHBrowseForFolder( &stBInfo );

	if( pidlRetFolder != NULL ) {
		//　フルパスを取得します。
		bRes = SHGetPathFromIDList( pidlRetFolder, foldername );
		CoTaskMemFree( pidlRetFolder );	
		if ( bRes == TRUE ) {
			// 編集ボックスより、現在の被圧縮ファイルのリストを取得する
			int iFileListSize = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_FILES)) + 1;
			char *pszFileList = (char *)calloc(iFileListSize, sizeof(char)); // リスト取得用メモリ確保

			if ( !pszFileList ) {
				MessageBox(hWnd, "作業を続行するためのメモリが足りません。", "-圧縮-", MB_OK | MB_ICONSTOP);
				return false;
			}
			GetDlgItemText(hWnd, IDC_EDIT_FILES, pszFileList, iFileListSize);
			string strFileList(pszFileList);

			// pszFileListが空でないか、最後の文字が\nで終わっていない場合は、\r\nを追加する
			if (iFileListSize > 1 && pszFileList[iFileListSize-2] != '\n') {
				strFileList.append("\r\n");
			}

			safefree(pszFileList);

			// フォルダ名を追加
			strFileList.append(foldername);
			strFileList.append("\r\n");

			// 圧縮後ファイル名が入力されていない場合は、被圧縮フォルダ名から自動生成
			// (参照入力されたフォルダの名前より、拡張子を付け加える形で圧縮後ファイル名を生成)
			automake_compressedfilename(hWnd, foldername);

			// 編集ボックスに戻す
			SetDlgItemText(hWnd, IDC_EDIT_FILES, strFileList.c_str()); 

			// カーソルを一番最後に移動
			SendDlgItemMessage(hWnd, IDC_EDIT_FILES, EM_LINESCROLL, 0, strFileList.length()-1);
			SendDlgItemMessage(hWnd, IDC_EDIT_FILES, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
			// フォーカスを編集ボックスへ移動
			SetFocus(GetDlgItem(hWnd, IDC_EDIT_FILES));
			return true;
		}
	}
	return false;
}

// 「圧縮開始」ボタン押下
static bool CallArchive(HWND hWnd)
{
	// 選択されている圧縮用DLLの標準拡張子は何？
	int         selDll        = selectedDll(hWnd);
	const char *p_default_ext = dllexts[selDll];
	char        szOldCurrentDir[MAX_PATH*2];

	// 圧縮対象のファイル名が空だった場合
	if ( GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_FILES)) == 0 ) {
		MessageBox(hWnd, "圧縮対象のファイル名を指定してください。", "-圧縮-", MB_OK | MB_ICONEXCLAMATION);
		return false;
	}

	// ファイル名が入力されていて、拡張子が標準と異なっている場合は、
	// 拡張子がこのままでもよいか、確認する。
	char arcfile[MAX_PATH*2];
	{
		char drv[_MAX_DRIVE*2], dir[_MAX_DIR*2], fname[_MAX_FNAME*2], fext[_MAX_EXT*2];
		
		GetDlgItemText(hWnd, IDC_EDIT1, arcfile, _countof(arcfile));
		if ( arcfile[0] == 0 ) {
			MessageBox(hWnd, "圧縮ファイル名を指定してください。", "-圧縮-", MB_OK | MB_ICONEXCLAMATION);
			return false;
		}

		_splitpath_s(arcfile, drv, _countof(drv), dir, _countof(dir), fname, _countof(fname), fext, _countof(fext));

		if (fext[0] != 0 && _stricmp(fext, ".exe") != 0 && _stricmp(fext, p_default_ext) != 0 &&
			!(selDll == OET_ZIP && (_stricmp(fext, ".jar") == 0 || _stricmp(fext, ".xpi") == 0))  &&
			!(selDll == OET_7Z && (_stricmp(fext, ".zip") == 0 || _stricmp(fext, ".jar") == 0 || _stricmp(fext, ".xpi") == 0)) ) {
			// 拡張子が空の場合は、あとから補完されるから良いとして、
			// exe(自己解凍)でなく、標準拡張子でもない場合は確認が必要。
			// ただし、selDll が OET_ZIP の場合、jar と xpi も OK
			//                   OET_7Z  の場合、zip, jar, xpi もOK
			char mes[100];

			wsprintf(mes, "圧縮ファイル名の拡張子が、%sでなく、.exeでもありません。%sに補正しますか?",
						  p_default_ext, p_default_ext);
			switch( MessageBox(hWnd, mes, "-圧縮-", MB_YESNOCANCEL | MB_ICONQUESTION) ) {
				case IDYES:
					// 拡張子の補正を行う
					_makepath_s(arcfile, _countof(arcfile), drv, dir, fname, p_default_ext);
					SetDlgItemText(hWnd, IDC_EDIT1, arcfile);
					break;

				case IDCANCEL:
					// 圧縮の取りやめ
					return false;
			}
		}
	}

	// コンボボックス履歴に登録	
	cbq->Add(arcfile);

	// 処理開始前のカレントディレクトリを取得
	GetCurrentDirectory(_countof(szOldCurrentDir), szOldCurrentDir);

	char   arcfile2[MAX_PATH*2];
	char   respname[MAX_PATH*2], tmppath[MAX_PATH*2] ,lzhname_wexe[MAX_PATH*2];
	char   password[MAX_PATH*2];
	int    fnl;
	bool   notclose = 0;
	bool   finmessage = 0;
	int    iAfter = 0;
	bool   abort = 0;
	HANDLE handle;
	REG    reg;

	// ダイアログ状態の抽出
	notclose   = (BST_CHECKED == SendDlgItemMessage(hWnd, IDC_CHECK_NOTCLOSE, BM_GETCHECK, 0, NULL))?1:0;
	finmessage = (BST_CHECKED == SendDlgItemMessage(hWnd, IDC_CHECK_FINISHMESSAGE, BM_GETCHECK, 0, NULL))?1:0;
	if (finmessage == 0) {
		iAfter = (int)SendDlgItemMessage(hWnd, IDC_COMBO_SHUTDOWN, CB_GETCURSEL, 0, NULL);
	}

	GetDlgItemText(hWnd, IDC_EDIT_PASSWORD, password, _countof(password));
	if (strlen(password) > 0) {
		if (selDll == OET_LZH) {
			password[0] = 0;
			MessageBox(hWnd, "LHA方式ではパスワードは扱えません。パスワード指定は無視されます。", "-圧縮-", MB_OK | MB_ICONWARNING);
		}
		else {
			if (strchr(password, ' ') != NULL || strchr(password, '"') != NULL) {
				MessageBox(hWnd, "パスワードにはスペースやダブルコーティションは使えません。", "-圧縮-", MB_OK | MB_ICONERROR);
				return false;
			}
		}
	}

	// 完了後シャットダウンをする場合、本当にそれでよいか確認
	if ( iAfter != 0 ) {
		char *p;
		switch(iAfter) {
			case 1:
				p = "圧縮完了後にコンピュータをシャットダウンします。よろしいですか?";
				break;

			case 2:
				p = "圧縮完了後にコンピュータを再起動します。よろしいですか?";
				break;

			case 3:
				p = "圧縮完了後にコンピュータをサスペンドします。よろしいですか?";
				break;

			case 4:
				p = "圧縮完了後にコンピュータを休止状態にします。よろしいですか?";
				break;

			default:
				p = "?";
				break;
		}
		if ( IDYES != MessageBox(hWnd, p, "-圧縮-", MB_YESNO | MB_ICONQUESTION) ) {
			return false;
		}
	}

	// テンポラリフォルダ内にレスポンスファイルを作成
	GetTempPath(_countof(tmppath), tmppath);
	GetTempFileName(tmppath, "lh", 0, respname);

	lstrcpy(arcfile2, arcfile); // ダイアログから圧縮後のファイル名：複製

	if ( arcfile[0] == '-' && selDll == OET_ZIP ) {
		if ( IDYES != MessageBox(hWnd, "選択しているアーカイバでは、半角ハイフン(-)で始まるファイル名を取り扱うことができない可能性があります。続行しますか?", "-圧縮-", MB_YESNO | MB_ICONQUESTION) ) {
			return false;
		}
	}

	// レスポンスファイルの作成
	if ( INVALID_HANDLE_VALUE != (handle = CreateFile(respname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) ) {
		DWORD wtn;
		char  mfile[_MAX_PATH*2+4];
		char  fname[_MAX_FNAME*2];
		char  ext[_MAX_EXT*2];
		bool  deldirinfo = 1; // ディレクトリ情報を破棄するかどうかフラグ(1:破棄する)

		// 圧縮されるファイル名の一覧を取得する(改行区切り)
		char *flist;
		char *next, *token;
		int  iFListSize;
		list<string> files;
		list<string>::iterator it;

		iFListSize = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT_FILES)) + 1;
		flist = (char *)calloc(iFListSize, sizeof(char));
		if ( flist == NULL ) {
			MessageBox(hWnd, "作業を続行するためのメモリが足りません。", "-圧縮-", MB_OK | MB_ICONSTOP);
			return false;
		}
		GetDlgItemText(hWnd, IDC_EDIT_FILES, flist, iFListSize);
		token = strtok_s(flist, "\r\n", &next);
		while( token ) {
			// ファイル名にダブルコーテーションがある場合は取り除く
			if (token[0] == '"') {
				string fname(token + 1);

				list<string>::size_type sz = fname.length();

				if (sz > 0) {
					fname.erase(sz-1);
					files.push_back(fname);
				}
			}
			else {
				files.push_back(token);
			}
			
			token = strtok_s(NULL, "\r\n", &next);
		}
		safefree( flist );

		// 圧縮対象のファイル名が空だった場合
		if ( files.empty() ) {
			MessageBox(hWnd, "圧縮対象のファイル名を指定してください。", "-圧縮-", MB_OK | MB_ICONEXCLAMATION);
			return false;
		}

		list<string>::iterator its = files.begin();
		list<string>::iterator ite = files.end();

		// まず最初に、カレントディレクトリをセット
		{ // カレントディレクトリをセット
			char cdir[MAX_PATH*2], cdir2[MAX_PATH*2];
			char drive[_MAX_DRIVE*2];
			char dir[_MAX_DIR*2];

			it = its;
			_splitpath_s(it->c_str(), drive, _countof(drive), dir, _countof(dir), NULL, 0, NULL, 0);
			_makepath_s(cdir, _countof(cdir), drive, dir, NULL, NULL);
			SetCurrentDirectory( cdir );

			// 2番目以降のファイルのディレクトリと比較し、
			// すべてのディレクトリと同じだったら、ディレクトリ情報は破棄する。
            // 1つでもディレクトリが違っていたら、ディレクトリ情報は破棄しない。
			++it;
			for(; it != ite ; ++it) {
				_splitpath_s(it->c_str(), drive, _countof(drive), dir, _countof(dir), NULL, 0, NULL, 0);
				_makepath_s(cdir2, _countof(cdir2), drive, dir, NULL, NULL);
				if ( _stricmp(cdir2, cdir) != 0 ) {
                    deldirinfo = 0;
					break;
				}
			}
		}

		// ファイル名をレスポンスファイルに書き込む
		const char *pfname;
		for(it=its ; it != ite ; ++it) {
			// Unlha32を使う場合は、ファイル名の前に -gb をつける
			if ( selDll == OET_LZH ) {
				WriteFile(handle, "-gb", 3, &wtn, NULL);
			}

			pfname = it->c_str();

			if ( deldirinfo ) {
				// ドライブ・ディレクトリ名の部分は分離
				_splitpath_s(pfname, NULL, 0, NULL, 0, fname, _countof(fname), ext, _countof(ext));
				_makepath_s(mfile, _countof(mfile), NULL, NULL, fname, ext);

				if ( mfile[0] == '-' && selDll == OET_ZIP ) {
					if ( IDYES != MessageBox(hWnd, "選択しているアーカイバでは、半角ハイフン(-)で始まるファイル名を取り扱うことができない可能性があります。このファイルを扱いますか?", mfile, MB_YESNO | MB_ICONQUESTION) ) {
						continue;
					}
				}

				WriteFile(handle, "\"", 1, &wtn, NULL);
				WriteFile(handle, mfile, lstrlen(mfile), &wtn, NULL);
				WriteFile(handle, "\"\r\n", 3, &wtn, NULL);
			}
			else {
				// ドライブ・ディレクトリ名部分を分離しない
				if ( pfname[0] == '-' && selDll == OET_ZIP ) {
					if ( IDYES != MessageBox(hWnd, "選択しているアーカイバでは、半角ハイフン(-)で始まるファイル名を取り扱うことができない可能性があります。このファイルを扱いますか?", pfname, MB_YESNO | MB_ICONQUESTION) ) {
						continue;
					}
				}

				WriteFile(handle, "\"", 1, &wtn, NULL);
				WriteFile(handle, pfname, lstrlen(pfname), &wtn, NULL);
				WriteFile(handle, "\"\r\n", 3, &wtn, NULL);
			}
		}
		CloseHandle( handle );
	}
	else {
        MessageBox(hWnd, "レスポンスファイルまたはリストファイルを作成できませんでした。", "-圧縮-", MB_OK | MB_ICONSTOP);
		if ( !notclose ) {
			EndDialog(hWnd, FALSE);
		}
		return false;
	}

	fnl = lstrlen( arcfile );
	if ( selDll != OET_7Z && fnl >= 5 && ( arcfile[fnl-1] == 'e' || arcfile[fnl-1] == 'E' ) && ( arcfile[fnl-2] == 'x' || arcfile[fnl-2] == 'X' ) && ( arcfile[fnl-3] == 'e' || arcfile[fnl-3] == 'E' ) && arcfile[fnl-4] == '.' ) {
		arcfile[fnl-4] = 0;
        fnl = 1; // 自己解凍書庫を作るフラグ
		lstrcpy( lzhname_wexe, arcfile );
		lstrcat( lzhname_wexe, dllexts[selDll] );
	}
	else {
		char drv[_MAX_DRIVE*2], dir[_MAX_DIR*2], fname[_MAX_FNAME*2], fext[_MAX_EXT*2], arcfname[MAX_PATH*2];
		fnl = 0; // 自己解凍書庫は作らない(通常の書庫)

		// 同名の圧縮ファイルが存在すると追記になってしまうため、それでも良いかどうか確認する
		_splitpath_s( arcfile, drv, _countof(drv), dir, _countof(dir), fname, _countof(fname), fext, _countof(fext) );
		if ( fext[0] == 0 ) {
			lstrcpy( fext, dllexts[selDll]);
		}                    
		_makepath_s( arcfname, _countof(arcfname), drv, dir, fname, fext );

		if ( tFileExist( arcfname ) ) {
			switch( MessageBox( hWnd, "すでに同名の圧縮ファイルが存在しています。このまま圧縮を行うと、既存の圧縮ファイルへ追記されます。よろしいですか?\n\n[はい]…既存の圧縮ファイルへ追記\n[いいえ]…既存の圧縮ファイルは削除し、新たに圧縮ファイルを作成\n[キャンセル]…圧縮を中止する", "-圧縮-", MB_ICONQUESTION | MB_YESNOCANCEL ) ) {
				/* case IDYES : break; */ // 省略
				case IDNO:
					DeleteFile( arcfile );
					break;

				case IDCANCEL:
					abort = 1;
					break;
			}
		}
	}

	if ( abort == 0 ) {
		char szOption[MAX_PATH*2+16] = "";
		int  iSel;
		char szOutputBuf[ARCDLL_OUTBUFSIZE+1];

		if ( !notclose ) {
			// ウィンドウを隠す
			ShowWindow( hWnd, SW_HIDE );
		}

		ZeroMemory(szOutputBuf, ARCDLL_OUTBUFSIZE+1);
		switch ( selDll ) {
			case OET_ZIP:
				lstrcpy( szOption, "-#" );
				iSel = (int)SendDlgItemMessage(hWnd, IDC_SELFORM_ZIP, CB_GETCURSEL, 0, NULL);
				szOption[1] = '0' + (char)iSel;
				
				if (password[0] != 0) {
					strcat(szOption, " -P ");
					strcat(szOption, password);
				}

				{
					if ( T_TF_SUCCESS != call_zip32j_log(hWnd, arcfile, respname, szOption, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
						char *szOutputBuf2 = replacestr(szOutputBuf, "\n", "\r\n");
						ShowOutputDlg(hWnd, "圧縮に失敗したか、中断されました。", "ZIPで圧縮", szOutputBuf2, MB_ICONSTOP | MB_OK);
						safefree(szOutputBuf2);
					}
					else {
						if ( fnl ) {
							if ( T_TF_SUCCESS != call_zip32_toexe_log(hWnd, lzhname_wexe, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
								char *szOutputBuf2 = replacestr(szOutputBuf, "\n", "\r\n");
								ShowOutputDlg(hWnd, "自己解凍書庫の作成をキャンセルしたか、失敗しました。", "ZIPで圧縮", szOutputBuf2, MB_ICONSTOP | MB_OK);
								safefree(szOutputBuf2);
							}
							else {
								// 自己解凍書庫へ変換する前のファイルを削除する
								DeleteFile( lzhname_wexe );

								// 拡張子EXEが大文字になってしまうため、実際にユーザが指定したファイル名にリネームする
								MoveFile(arcfile2, arcfile2);
							}                                                        
						}
						else {
							if ( finmessage ) {
								char *szOutputBuf2 = replacestr(szOutputBuf, "\n", "\r\n");
								ShowOutputDlg(hWnd, "圧縮が完了しました。", "ZIPで圧縮", szOutputBuf2, MB_ICONINFORMATION | MB_OK);
								safefree(szOutputBuf2);
							}
						}
					}
				}
				break;

			case OET_7Z:
				lstrcpy( szOption, "-mx=" );
				iSel = (int)SendDlgItemMessage(hWnd, IDC_SELFORM_7Z, CB_GETCURSEL, 0, NULL);
				switch( iSel ) {
					case 0:
						lstrcat( szOption, "0" );
						break;
					case 1:
						lstrcat( szOption, "1" );
						break;
					case 2:
						lstrcat( szOption, "5" );
						break;
					case 3:
						lstrcat( szOption, "7" );
						break;
					case 4:
						lstrcat( szOption, "9" );
						break;
				}
				if ( BST_CHECKED == SendDlgItemMessage(hWnd, IDC_CHECK_MT, BM_GETCHECK, 0, NULL) ) {
					lstrcat( szOption, " -mmt=on" );
				}
				else {
					lstrcat( szOption, " -mmt=off" );
				}

				if (password[0] != 0) {
					strcat(szOption, " -p");
					strcat(szOption, password);
				}

				// 拡張子exeの自己解凍書庫は、ライブラリが自力で見ているため、ここで判定文は入れない
				if ( T_TF_SUCCESS != call_7zip32r_log(hWnd, arcfile, respname, szOption, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
					ShowOutputDlg(hWnd, "圧縮に失敗したか、中断されました。", "7-ZIPで圧縮", szOutputBuf, MB_ICONSTOP | MB_OK);
				}
				else {
					if ( finmessage ) {
						ShowOutputDlg(hWnd, "圧縮が完了しました。", "7-ZIPで圧縮", szOutputBuf, MB_ICONINFORMATION | MB_OK);
					}
				}
				break;

			default: // LZH形式
				lstrcpy( szOption, "-jm" );
				iSel = (int)SendDlgItemMessage(hWnd, IDC_SELFORM_LZH, CB_GETCURSEL, 0, NULL);
				switch( iSel ) {
					case 0:
						lstrcat( szOption, "0" );
						break;
					case 1:
						lstrcat( szOption, "1" );
						break;
					case 2:
						lstrcat( szOption, "2" );
						break;
					case 3:
						lstrcat( szOption, "3" );
						break;
					case 4:
						lstrcat( szOption, "4" );
						break;
					case 5:
						lstrcat( szOption, "a" );
						break;
					case 6:
						lstrcat( szOption, "5" );
						break;
					case 7:
						lstrcat( szOption, "6" );
						break;
					case 8:
						lstrcat( szOption, "7" );
						break;
					case 9:
						lstrcat( szOption, "8" );
						break;
				}
				if ( T_TF_SUCCESS != call_unlha32r_log(hWnd, arcfile, respname, szOption, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
					ShowOutputDlg(hWnd, "圧縮に失敗したか、中断されました。", "LHAで圧縮", szOutputBuf, MB_ICONSTOP | MB_OK);
				}
				else {
					if ( fnl ) {
						if ( T_TF_SUCCESS != call_unlha32_toexe_log(hWnd, arcfile, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
							ShowOutputDlg(hWnd, "自己解凍書庫の作成をキャンセルしたか、失敗しました。", "LHAで圧縮", szOutputBuf, MB_ICONSTOP | MB_OK);
						}
						else {
							// 自己解凍書庫へ変換する前のファイルを削除する
							DeleteFile( lzhname_wexe );

							// 拡張子EXEが大文字になってしまうため、実際にユーザが指定したファイル名にリネームする
							MoveFile(arcfile2, arcfile2);
						}                                                        
					}
					else {
						if ( finmessage ) {
							// 正常終了の場合のみ、ダイアログ出力前にカレントディレクトリを戻す
							SetCurrentDirectory(szOldCurrentDir);

							ShowOutputDlg(hWnd, "圧縮が完了しました。", "LHAで圧縮", szOutputBuf, MB_ICONINFORMATION | MB_OK);
						}
					}
				}
				break;
		}
	}

	// カレントディレクトリを元に戻す
	SetCurrentDirectory(szOldCurrentDir);

	// レスポンスファイルを削除
	DeleteFile( respname );

	// 終了処理（開始時の質問でNoの場合は、ここを通らない）
	if ( abort == 0 ) {
		if ( !notclose ) {
			EndDialog(hWnd, TRUE);
			if ( iAfter ) {
				switch (iAfter) {
					case 1:
						shutdown_countdown_message = "あと %u 秒でシャットダウンします。";
						shutdown_button_message = "すぐにシャットダウン(&S)";
						break;
					case 2:
						shutdown_countdown_message = "あと %u 秒で再起動します。";
						shutdown_button_message = "すぐに再起動(&S)";
						break;
					case 3:
						shutdown_countdown_message = "あと %u 秒でサスペンドします。";
						shutdown_button_message = "すぐにサスペンド(&S)";
						break;
					case 4:
						shutdown_countdown_message = "あと %u 秒で休止状態に入ります。";
						shutdown_button_message = "すぐに休止状態に入る(&S)";
						break;
					default:
						shutdown_countdown_message = "?? [%u]";
						break;
				}

				if ( IDOK == DialogBox(hInst, (LPCTSTR)IDD_COUNTDOWN, NULL, (DLGPROC)DlgProc_sleepBeforeShutdown) ) {
					GetQuitRight();
					switch (iAfter) {
						case 1:
							if ( 0 == ExitWindowsEx(EWX_SHUTDOWN | EWX_POWEROFF, 0) ) {
								MessageBox(hWnd, "Windowsの終了に失敗しました。", "-圧縮-", MB_OK | MB_ICONSTOP);
							}
							break;
						case 2:
							if ( 0 == ExitWindowsEx(EWX_REBOOT, 0) ) {
								MessageBox(hWnd, "Windowsの再起動に失敗しました。", "-圧縮-", MB_OK | MB_ICONSTOP);
							}
							break;
						case 3:
							if ( 0 == SetSystemPowerState( TRUE, FALSE ) ) {
								MessageBox(hWnd, "サスペンドに失敗しました。", "-圧縮-", MB_OK | MB_ICONSTOP);
							}
							break;
						case 4:
							if ( 0 == SetSystemPowerState( FALSE, FALSE ) ) {
								MessageBox(hWnd, "休止状態への移行に失敗しました。", "-圧縮-", MB_OK | MB_ICONSTOP);
							}
							break;
					}
				}
			}
		}
		else {
			SetDlgItemText(hWnd, IDCANCEL, "閉じる(&X)");
		}
	}


	return true;
}

// 編集ボックスのサブクラス化用ウィンドウプロシージャ
static WNDPROC re_OldEditProc;

// サンプルウィンドウ内の編集ボックスのサブクラス化用ウィンドウプロシージャ
LRESULT CALLBACK re_NewEditProc(HWND hEdit, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch( message ) {
		case WM_CHAR: // 全選択のための Ctrl+A 受け取りのため
			if( (int)wParam == 1 ) {
				SendMessage( hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)-1 );  
				return 0; // デフォルトのプロシージャを呼ばずにそのまま終了
			}
			break;
	}

	// デフォルトのプロシージャをコール
	return CallWindowProc(re_OldEditProc, hEdit, message, wParam, lParam);
}

// ドラッグ＆ドロップ圧縮用ウィンドウ用ダイアログプロシージャ
static LRESULT CALLBACK DlgProc_OpenArchiver( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
	static SIZEDLG *sizedlg;

	switch( message ) {
		case WM_INITDIALOG:
			// 現在は、ダイアログは MS P ゴシックで固定
			// SetChildWindowFont(hDlg);
			// タイトルバーのアイコンの設定
			{
				HICON hDialogIcon = (HICON)LoadImage(hInst, (LPCSTR)133, IMAGE_ICON, 0, 0,
					                                 LR_DEFAULTSIZE | LR_SHARED);

				SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hDialogIcon);
				SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hDialogIcon);
			}
			{
				REG reg;
				int drvs[3]; // どのDLLが有効か?(添字は、OET_***にそのまま該当)

				drvs[OET_LZH] = call_unlha32(NULL, NULL);
				drvs[OET_ZIP] = call_zip32j(NULL, NULL, NULL, NULL);
				drvs[OET_7Z]  = call_7zip32(NULL, NULL);

				// 使用不可の項目をグレイアウト
				// (DLLが有効であれば、T_TF_ILLEGALCALLが返ってきているはず)
				if ( drvs[OET_LZH] != T_TF_ILLEGALCALL ) {
					EnableWindow(GetDlgItem(hDlg, IDC_RADIO_LZH), FALSE);
				}
				if ( drvs[OET_ZIP] != T_TF_ILLEGALCALL ) {
					EnableWindow(GetDlgItem(hDlg, IDC_RADIO_ZIP), FALSE);
				}
				if ( drvs[OET_7Z]  != T_TF_ILLEGALCALL ) {
					EnableWindow(GetDlgItem(hDlg, IDC_RADIO_7Z), FALSE);
				}

				// 圧縮に利用するDLLの、デフォルトの選択肢を設定
				// (DLLが有効であれば、T_TF_ILLEGALCALLが返ってきているはず)
				if ( drvs[OET_LZH] == T_TF_ILLEGALCALL ) {
					SendDlgItemMessage(hDlg, IDC_RADIO_LZH, BM_SETCHECK, BST_CHECKED, NULL);
				}
				else if ( drvs[OET_ZIP] == T_TF_ILLEGALCALL ) {
					SendDlgItemMessage(hDlg, IDC_RADIO_ZIP, BM_SETCHECK, BST_CHECKED, NULL);
				}
				else if ( drvs[OET_7Z]  == T_TF_ILLEGALCALL ) {
					SendDlgItemMessage(hDlg, IDC_RADIO_7Z,  BM_SETCHECK, BST_CHECKED, NULL);
				}

				// 圧縮形式／圧縮率の選択肢を準備
				// [LZH]
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh0 (無圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh1 (LHarc互換)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh5 (標準)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh6 (高圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh7 (新圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"最適な形式を自動選択");
				if ( call_unlha32_GetVersion() >= 2400100 ) {
					SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh2 (LH.EXE 1.9x互換)");
					SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lh3 (LH.EXE 1.9x互換)");
					SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lzs (LArc互換)");
					SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_ADDSTRING, 0, (LPARAM)"lz5 (LArc互換)");
				}
				// デフォルトの選択肢
				SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_SETCURSEL, (WPARAM)2, (LPARAM)NULL);

				// [ZIP]
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -0 (無圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -1 (高速/圧縮率低)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -2");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -3");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -4");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -5");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -6 (標準)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -7");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -8");
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_ADDSTRING, 0, (LPARAM)" -9 (低速/圧縮率高)");
				// デフォルトの選択肢
				SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_SETCURSEL, (WPARAM)6, (LPARAM)NULL);

				// [7z]
				SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_ADDSTRING, 0, (LPARAM)"x=0 (無圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_ADDSTRING, 0, (LPARAM)"x=1 (高速圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_ADDSTRING, 0, (LPARAM)"x=5 (標準圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_ADDSTRING, 0, (LPARAM)"x=7 (最高圧縮)");
				SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_ADDSTRING, 0, (LPARAM)"x=9 (超高圧縮)");
				// デフォルトの選択肢
				SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_SETCURSEL, (WPARAM)2, (LPARAM)NULL);

				// シャットダウン等の選択肢
				SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_ADDSTRING, 0, (LPARAM)"圧縮完了後にエラーがなくても、特に何もしない");
				SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_ADDSTRING, 1, (LPARAM)"圧縮完了後にエラーがなければシャットダウンする");
				SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_ADDSTRING, 2, (LPARAM)"圧縮完了後にエラーがなければ再起動する");
				SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_ADDSTRING, 3, (LPARAM)"圧縮完了後にエラーがなければサスペンドする");
				SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_ADDSTRING, 4, (LPARAM)"圧縮完了後にエラーがなければ休止状態に入る");
				// デフォルトの選択肢
				SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN,  CB_SETCURSEL, (WPARAM)0, (LPARAM)NULL);

				// 前回のチェック状態をレジストリから読み込む
				if ( reg.OpenKey(HKEY_CURRENT_USER, RNSF7REGKEY) ) {
					int iSel;

					switch ( reg.ReadInteger("arc_lzh_or_zip", 0) ) {
						case OET_LZH:
							if ( drvs[OET_LZH] == T_TF_ILLEGALCALL ) {
								SendDlgItemMessage(hDlg, IDC_RADIO_LZH, BM_SETCHECK, BST_CHECKED, NULL);
								SendDlgItemMessage(hDlg, IDC_RADIO_ZIP, BM_SETCHECK, BST_UNCHECKED, NULL);
								SendDlgItemMessage(hDlg, IDC_RADIO_7Z,  BM_SETCHECK, BST_UNCHECKED, NULL);
							}
							break;
						case OET_ZIP:
							if ( drvs[OET_ZIP] == T_TF_ILLEGALCALL ) {
								SendDlgItemMessage(hDlg, IDC_RADIO_LZH, BM_SETCHECK, BST_UNCHECKED, NULL);
								SendDlgItemMessage(hDlg, IDC_RADIO_ZIP, BM_SETCHECK, BST_CHECKED, NULL);
								SendDlgItemMessage(hDlg, IDC_RADIO_7Z,  BM_SETCHECK, BST_UNCHECKED, NULL);
							}
							break;
						case OET_7Z:
							if ( drvs[OET_7Z]  == T_TF_ILLEGALCALL ) {
								SendDlgItemMessage(hDlg, IDC_RADIO_LZH, BM_SETCHECK, BST_UNCHECKED, NULL);
								SendDlgItemMessage(hDlg, IDC_RADIO_ZIP, BM_SETCHECK, BST_UNCHECKED, NULL);
								SendDlgItemMessage(hDlg, IDC_RADIO_7Z,  BM_SETCHECK, BST_CHECKED, NULL);
							}
							break;
					}
					if ( 1 == reg.ReadInteger("arc_lzh_or_zip_disclose", 0) ) {
						SendDlgItemMessage(hDlg, IDC_CHECK_NOTCLOSE, BM_SETCHECK, BST_CHECKED, NULL);
					}
					if ( 1 == reg.ReadInteger("arc_lzh_or_zip_finmessage", 0) ) {
						SendDlgItemMessage(hDlg, IDC_CHECK_FINISHMESSAGE, BM_SETCHECK, BST_CHECKED, NULL);
					}
					iSel = reg.ReadInteger("arc_lzh_or_zip_shutdown", 0);
					if ( 0 <= iSel && iSel <= 4 ) {
						SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_SETCURSEL, iSel, NULL);
					}

					// 圧縮形式／圧縮率の前回選択した選択肢を選択する。
					// [LZH]
					iSel = reg.ReadInteger("arc_lzh_lhx", 2);
					if ( 0 <= iSel && iSel <= 9 ) {
						SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_SETCURSEL, iSel, NULL);
					}
					
					// [ZIP]
					iSel = reg.ReadInteger("arc_zip_zipx", 6);
					if ( 0 <= iSel && iSel <= 9 ) {
						SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_SETCURSEL, iSel, NULL);
					}

					// [7z]
					iSel = reg.ReadInteger("arc_7z_7zx", 2);
					if ( 0 <= iSel && iSel <= 4 ) {
						SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_SETCURSEL, iSel, NULL);
					}

					// マルチスレッド利用かどうか
					if ( reg.ReadInteger("arc_lz_mt", 0) == 1 ) {
						SendDlgItemMessage(hDlg, IDC_CHECK_MT, BM_SETCHECK, BST_CHECKED, NULL);
					}

					// 前回のファイル名をレジストリから読み込む（コンボボックス履歴とは別制御）
					reg.ReadStringForEditbox("arc_lastname", hDlg, IDC_EDIT1);

					// 選択中でないDLLのリストボックスを隠す
					hide_listbox_change_ext(hDlg);

					reg.CloseKey();
				}
			
				// 使用不可のチェックボックスをグレイアウト
				DlgProc_OpenArchiver_CheckDisable( hDlg );

				// ダイアログのリサイズのための準備
				sizedlg = new SIZEDLG(hDlg, dlgitems);

				// ツールチップの追加
				CreateToolTip(hInst, hDlg, oa_tooltips);

				// コンボボックスのリストを準備
				cbq = new ComboboxQueue();
				cbq->Init(hDlg, IDC_EDIT1, 16, HKEY_CURRENT_USER, RNSF7REGKEY, "arc_lastname_combo");

				// サブクラス化
				HWND hEdit = GetDlgItem(hDlg, IDC_EDIT_FILES);
				re_OldEditProc = (WNDPROC)GetWindowLongPtr( hEdit, GWLP_WNDPROC );
				SetWindowLongPtr( hEdit, GWLP_WNDPROC, (LONG_PTR)re_NewEditProc );
			}
			return TRUE;

		case WM_DROPFILES:
			// エクスプローラからファイルをドロップ
			oa_DropFiles(hDlg, (HDROP)wParam);
			return TRUE;

		case WM_DESTROY:
			{
				REG reg;

				// チェックボックスの状態を保存
				if ( reg.OpenKey(HKEY_CURRENT_USER, RNSF7REGKEY, TREG_OPEN_CREATE) ) {
					reg.WriteInteger("arc_lzh_or_zip", selectedDll(hDlg) );
					reg.WriteInteger("arc_lzh_or_zip_disclose", BST_CHECKED == SendDlgItemMessage(hDlg, IDC_CHECK_NOTCLOSE, BM_GETCHECK, 0, NULL)?1:0 );
					reg.WriteInteger("arc_lzh_or_zip_finmessage", BST_CHECKED == SendDlgItemMessage(hDlg, IDC_CHECK_FINISHMESSAGE, BM_GETCHECK, 0, NULL)?1:0 );
					reg.WriteInteger("arc_lzh_or_zip_shutdown", (int)SendDlgItemMessage(hDlg, IDC_COMBO_SHUTDOWN, CB_GETCURSEL, 0, NULL) );

					// 圧縮形式／圧縮率の選択肢を保存する
					// [LZH]
					reg.WriteInteger("arc_lzh_lhx", (DWORD)SendDlgItemMessage(hDlg, IDC_SELFORM_LZH, CB_GETCURSEL, 0, NULL));
					
					// [ZIP]
					reg.WriteInteger("arc_zip_zipx", (DWORD)SendDlgItemMessage(hDlg, IDC_SELFORM_ZIP, CB_GETCURSEL, 0, NULL));

					// [7z]
					reg.WriteInteger("arc_7z_7zx", (DWORD)SendDlgItemMessage(hDlg, IDC_SELFORM_7Z,  CB_GETCURSEL, 0, NULL));
					// マルチスレッド利用かどうか
					reg.WriteInteger("arc_lz_mt", BST_CHECKED == SendDlgItemMessage(hDlg, IDC_CHECK_MT, BM_GETCHECK, 0, NULL) ? 1 : 0);

					// 前回のファイル名として、ファイル名をレジストリへ書き込む（コンボボックス履歴とは別制御）
					reg.WriteStringFromEditbox("arc_lastname", hDlg, IDC_EDIT1);

					reg.CloseKey();
				}

				// リサイズのための情報を破棄
				delete sizedlg;
				sizedlg = NULL;

				// コンボボックスの情報を破棄
				delete cbq;
				cbq = NULL;
			}
			return TRUE;

		case WM_SIZE:
			sizedlg->Resize(1);
			return TRUE;

		case WM_GETMINMAXINFO:
			return sizedlg->GetMinMaxInfo(lParam);

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case IDOK:
					CallArchive(hDlg);
					return TRUE;

				case IDHELP:
					{
						// カレントフォルダがずれている可能性があるため、exeと同じ位置にあるhlpを
						// 探す
						char hlpname[MAX_PATH*2];
						int i;

						if ( GetModuleFileNameA(NULL, hlpname, _countof(hlpname)) ) {
							int i = lstrlen(hlpname);

							do {
								i--;
							} while(i>0 && (hlpname[i] != '\\' || isKanji1A(hlpname,i-1)));
							if (i > 0) {
								hlpname[i] = 0;
							}
						}
						lstrcat(hlpname, "\\RNSF7.CHM::/_RESOURCE/HLP000187.html");

						HtmlHelp(hDlg, hlpname, HH_DISPLAY_TOPIC, NULL);
					}
					return TRUE;

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

				case IDC_BUTTON_BROWSE:
					{
						OPENFILENAME ofn;
						char fname[MAX_PATH*2]="";
						int  selDll = selectedDll(hDlg);

						GetDlgItemText(hDlg, IDC_EDIT1, fname, _countof(fname));

						ofn.lStructSize = sizeof(OPENFILENAME);
						ofn.hwndOwner = hDlg;
						ofn.lpstrFilter = (selDll == OET_LZH?"LZH書庫(*.lzh)\0*.lzh\0自己解凍書庫(*.exe)\0*.exe\0すべてのファイル(*.*)\0*.*\0\0":
							               selDll == OET_ZIP?"ZIP書庫(*.zip;*.jar;*.xpi)\0*.zip;*.jar;*.xpi\0自己解凍書庫(*.exe)\0*.exe\0すべてのファイル(*.*)\0*.*\0\0":
										                     "7-ZIP書庫(*.7z)\0*.7z\0ZIP書庫(*.zip;*.jar;*.xpi)\0*.zip;*.jar;*.xpi\0自己解凍書庫(*.exe)\0*.exe\0すべてのファイル(*.*)\0*.*\0\0");
						ofn.nFilterIndex = 1;
						ofn.lpstrCustomFilter = (LPSTR) NULL;
						ofn.nMaxCustFilter = 0L;
						ofn.lpstrFile = fname;
						ofn.nMaxFile = _countof(fname);
						ofn.lpstrFileTitle = NULL;
						ofn.nMaxFileTitle = 0;
						ofn.lpstrInitialDir = NULL;
						ofn.lpstrTitle = "圧縮後のファイル名を指定";
						ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR | OFN_OVERWRITEPROMPT;
						ofn.nFileOffset = 0;
						ofn.nFileExtension = 0;
						ofn.lpstrDefExt = (selDll == OET_LZH?"lzh":
							               selDll == OET_ZIP?"zip":
										                     "7z"); 

						if (GetSaveFileName(&ofn)) {
							SetDlgItemText(hDlg, IDC_EDIT1, fname);
						}
					}			
					SetFocus(GetDlgItem(hDlg,IDC_EDIT1));
					return TRUE;

				case IDC_RADIO_LZH:
				case IDC_RADIO_ZIP:
				case IDC_RADIO_7Z:
					// 選択中でないDLLのリストボックスを隠す
					hide_listbox_change_ext(hDlg);
					return TRUE;

				case IDC_COMBO_SHUTDOWN:
					if ( HIWORD(wParam) != CBN_SELCHANGE ) {
						return TRUE;
					}
					// そのまま下へ
				case IDC_CHECK_NOTCLOSE:
				case IDC_CHECK_FINISHMESSAGE:
					DlgProc_OpenArchiver_CheckDisable(hDlg);
					return TRUE;

				case IDC_BUTTON_BROWSE_FILE:	// ファイル選択
					oa_SelectFiles(hDlg);
					return TRUE;

				case IDC_BUTTON_BROWSE_FOLDER:	// フォルダ選択
					oa_SelectFolder(hDlg);
					return TRUE;

				case IDC_BUTTON_CLEAR: // クリア
					SetDlgItemText(hDlg, IDC_EDIT_FILES, "");
					return TRUE;
			}
			break;
	}
    return FALSE;
}

// ドラッグ＆ドロップ圧縮用ウィンドウ
bool OpenArchiver( void )
{
	int drvl = call_unlha32(NULL, NULL);
	int drvz = call_zip32j(NULL, NULL, NULL, NULL);
	int drv7z = call_7zip32(NULL, NULL);

	if ( (drvl == T_TF_DLLNOTFOUND || drvl == T_TF_ILLEGALDLL) &&
		 (drvz == T_TF_DLLNOTFOUND || drvz == T_TF_ILLEGALDLL) &&
		 (drv7z == T_TF_DLLNOTFOUND || drv7z == T_TF_ILLEGALDLL) ) {
		MessageBox(NULL, UNLHA32DLL"、"ZIP32JDLL"、"SEVENZIP32DLL"がいずれも見つからないか、正しくありません。", 
#ifdef _WIN64
			"-圧縮- [x64]",
#else
			"-圧縮-",
#endif
			MB_OK | MB_ICONSTOP);
		return false;
	}
	return DialogBox(hInst, (LPCTSTR)IDD_OPEN_ARCHIVER, NULL, (DLGPROC)DlgProc_OpenArchiver)?true:false;
}
