// MainWindow.cpp :
// メインウインドウと、そのリストビュー

#include "stdafx.h"
#include "RNSF7.h"
#include "MainWindow.h"
#include "MainMenu.h"
#include "About.h"
#include "OpenSetting.h"
#include "refresh.h"
#include "addctrl.h"
#include "sakura.h"
#include "helpdlg.h"
#include "opendlg.h"
#include "splash.h"
#include "MainListview.h"
#include "MainCategory.h"
#include "MainNavigator.h"
#include "MainSearchRsc.h"
#include "MainStatusBar.h"
#include "ItemProp.h"
#include "commfunc.h"
#include "pre_interprete.h"
#include "inst.h"
#include "cpp_func.h"
#include "kwd_search.h"
#include "kwd_treectrl.h"
#include "regopendlg.h"
#include "MultiRnd.h"

// 変数
int	ItemCount;		// カレントディレクトリに存在する実行可能なスクリプトファイル総数
LPMLVI mlvi;			// スクリプトファイル一覧
char **categorys;	// スクリプトファイルの属するカテゴリ一覧 - カテゴリがない場合はNULL, ある場合は最終要素+1にNULL
HWND hMainWindow, hMainListView, hStatusBar, hCategoryTreeView;

// グローバル変数
bool bCategory = 1, bNavigator = 0;	// 画面右側のナビゲータとカテゴリ表示
bool bAutoUpdateCheck = 0;			// 起動時に自動的に更新確認を行うか
bool bR7recentChange = 1;			// 「最近使った機能項目」メニューを増減させるか
int  iLast_MaxRecent = -1;			// 直前に表示しようとしたときの「最近使った機能項目」のメニュー数

// メニューバーのメニュー
#define MW_MB_SETTING	0
#define MW_MB_SHOW		1
#define MW_MB_FIND		2
#define MW_MB_FAVORITE	3
#define MW_MB_TOOL		4
#define MW_MB_HELP		5

// 「最近使った機能項目」サブメニューは動的に増減する部分であるため位置で管理する。「設定」メニューのこの項目よりも前の
// メニューを追加したり削除したりする場合は、MainWindow.h の RECENTMENU_POS を変化させること。

// チュートリアルを開くために必要なファイル（優先度順）
// 注：CreateProcessがコマンドラインをLPTSTRで受け取るため、constにできない
char *rnsf7tfiles[] = {"Rnsf7t.rsc","Rnsf7t.hlp","Rnsf7t.chm","Rnsf7t.html","Rnsf7t.htm","Rnsf7t.pdf","Rnsf7t.doc","Rnsf7t.xls","Rnsf7t.jtd","Rnsf7t.sxw","Rnsf7t.sxc","Rnsf7t.rtf","Rnsf7t.wri","Rnsf7t.txt", NULL};

// 非表示スクリプト
int invisible_item_num = 4;
const char *invisible_item_rsc[] = {"RNSF7.rsc", "R7FAV.rsc", "R7HIST.rsc", "R7UPDATE.rsc"};
const char *invisible_item_name[] = {"オプション", "お気に入りの整理", "履歴管理", "更新確認機能の設定"};

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	int    n;
	static HMENU hMainMenu, hContextMenu, hContextMenu2, hContextMenuCategory;

	switch (message) {
		case R7MW_READY:
			// メインウィンドウの準備（再準備も含める）
			{
				HCURSOR hOrgCursor;

				hOrgCursor = SetCursor( LoadCursor(NULL, IDC_WAIT) );
				setStatusBarText( "カレントフォルダのスクリプトファイルから、機能項目の一覧を生成しています...", 0);

				// カレントディレクトリからスクリプトファイルの読み出し
				searchRSCs( hWnd );

				if ( bCategory ) {
					// 左にリストビューを作り、カテゴリリストを作成
					hCategoryTreeView = createCategoryTreeView( hWnd );
				}

				// リストビューコントロールの生成
				if ( NULL == ( hMainListView = createListView( hWnd ) ) ) {
					destroy_splash_window();
					MessageBox(hWnd, "リストビューコントロールを生成できませんでした", szTitle, MB_OK | MB_ICONSTOP);
					DestroyWindow( hWnd );
					return TRUE;
				}

				// リストビューのスタイルを変更
				ChangeLVStyle(hWnd, hMainListView, wLVStyle, 0);

				// リストビューのソート (デフォルトは、ファイル名順)
				startListviewSort( hMainListView, LVORDER_LAST );

				// ステータスバーを考慮して、リストビューのサイズを決める
				resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView);

				// リストビューにフォーカスを与える
				SetFocus( hMainListView );

				// ステータスバーを設定する
				setStatusBarText( NULL, 0 );

				// リストビューの第1項目にカーソルを合わせる
				// 第1項目目へのカーソルのセットと、カラムサイズの自動調整
				if (ItemCount > 0) {
					ListView_SetItemState(hMainListView, 0, LVIS_FOCUSED, LVIS_FOCUSED);
				}

				// ナビゲータの表示
				OpenNavigator(hWnd, hCategoryTreeView, hMainListView, hStatusBar);

				SetCursor( hOrgCursor );
			}
			break;

		case R7MW_DELETEICONS:
			// メインウィンドウ上のリストビューの削除（再準備も含める）
			{
				// アイテムの削除
				ListView_DeleteAllItems(hMainListView);
				// グループの削除（可能な場合）
				if (winver >= 501) ListView_RemoveAllGroups(hMainListView);
				// リストビューのアイコンリストを削除
				ImageList_Destroy(ListView_GetImageList(hMainListView, LVSIL_SMALL));
				ImageList_Destroy(ListView_GetImageList(hMainListView, LVSIL_NORMAL));
				// 構造体中の各メモリの解放
				if ( mlvi ) {
					for(n=0 ; n<ItemCount ; n++) { // アイテムリストを削除
						// ITEM指定なしの場合はファイル名になるが、その場合はメモリ領域をrsc_fnameと共有しているので解放する必要はない
						if ( mlvi[n].item != mlvi[n].rsc_fname ) {
							safefree( mlvi[n].item );
						}
						//INFORMATOIN指定なしの場合はファイル名になるが、その場合はメモリ領域をrsc_fnameと共有しているので解放する必要はない
						if ( mlvi[n].info != mlvi[n].rsc_fname ) {
							safefree( mlvi[n].info );
						}
						safefree( mlvi[n].rsc_fname );
						safefree( mlvi[n].help );
						safefree( mlvi[n].author );
						safefree( mlvi[n].url );
						mlvi[n].category = NULL; // カテゴリは共通のポインタを差しているのでここでは解放しない
						if ( mlvi[n].hicon ) {
							// 過去に同じハンドルのアイコンを解放していないかもチェック
							int j;
							for(j=0 ; j<n ; j++) {
								if ( mlvi[n].hicon == mlvi[j].hicon ) {
									break;
								}
							}	
							if ( n == j ) { // 過去に同じハンドルのアイコンは解放されていなかった
								DestroyIcon( mlvi[n].hicon );
							}
						}
						if ( mlvi[n].hSmallIcon && mlvi[n].hSmallIcon != mlvi[n].hicon ) {
							// 過去に同じハンドルのアイコンを解放していないかもチェック
							int j;
							for(j=0 ; j<n ; j++) {
								if ( mlvi[n].hSmallIcon == mlvi[j].hSmallIcon ||
									mlvi[n].hSmallIcon == mlvi[j].hicon ) {
									break;
								}
							}	
							if ( n == j ) { // 過去に同じハンドルのアイコンは解放されていなかった
								DestroyIcon( mlvi[n].hSmallIcon );
							}
						}
					}
					safefree(mlvi);
				}

				// カテゴリの削除
				if ( categorys ) {
					for(n=0 ; categorys[n] ; ++n) {
						safefree( categorys[n] );
					}
					safefree( categorys ); 
				}
			}
			break;

		case WM_CREATE:
			// メインウィンドウのハンドルを外部変数にコピー
            hMainWindow = hWnd;

			// ステータスバーの生成
			hStatusBar = createStatusBar( hWnd );

			// メニューハンドラの取得
			hMainMenu = GetMenu(hWnd);	// メインメニュー
			hContextMenu = LoadMenu(hInst, (LPSTR)IDR_CONTEXT_MENU);		// アイテムがマークされているときのコンテキストメニュー
			hContextMenu2 = LoadMenu(hInst, (LPSTR)IDR_CONTEXT_MENU2);	// アイテムがマークされていないときのコンテキストメニュー
			hContextMenuCategory = LoadMenu(hInst, (LPSTR)IDR_CONTEXT_MENUCATEGORY); // カテゴリ表示でカーソルがないときのコンテキストメニュー

			// メニューのデフォルトを太字にする
			SetMenuDefaultItem(GetSubMenu(hMainMenu,MW_MB_SETTING),0,TRUE);
			SetMenuDefaultItem(GetSubMenu(hContextMenu,0),0,TRUE);

			// Toolsメニュー内の項目が利用できるかどうかを確認
			if (isNT && winver >= 500) {
				if (winver < 600) { // Windows Vista以降では、NTBackupは存在しない
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_BACKUPREGISTRY, MF_BYCOMMAND | MF_ENABLED);
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_RESTOREREGISTRY, MF_BYCOMMAND | MF_ENABLED);
				}
				if (winver > 500 && winver != 502) { // Windows Server 2003には、どうやらシステムの復元機能はないらしい
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_SYSTEMRESTORE, MF_BYCOMMAND | MF_ENABLED);
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_MAKERPXP, MF_BYCOMMAND | MF_ENABLED);
				}
			}
#if _MSC_VER < 1500
#ifndef _WIN64
			if (!isNT) {
				EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_BACKUPREGISTRY, MF_BYCOMMAND | MF_ENABLED);
				EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_RESTOREREGISTRY, MF_BYCOMMAND | MF_ENABLED);
				if (winver >= 490) {
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_SYSTEMRESTORE, MF_BYCOMMAND | MF_ENABLED);
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_MAKERPXP, MF_BYCOMMAND | MF_ENABLED);
				}
			}
			if (!isNT && winver >= 410) {
				EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_OPTIMIZEREGISTRY, MF_BYCOMMAND | MF_ENABLED);
			}
#endif /* _WIN64 */
#endif // _MSC_VER < 1500
			if ( (!isNT && winver >= 410) || (isNT && winver >= 501) ) {
				EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_MSCONFIG, MF_BYCOMMAND | MF_ENABLED);
			}
			if (winver >= 490) {
				// キーを指定してレジストリを開く
				EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_KEYREGEDIT, MF_BYCOMMAND | MF_ENABLED);
			}

			// GodModeを呼び出す。ただし、Vista 64bitではクラッシュするという情報があるため、呼び出させない。
#ifndef _WIN64
			if (isNT && winver >= 600 && (winver >= 601 || ccpu32_IsWow64Process() == FALSE) ) {
#else  /* _WIN64 */
			if (isNT && winver >= 601) {
#endif /* _WIN64 */
				EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_WIN7GM, MF_BYCOMMAND | MF_ENABLED);
			}
			{
				// Syseditは64bitでは存在しなさそうなので、いちおう検索する
				char szPath[MAX_PATH*2], *pszPart;

				if (0 == SearchPath(NULL, "SYSEDIT.EXE", NULL, _countof(szPath), szPath, &pszPart)) {
					// Sysedit見つからず
					EnableMenuItem(GetSubMenu(GetMenu(hWnd),MW_MB_TOOL), ID_TOOLS_SYSEDIT, MF_BYCOMMAND | MF_GRAYED);
				}
			}
			break;


		case WM_PAINT:
			{
				PAINTSTRUCT ps;
				HDC hdc;

				hdc = BeginPaint(hWnd, &ps);
				if ( hdc ) {
					ShowNavigator(hWnd, hdc, hCategoryTreeView, hMainListView, hStatusBar);
					EndPaint(hWnd,&ps);
				}
			}
			break;

		case WM_MENUSELECT:
			{ // ステータスバーに説明を表示
				UINT uItem = (UINT) LOWORD(wParam);
				UINT fuFlags = (UINT) HIWORD(wParam);
				HMENU hmenu = (HMENU) lParam;	

				if (fuFlags == 0xffff && hmenu == NULL) {
					setStatusBarText( NULL, 0);
				}
				else {
					if ( setStatusBarHelp( uItem ) ) {
						switch(uItem) { // サーチアウトしたら
							case MW_MB_HELP: // ヘルプメニュー
								if ( hmenu == hMainMenu ) {
									char helpfile[MAX_PATH*2], *p = NULL;
									int  i;

									// ヘルプ・ドキュメントライブラリの無効化または有効化
									if ( 0 != SearchPath(NULL, "RNSF7.CHM", NULL, _countof(helpfile), helpfile, &p) ) {
										EnableMenuItem(hMainMenu, IDM_HELP_KIFU, MF_BYCOMMAND | MF_ENABLED );
										EnableMenuItem(hMainMenu, IDM_HELP_HELP, MF_BYCOMMAND | MF_ENABLED );
										EnableMenuItem(hMainMenu, IDHELP_RSCRIPT, MF_BYCOMMAND | MF_ENABLED );
										EnableMenuItem(hMainMenu, IDHELP_DOCLIB, MF_BYCOMMAND | MF_ENABLED );
									}
									else {
										EnableMenuItem(hMainMenu, IDM_HELP_KIFU, MF_BYCOMMAND | MF_GRAYED );
										EnableMenuItem(hMainMenu, IDM_HELP_HELP, MF_BYCOMMAND | MF_GRAYED );
										EnableMenuItem(hMainMenu, IDHELP_RSCRIPT, MF_BYCOMMAND | MF_GRAYED );
										EnableMenuItem(hMainMenu, IDHELP_DOCLIB, MF_BYCOMMAND | MF_GRAYED );
									}

									// アップデート確認の設定の有効／無効
									EnableMenuItem(hMainMenu, ID_HELP_UPDATECHECKSET, MF_BYCOMMAND | (tFileExist( "R7UPDATE.RSC" )?MF_ENABLED:MF_GRAYED) );

									// チュートリアルの有効／無効
									for(i=0; rnsf7tfiles[i] ; ++i) {
										if ( tFileExist(rnsf7tfiles[i]) )
											break;
									}

									// rnsf7tfiles[i] == NULL でサーチアウトしたとみなす
									EnableMenuItem(hMainMenu, IDM_HELP_RNSF7T, MF_BYCOMMAND | (rnsf7tfiles[i] ? MF_ENABLED : MF_GRAYED) );

									setStatusBarText( "このプログラムのヘルプや、アップデート確認機能の実行・設定です。", 1);
								}
								break;

							case MW_MB_SHOW: // 表示メニュー
								// 表示メニューが開かれたら、選択中の項目をラジオとして表示する
								if ( hmenu == hMainMenu ) {
									int m;

									// リストビューの表示スタイル
									switch( wLVStyle ) {
										case 1 : m = ICO_LARGE; break;
										case 2 : m = ICO_SMALL; break;
										case 3 : m = ICO_LIST; break;
										default: m = ICO_REPORT; break;
									}
									CheckMenuRadioItem(hMainMenu, ICO_LARGE, ICO_REPORT, m, MF_BYCOMMAND);

									// リストビューのソート基準
									switch( rnsf7RegRead("LastSort", 3) ) {
										case -1:
										case 1 : m = IDM_VIEW_ITEM; break;
										case -2:
										case 2 : m = IDM_VIEW_INFORMATION; break;
										case -4:
										case 4 : m = IDM_VIEW_TIME; break;
										case -5:
										case 5 : m = IDM_VIEW_SIZE; break;
										case -6:
										case 6 : m = IDM_VIEW_AUTHOR; break;
										case 99: if (winver >= 501) {m = IDM_VIEW_GROUPVIEW; break;}
										default: m = IDM_VIEW_FILE; break;
									}
									CheckMenuRadioItem(hMainMenu, IDM_VIEW_ITEM, IDM_VIEW_GROUPVIEW, m, MF_BYCOMMAND);
#if _MSC_VER < 1500
#ifndef _WIN64
									if (winver < 501) {
										// グループ分けして表示できるのはWindows XP以降
										EnableMenuItem(hMainMenu, IDM_VIEW_GROUPVIEW, MF_BYCOMMAND | MF_GRAYED);
									}
#endif /* _WIN64 */
#endif // _MSC_VER < 1500
									// リストビューの第1項目をファイル名にする
									CheckMenuItem(hMainMenu, IDM_VIEW_FIRSTITEMFILE, (bLVFirstItemFile?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

									// カテゴリ分類を利用する
									CheckMenuItem(hMainMenu, IDM_VIEW_LISTBOX, (bCategory?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

									// ナビゲータを利用する
									CheckMenuItem(hMainMenu, IDM_VIEW_NAVIGATOR, (bNavigator?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

									// 詳細表示でアイテム数が1以上であれば、カラム幅を自動調整するメニューを有効にする
									EnableMenuItem(hMainMenu, IDM_VIEW_AUTOCOLUMN, ((wLVStyle == 0 && ListView_GetItemCount(hMainListView) > 0)?MF_ENABLED:MF_GRAYED) | MF_BYCOMMAND );

									setStatusBarText( "機能項目の一覧の表示方法や、メインウィンドウの表示方法の設定です。", 1);
								}
								break;

							case MW_MB_SETTING:
								// == 0「設定(S)」メニューが開かれたら、リストビューのカーソルがなにかの項目に設定されているかどうかを確認し、「開く(O)」メニューを有効/無効化する
								if ( hmenu == hMainMenu ) {
									REG   reg;
									int   i = 0, j = 0;
									char  *name = NULL, *name2 = NULL;
									char  s[50], n[14];
									int   iMaxRecent = 0; // 管理される数

									EnableMenuItem(hMainMenu, ID_SETTINGS_OPEN, ((-1 == GetLVCursor(hMainListView))?MF_GRAYED:MF_ENABLED) | MF_BYCOMMAND );
									// 「オプション」はRnsf7.rscが存在しなければ無効
									EnableMenuItem(hMainMenu, ID_SETTINGS_SETTING, MF_BYCOMMAND | (tFileExist( "RNSF7.RSC" )?MF_ENABLED:MF_GRAYED) );
									// 「履歴管理」はR7hist.rscが存在しなければ無効
									EnableMenuItem(hMainMenu, ID_SETTINGS_HISTORY, MF_BYCOMMAND | (tFileExist( "R7HIST.RSC" )?MF_ENABLED:MF_GRAYED) );

									// ↓関係のないところでもこのメッセージが表示されてしまうので、表示はしないことにする
									// setStatusBarText( "選択された項目を開いたり、このプログラム自身の設定を行ったりします。", 1);
									setStatusBarText("", 1);

									// 「最近使った機能項目」のメニュー数についても調べ、変化があったら読み出しを行う
									if ( reg.OpenSubKey(HKEY_CURRENT_USER, RNSF7REGKEY, "R7RECENT", TREG_OPEN_READONLY) ) {
										iMaxRecent = reg.ReadInteger( "MaxRecent", RECENTDEF );
										if ( iMaxRecent < 0 || RECENTMAX < iMaxRecent ) {
											// レジストリに記述された数がありえない数だった場合はデフォルトにする
											iMaxRecent = RECENTDEF;
										}
										reg.CloseKey();
									}
									if (iMaxRecent != iLast_MaxRecent) {
										bR7recentChange = 1;
									}

									// 最近使った機能項目の読み出し(変化があった場合のみ)
									// レジストリから項目をロード
									if (bR7recentChange) {
										// bR7recentChangeが1にされるまでは、次の更新はなし
										bR7recentChange = 0;

										// ロードの前に、「最近使った機能項目」全メニューの削除
										for(i=0 ; i<RECENTMAX ; ++i) {
											DeleteMenu(hMainMenu, ID_RECENT_1+i, MF_BYCOMMAND);
										}

										// サブメニューのハンドルを取得
										HMENU hRecentMenu = GetSubMenu(GetSubMenu(hMainMenu, MW_MB_SETTING), RECENTMENU_POS);

										//InsertMenuを使って、メニュー数を動的に変化させる
										if ( reg.OpenSubKey(HKEY_CURRENT_USER, RNSF7REGKEY, "R7RECENT", TREG_OPEN_READONLY) ) {
											iLast_MaxRecent = iMaxRecent;

											for(i=j=0 ; i<iMaxRecent ; ++i) {
												wsprintf(s, "r7r_item%d", i+1);
												name = reg.new_ReadString(s);
												if ( name ) {
													wsprintf(n, "(&%d)", (j+1)%10);
													name2 = new_strcat(name, n);
													if ( name2 ) name = name2; // 名前がなければファイル名
													InsertMenu(hRecentMenu, j, MF_BYPOSITION, ID_RECENT_1+i, name);
													safedelete(name);
													++j;
												}
											}
											reg.CloseKey();
										}

										if ( j == 0 ) {
											// 何も表しない場合は、グレイアウトしたメニューを1つ表示
											InsertMenu(hRecentMenu, 0, MF_BYPOSITION | MF_GRAYED | MF_STRING, ID_RECENT_1, "(なし)");
										}
									}

									DrawMenuBar(hWnd);
								}
								break;

							case MW_MB_FAVORITE: // お気に入りメニュー
								// レジストリから項目をロード
								if ( hmenu == hMainMenu ) {
									REG   reg;
									int   i;
									DWORD len, len2;
									char  *name;

									// 「お気に入りの追加」メニューは、設定項目がなければ無効
									EnableMenuItem(hMainMenu, IDM_FAVORITE_ADD, ((-1 == GetLVCursor(hMainListView))?MF_GRAYED:MF_ENABLED) | MF_BYCOMMAND );
									// 「お気に入りの整理」メニューはr7fav.rscがなければ無効
									EnableMenuItem(hMainMenu, IDM_FAVORITE_EDIT, MF_BYCOMMAND | (tFileExist( "R7FAV.RSC" )?MF_ENABLED:MF_GRAYED) );

									// ロードの前にメニューの削除
									for(i=0 ; i<100 ; ++i) {
										if ( 0 == DeleteMenu(hMainMenu, IDM_FAVORITE_001+i, MF_BYCOMMAND) ) {
											// 失敗＝終了
											break;
										}
									}

									if ( reg.OpenSubKey(HKEY_CURRENT_USER, RNSF7REGKEY, "R7FAV", TREG_OPEN_READONLY) ) {
										HKEY hKey = reg.GetHKey();

										RegQueryInfoKey( hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &len, NULL, NULL, NULL);
										len = (len+1)*2; // WinNT系での対策
										name = zalloc( len );
										if ( name ) {
											// IDM_FAVORITE_001 から 100個まで
											for(i=0 ; i<100 ; ++i) {
												len2 = len;
												if ( ERROR_SUCCESS == RegEnumValue( hKey, i, name, &len2, NULL, NULL, NULL, NULL ) ) {
													if ( AppendMenu(GetSubMenu(hMainMenu, MW_MB_FAVORITE), MF_STRING, IDM_FAVORITE_001+i, name) ) {
														; // 今のところ、特に何もしない
													}
													else
														break;
												}
												else
													break;
											}
											safefree( name );
										}
										reg.CloseKey();
									}

									setStatusBarText("このプログラム内のお気に入り機能に関する項目です。", 1);
									DrawMenuBar(hWnd);
								}
								break;

							case MW_MB_TOOL: // ツールメニュー
								if ( hmenu == hMainMenu ) {
									setStatusBarText("各種関連ツールの呼び出しを行います。", 1);
								}
								break;

							default:
								setStatusBarText("", 1);
								break;
						}
					}
				}
				break;
			}

		case R7MW_STATUS_BAR: // (WM_APP+2) ステータスバーを変える
			setStatusBarText((char *)lParam, (short)wParam);
			break;

		case WM_SIZE: // ウィンドウのサイズ変更
			SendMessage(hStatusBar, WM_SIZE, wParam, lParam);
		    resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView);
			// ↑ 1, hListBoxは条件により要修正!!!
			break;

		case WM_NOTIFY: // リストビュー・ツリービューへのメッセージ他
			if (((LPNMHDR)lParam)->hwndFrom == hMainListView) {
				int n;

				switch (((LPNMHDR)lParam)->code) {
					case NM_DBLCLK: // リストビュー内でダブルクリックされたら
						if ( 0 <= (n = GetLVCursor( hMainListView )) ) {
							SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
							OpenSetting( hWnd, &mlvi[(int)lvGetLParam(hMainListView, n)], hStatusBar );
						}
						break;

					case LVN_GETINFOTIP: // リストビューのスタイルが「詳細」以外だったら、InfoTipには説明を表示する
						if (wLVStyle != 0) { // (このメッセージは Comctl ver.4.71+)
							LPNMLVGETINFOTIP pGetInfoTip = (LPNMLVGETINFOTIP)lParam;

							pGetInfoTip->pszText = mlvi[(int)lvGetLParam(hMainListView, pGetInfoTip->iItem)].info;
							pGetInfoTip->cchTextMax = lstrlen(pGetInfoTip->pszText);
						}
						break;

					case LVN_ITEMCHANGED: // アイテムがかわった
						// ナビゲータの再表示
						OpenNavigator( hWnd, hCategoryTreeView, hMainListView, hStatusBar );
						// ステータスバーの再表示
						setStatusBarText( NULL, 0 );
						break;

					case LVN_COLUMNCLICK: // ヘッダがクリックされたら
						{ // ComCtl ver.4.70より前で、NMLISTVIEW が正しく使えるのかどうかは…不明
							int iColumn = ((LPNMLISTVIEW)lParam)->iSubItem;

							if ( bLVFirstItemFile ) { // 最初の項目をファイル名にする場合
								if ( iColumn == 0 ) {
									startListviewSort( hMainListView, LVORDER_FILE_ASC );
								}
								else if ( iColumn == 1 ) {
									startListviewSort( hMainListView, LVORDER_NAME_ASC );
								}
								else if ( iColumn == 2 ) {
									startListviewSort( hMainListView, LVORDER_INFO_ASC );
								}
								else {
									startListviewSort( hMainListView, iColumn + 1 );
								}
							}
							else {
								startListviewSort( hMainListView, iColumn + 1 );
							}
						}
						break;
				}
			}
			else if ( ((LPNMHDR)lParam)->hwndFrom == hCategoryTreeView ) {
				// カテゴリボックス
				if ( ((LPNMHDR)lParam)->code == TVN_SELCHANGED ) {
					// カテゴリが選び直された
					LPNMTREEVIEW pnmtv = (LPNMTREEVIEW)lParam;

					// 選択されたカテゴリ分類に合わせてリストビューを再表示
					showListView( hMainListView, (int)(pnmtv->itemNew.lParam) );

					// ナビゲータの表示
					OpenNavigator(hWnd, hCategoryTreeView, hMainListView, hStatusBar);

					// ソートorグループ表示
					startListviewSort(hMainListView, LVORDER_LAST);
				}
			}
			break;

		case WM_DROPFILES: // lzh,zip,7z ファイルの展開, rsc,rndの実行と適用
			SetForegroundWindow( hWnd );
			if (IDYES == MessageBox(hWnd, "ドロップされたファイルがlzh/zip/7zファイルの場合、カレントフォルダに展開を試みます。\nドロップされたファイルがrscファイルの場合はスクリプトとして実行します。\nドロップされたファイルがrndファイルの場合は、ダイアログ状態として読み込み、その状態を適用済みの状態で開きます。\nよろしいですか?\n\n※複数のファイルをドロップした場合、順次処理されていきますが、次のファイルの処理へ移るときに[Shift]キーを押しておくと、処理が中止されます。", "", MB_YESNO | MB_ICONQUESTION)) {
				char lzhname[MAX_PATH*2];
				UINT n, i, l; // n:ドロップされたファイルの総数, i:ファイルの番号, l:ファイル名の長さ
				bool f = 0; // 1つ以上のファイルを処理したか?
				char *rnd_drop_mes = NULL; // 一回のdropで一回のみ表示するメッセージ
				char szOutputBuf[ARCDLL_OUTBUFSIZE+1];
				int  rv_dll;

				n = DragQueryFile((HDROP)wParam, (UINT)-1, NULL, 0); // ドロップされたファイルの総数を得る

				if (n >= 2) tp_nreboot = 1; // 一時的に再起動を禁止する
				for( i=0 ; i<n ; i++ ) {
                    DragQueryFile((HDROP)wParam, i, lzhname, _countof(lzhname));
					l = lstrlen( lzhname );

					if ( GetAsyncKeyState(VK_SHIFT)&0x8000 ) { // Shiftキーが押されていると中断
						char mes[MAX_PATH*2+100];

						wsprintf( mes, "次は%sを処理するところですが、[Shift]キーが押されたため、処理を中断します。\nよろしいですか?", lzhname );
						if ( IDYES == MessageBox( hWnd, mes, "中断確認", MB_OK | MB_ICONQUESTION | MB_YESNO ) ) {
							break;
						}
					}
					else {
						char mes[MAX_PATH*2+60];

						wsprintf( mes, "%sを処理中です...　　　　　※[Shift]キーで中断します", lzhname );
						setStatusBarText( mes, 0 );
					}


					if ( l > 4 ) {
						if ( 0 == _stricmp(&lzhname[l-4], ".rsc") ) { // 拡張子がrscだった場合、スクリプトファイルであるとして実行する
							openrsc( hWnd, lzhname, NULL );
						}
						if ( 0 == _stricmp(&lzhname[l-4], ".rnd") ) { // 拡張子がrndだった場合 - ダイアログ状態定義ファイルであるとみなして読み込み
							if ( rnd_drop_mes == NULL ) { // 最初の一回だけ表示
								rnd_drop_mes = "状態定義ファイルを読み込みます。\n読み込んだ内容で問題なければ、[OK]ボタンを押していって下さい。\n複数の状態定義ファイルがある場合は、複数回[OK]を押すことになりますが、レジストリを扱うものですので、必ず全てについてよく確認して下さい。\n\n※異なる環境で作られたrndファイルを読み込ませないでください。特にOSが異なる（Windows XPで作られたrndファイルをVistaに入れたり、x86版で作られたrndファイルをx64版に入れたりする）場合、レジストリの使われ方が異なることがあり、予期せぬ結果を招くことがあります。";
								MessageBox( hWnd, rnd_drop_mes, "ダイアログ状態の読み込み", MB_OK | MB_ICONINFORMATION );
							}
							openrsc( hWnd, lzhname, NULL );
						}
						else if (0 == _stricmp(&lzhname[l-4], ".lzh")) { // lzhファイルだった場合DLLを使って展開
							switch ( rv_dll = call_unlha32_log(hWnd, lzhname, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
								case T_TF_SUCCESS:
									f = 1; // リフレッシュフラグON
									break;

								case T_TF_DLLNOTFOUND:
								case T_TF_ILLEGALDLL:
#ifndef _WIN64
									MessageBox(hWnd, rv_dll == T_TF_DLLNOTFOUND ? "Unlha32.dllが見つかりません。" : "Unlha32.dllが正しくありません。", "ファイルの展開", MB_OK | MB_ICONSTOP);
									i = n; // そのまま終了
#else  /* _WIN64 */
									{ // もしかしたら32bit版DLLが存在しているかもしれないので、そちらをexe経由で呼び出してみる
										char buf[540];
										wsprintf(buf, "context_x86.exe /LX%s", lzhname);
										if (ERRORVALUE == runProgram_sync(buf)) {
											MessageBox(hWnd, "context_x86.exe /LXを実行できません。", "ファイルの展開", MB_OK | MB_ICONSTOP);
											i = n; // そのまま終了
										}
										else {
											f = 1; // 結果は分からないが、とりあえずリフレッシュフラグON
										}
									}
#endif /* _WIN64 */
									break;

								case T_TF_ERROR:
									ShowOutputDlg(hWnd, "LZHファイルの展開を中断したか、失敗しました。", "ファイルの展開", szOutputBuf, MB_ICONSTOP | MB_OK);
									break;
							}
						}
						else if (0 == _stricmp(&lzhname[l-4], ".zip")) { // zipファイルだった場合DLLを使って展開
							if (lzhname[0] == '-') {
								if ( IDYES != MessageBox(hWnd, "半角ハイフン(-)で始まるzipファイルを扱うことができない可能性があります。このファイルを処理しますか?", lzhname, MB_YESNO | MB_ICONQUESTION) ) {
									continue;
								}
							}
							else {
								switch ( rv_dll = call_unzip32_log(hWnd, lzhname, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
									case T_TF_SUCCESS:
										f = 1; // リフレッシュフラグON
										break;

									case T_TF_DLLNOTFOUND:
									case T_TF_ILLEGALDLL:
										// 通常のUnzip32.dll呼出しに失敗した場合、Windows XP以降であれば、OS標準のzip展開機能の
										// 呼出しを試みる。
										if (winver >= 501) {
											LPWSTR wstr_zipname = mb2wc(lzhname);
											if (wstr_zipname) {
												WCHAR wstr_cdir[MAX_PATH*2];
												// 展開先はカレントディレクトリ
												if (0 < GetCurrentDirectoryW(_countof(wstr_cdir), wstr_cdir)) {
													if (Shell_UnZipW(wstr_zipname, wstr_cdir)) {
														f = 1; // リフレッシュフラグON
														safefree(wstr_zipname);
														break;
													}
												}
												safefree(wstr_zipname);
											}
										}
#ifndef _WIN64
										MessageBox(hWnd, rv_dll == T_TF_DLLNOTFOUND ? "Unzip32.dllが見つかりません。" : "Unzip32.dllが正しくありません。", "ファイルの展開", MB_OK | MB_ICONSTOP);
										i = n; // そのまま終了
#else  /* _WIN64 */
										{ // もしかしたら32bit版DLLが存在しているかもしれないので、そちらをexe経由で呼び出してみる
											char buf[540];
											wsprintf(buf, "context_x86.exe /ZX%s", lzhname);
											if (ERRORVALUE == runProgram_sync(buf)) {
												MessageBox(hWnd, "context_x86.exe /ZXを実行できません。", "ファイルの展開", MB_OK | MB_ICONSTOP);
												i = n; // そのまま終了
											}
											else {
												f = 1; // 結果は分からないが、とりあえずリフレッシュフラグON
											}
										}
#endif /* _WIN64 */
										break;

									case T_TF_ERROR:
										{
											char *szOutputBuf2 = replacestr(szOutputBuf, "\n", "\r\n");
											ShowOutputDlg(hWnd, "ZIPファイルの展開を中断したか、失敗しました。", "ファイルの展開", szOutputBuf2, MB_ICONSTOP | MB_OK);
											safefree(szOutputBuf2);
										}
										break;
								}
							}
						}
						else if (0 == _stricmp(&lzhname[l-3], ".7z")) { // 7zファイルだった場合DLLを使って展開
							switch ( rv_dll = call_7zip32_log(hWnd, lzhname, szOutputBuf, ARCDLL_OUTBUFSIZE) ) {
								case T_TF_SUCCESS:
									f = 1; // リフレッシュフラグON
									break;

								case T_TF_DLLNOTFOUND:
								case T_TF_ILLEGALDLL:
#ifndef _WIN64
									MessageBox(hWnd, rv_dll == T_TF_DLLNOTFOUND ? "7-zip32.dllが見つかりません。" : "7-zip32.dllが正しくありません。", "ファイルの展開", MB_OK | MB_ICONSTOP);
									i = n; // そのまま終了
#else  /* _WIN64 */
									{ // もしかしたら32bit版DLLが存在しているかもしれないので、そちらをexe経由で呼び出してみる
										char buf[540];
										wsprintf(buf, "context_x86.exe /7X%s", lzhname);
										if (ERRORVALUE == runProgram_sync(buf)) {
											MessageBox(hWnd, "context_x86.exe /7Xを実行できません。", "ファイルの展開", MB_OK | MB_ICONSTOP);
											i = n; // そのまま終了
										}
										else {
											f = 1; // 結果は分からないが、とりあえずリフレッシュフラグON
										}
									}
#endif /* _WIN64 */
									break;

								case T_TF_ERROR:
									ShowOutputDlg(hWnd, "7zファイルの展開を中断したか、失敗しました。", "ファイルの展開", szOutputBuf, MB_ICONSTOP | MB_OK);
									break;
							}

						}
					}
				}
				tp_nreboot = 0; // 再起動禁止を解除

				if ( f ) { // リストビューを作り直す
					SendMessage( hWnd, WM_COMMAND, IDM_VIEW_RELOAD, NULL );
				}
				// ステータスバーを元に戻す
				setStatusBarText( NULL, 0 );
			}
			DragFinish((HDROP)wParam);
			break;

		case R7MW_SAVESETTINGS: // 設定の保存
			{
				REG reg;

				if ( reg.OpenKey(HKEY_CURRENT_USER, RNSF7REGKEY, TREG_OPEN_CREATE) ) {
					WINDOWPLACEMENT wp;
					RECT rc;
					POINT po;
					char lvColumnWidthValue[20];
					int i;

					wp.length = sizeof(WINDOWPLACEMENT);
					if ( GetWindowPlacement(hWnd, &wp) ) {
						reg.WriteInteger( "wMax",   wp.showCmd == SW_SHOWMAXIMIZED );
						reg.WriteInteger( "wLeft",  wp.rcNormalPosition.left );
						reg.WriteInteger( "wTop",   wp.rcNormalPosition.top );
						reg.WriteInteger( "wWidth", wp.rcNormalPosition.right - wp.rcNormalPosition.left );
						reg.WriteInteger( "wHeight",wp.rcNormalPosition.bottom - wp.rcNormalPosition.top );
					}

					// リストビューのスタイル
					reg.WriteInteger( "wLVStyle", wLVStyle );
					// リストビューの第1項目をファイル名にする
					reg.WriteInteger( "bLVFirstItemFile", bLVFirstItemFile );

					// カテゴリ表示
					reg.WriteInteger( "bCategory", bCategory );
					// ナビゲータ表示
					reg.WriteInteger( "bNavigator", bNavigator );

					// 縦のバーが存在→x座標を記録
					if ( hBar ) {
						GetWindowRect( hBar, &rc );
						po.x = rc.left;
						po.y = rc.top;
						ScreenToClient( hWnd, &po );
                        reg.WriteInteger( "iBarVx", po.x );
					}
					else {
                        reg.DeleteValue( "iBarVx" );
					}

					// 横のバーが存在→y座標を記録
					if ( hBarh ) {
						GetWindowRect( hBarh, &rc );
						po.x = rc.left;
						po.y = rc.top;
						ScreenToClient( hWnd, &po );
                        reg.WriteInteger( "iBarHy", po.y );
					}
					else {
						reg.DeleteValue( "iBarHy" );
					}

					if ( wLVStyle == 0 ) { // 詳細モードだったら、各カラムのサイズを保存する
						// リストビューの各カラムのサイズ
						for(i=0 ; i<NUMCOLUMN ; i++) {
							wsprintf( lvColumnWidthValue, "lvColumnWidth%d", i );
							reg.WriteInteger( lvColumnWidthValue, ListView_GetColumnWidth(hMainListView, i) );
						}
					}

					reg.CloseKey();
				}
				else {
					dispErrorMessage(hWnd, MB_OK | MB_ICONSTOP, "レジストリへの書き込み中エラー", "レジストリキー'HKEY_CURRENT_USER\\", RNSF7REGKEY,
									 "'を書き込みアクセスで開こうとしてエラーになりました。\nAPIが報告した原因：", getLastErrorString(tRegGetLastError()), NULL, NULL);
				}
			}
			break;
			
		case WM_DESTROY: // ウィンドウの破棄
			// 設定の保存
			SendMessage(hWnd, R7MW_SAVESETTINGS, 0, NULL);
			// リストビューの削除
			SendMessage(hWnd, R7MW_DELETEICONS, 0, NULL);

			// メニュー・コンテキストメニューの解放
			DestroyMenu( hMainMenu );
			DestroyMenu( hContextMenu );
			DestroyMenu( hContextMenu2 );
			DestroyMenu( hContextMenuCategory );

			// ナビゲータフォントの削除
			if ( ui_font ) {
				DeleteObject( ui_font );
				ui_font = NULL;
			}
			if ( bold_font ) {
                DeleteObject( bold_font );
				bold_font = NULL;
			}
			if ( uline_font ) {
                DeleteObject( uline_font );
				uline_font = NULL;
			}

			PostQuitMessage( 0 );
			break;

		case WM_RBUTTONDOWN: // ナビゲータ上で右クリック(押された)
			{
				HMENU hMenu;
				POINT pt;
				
				GetCursorPos(&pt);
				hMenu = GetSubMenu(hContextMenuCategory, 0);
				if ( hMenu ) {
					// カテゴリ分類を利用する
					CheckMenuItem(hMenu, IDM_VIEW_LISTBOX, (bCategory?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

					// ナビゲータを利用する
					CheckMenuItem(hMenu, IDM_VIEW_NAVIGATOR, (bNavigator?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

					// メニューを表示
					TrackPopupMenuEx(hMenu, 0, pt.x, pt.y, hWnd, NULL);
				}
			}
			break;

		case WM_LBUTTONDOWN:
			{
				RECT rc;
				POINT po;
				po.x = LOWORD(lParam);  // horizontal position of cursor 
				po.y = HIWORD(lParam);  // vertical position of cursor 
				ClientToScreen( hWnd, &po );

				if ( hBar ) {
					GetWindowRect( hBar, &rc );
					if ( rc.left-1 < po.x && po.x < rc.right+1 && rc.top < po.y && po.y < rc.bottom ) {
						SetCapture( hWnd );
						lbdx = po.x - rc.left;
						if ( lbdx == 0 ) {
							lbdx = 1;
						}
						SetWindowLongPtr( hBar, GWL_STYLE, WS_CHILD|WS_VISIBLE|SS_BLACKRECT );
						InvalidateRect( hBar, NULL, TRUE );
						SetCursor(LoadCursor(NULL, IDC_SIZEWE));
						break;
					}
				}
				if ( hBarh ) {
					GetWindowRect( hBarh, &rc );
					if ( rc.left < po.x && po.x < rc.right && rc.top-1 < po.y && po.y < rc.bottom+1 ) {
						SetCapture( hWnd );
						lbdy = po.y - rc.top;
						if ( lbdy == 0 ) {
							lbdy = 1;
						}
						SetWindowLongPtr( hBarh, GWL_STYLE, WS_CHILD|WS_VISIBLE|SS_BLACKRECT );
						InvalidateRect( hBarh, NULL, TRUE );
						SetCursor(LoadCursor(NULL, IDC_SIZENS));
						break;
					}
				}
			}
			break;

		case WM_MOUSEMOVE:
			{
				POINT po;
				po.x = LOWORD(lParam);  // horizontal position of cursor 
				po.y = HIWORD(lParam);  // vertical position of cursor 

				ClientToScreen(hWnd, &po);
				if ( !rebarMove( hWnd, (int)wParam, &po ) ) {
					// ナビゲータ上でマウスが動いたとみなす
					MoveMouseOnNavigator( hWnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) );
				}
			}
			break;

		case WM_LBUTTONUP:
			if ( lbdx != 0 || lbdy != 0 ) { // リバードラッグ終了
				ReleaseCapture();
				lbdx = lbdy = 0;
				resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView );
				InvalidateRect( hWnd, NULL, TRUE );
			}
			else { // ナビゲータ上でマウスがクリックされた(放された)
				ClickButtonOnNavigator( hWnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) );
			}
			break;

		case WM_CONTEXTMENU: // 右クリックメニュー
			if ((HWND)wParam == hMainListView) {
				HMENU hMenu;
				POINT pt;
				int n;
				
				GetCursorPos(&pt);
				if (-1 == (n = GetLVCursor( hMainListView )) ) {
					hMenu = GetSubMenu(hContextMenu2, 0);
					if ( hMenu ) { // 表示メニューが開かれたら、選択中の項目をラジオとして表示する
						int m;

						// リストビューの表示スタイル
						switch( wLVStyle ) {
							case 1 : m = ICO_LARGE; break;
							case 2 : m = ICO_SMALL; break;
							case 3 : m = ICO_LIST; break;
							default: m = ICO_REPORT; break;
						}
						CheckMenuRadioItem(hMenu, ICO_LARGE, ICO_REPORT, m, MF_BYCOMMAND);

						// リストビューのソート基準
						switch( rnsf7RegRead("LastSort", 3) ) {
							case -1:
							case 1 : m = IDM_VIEW_ITEM; break;
							case -2:
							case 2 : m = IDM_VIEW_INFORMATION; break;
							case -4:
							case 4 : m = IDM_VIEW_TIME; break;
							case -5:
							case 5 : m = IDM_VIEW_SIZE; break;
							case -6:
							case 6 : m = IDM_VIEW_AUTHOR; break;
							case 99: if (winver >= 501) {m = IDM_VIEW_GROUPVIEW; break;}
							default: m = IDM_VIEW_FILE; break;
						}
						CheckMenuRadioItem(hMenu, IDM_VIEW_ITEM, IDM_VIEW_GROUPVIEW, m, MF_BYCOMMAND);
#if _MSC_VER < 1500
#ifndef _WIN64
						if (winver < 501) {
							// グループ分けして表示できるのはWindows XP以降
							EnableMenuItem(hMenu, IDM_VIEW_GROUPVIEW, MF_BYCOMMAND | MF_GRAYED);
						}
#endif /* _WIN64 */
#endif // _MSC_VER < 1500
						// リストビューの第1項目をファイル名にする
						CheckMenuItem(hMenu, IDM_VIEW_FIRSTITEMFILE, (bLVFirstItemFile?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

						// カテゴリ分類を利用する
						CheckMenuItem(hMenu, IDM_VIEW_LISTBOX, (bCategory?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

						// ナビゲータを利用する
						CheckMenuItem(hMenu, IDM_VIEW_NAVIGATOR, (bNavigator?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

						// 詳細表示であれば、カラム幅を自動調整するメニューを有効にする
						EnableMenuItem(hMenu, IDM_VIEW_AUTOCOLUMN, ((wLVStyle == 0 && ListView_GetItemCount(hMainListView) > 0)?MF_ENABLED:MF_GRAYED) | MF_BYCOMMAND );

						// メニューを表示
						TrackPopupMenuEx(hMenu, 0, pt.x, pt.y, hWnd, NULL);
					}
				}
				else {

					hMenu = GetSubMenu(hContextMenu, 0);
					int ilp = (int)lvGetLParam(hMainListView, n);

					// 「ヘルプ」(help=ファイル名 になっているならば、ヘルプを表示する)
					EnableMenuItem(hMenu, IDM_ITEMHELP, (mlvi[ilp].help[0] == 0 || _stricmp(mlvi[ilp].help, "none") == 0 || _stricmp(mlvi[ilp].help, "dynamic") == 0)?MF_GRAYED:MF_ENABLED | MF_BYCOMMAND );

					// 「URLを開く」(url=があるならば、ヘルプを表示する)
					EnableMenuItem(hMenu, ID_ITEMWEB, (mlvi[ilp].url[0] == 0)?MF_GRAYED:MF_ENABLED | MF_BYCOMMAND );

					// 「編集」メニューの取り扱い
					REG reg;
					if ( reg.OpenKey( HKEY_CLASSES_ROOT, "rscfile\\shell\\edit\\command" ) ) {
						EnableMenuItem(hMenu, ID_ITEMEDIT, MF_ENABLED | MF_BYCOMMAND );
						reg.CloseKey();                            
					}
					else {
						EnableMenuItem(hMenu, ID_ITEMEDIT, MF_GRAYED | MF_BYCOMMAND );
					}							

					TrackPopupMenuEx(hMenu, 0, pt.x, pt.y, hWnd, NULL);
				}
			}
			else if ( (HWND)wParam == hCategoryTreeView ) {
				HMENU hMenu;
				POINT pt;
				
				GetCursorPos(&pt);
				hMenu = GetSubMenu(hContextMenuCategory, 0);
				if ( hMenu ) {
					// カテゴリ分類を利用する
					CheckMenuItem(hMenu, IDM_VIEW_LISTBOX, (bCategory?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

					// ナビゲータを利用する
					CheckMenuItem(hMenu, IDM_VIEW_NAVIGATOR, (bNavigator?MF_CHECKED:MF_UNCHECKED) | MF_BYCOMMAND );

					// メニューを表示
					TrackPopupMenuEx(hMenu, 0, pt.x, pt.y, hWnd, NULL);
				}
			}
			else {
				return DefWindowProc( hWnd, message, wParam, lParam );
			}
			break;

		case WM_SETFOCUS: // ウィンドウにフォーカスが来たら、リストビューに渡す
			SetFocus( hMainListView );
			break;

		case WM_HELP: // ヘルプの呼び出し
			callhelp2(hWnd, "HLP000001.html");
			break;

		case WM_COMMAND:
			switch ( LOWORD(wParam) ) {
				case ID_SETTINGS_OPEN:
					if (0 <= (n = GetLVCursor( hMainListView ))) {
						SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
						OpenSetting( hWnd, &mlvi[(int)lvGetLParam(hMainListView, n)], hStatusBar );
					}
					break;

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

						if ( openDialog(hWnd, SOFTWARENAME"スクリプト/状態定義(*.rsc;*.rnd)\0*.rsc;*.rnd\0"SOFTWARENAME"スクリプト(*.rsc)\0*.rsc\0ダイアログ状態定義(*.rnd)\0*.rnd\0すべてのファイル(*.*)\0*.*\0", fname, _countof(fname), "スクリプト/状態定義ファイルの選択", NULL) ) {
							openrsc( hWnd, fname, NULL );
						}
					}
					break;

				case ID_SETTINGS_SETTING: // オプション（Rnsf7自身の設定）
					SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
					bNotAddRecent = 1; // 「最近使った機能項目」への追加（更新）処理を一時的に抑止する
					openrsc( hWnd, "RNSF7.RSC", NULL );
					bNotAddRecent = 0; // 「最近使った機能項目」への追加（更新）抑止を解除
					break;

				case ID_SETTINGS_HISTORY: // 履歴管理（各種履歴付き編集ボックスの履歴を編集する）
					SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
					bNotAddRecent = 1; // 「最近使った機能項目」への追加（更新）処理を一時的に抑止する
					openrsc( hWnd, "R7HIST.RSC", NULL );
					bNotAddRecent = 0; // 「最近使った機能項目」への追加（更新）抑止を解除
					break;

				case IDSAVE: // ダイアログの状態をまとめて保存
					{ // フォルダの参照
						char chPutFolder[MAX_PATH*2] = "";
						int  len;
						char mode = -1;
						char *msz_rnds = NULL;

						if ( multirnd(hWnd, mlvi, ItemCount, MR_SAVE, &mode, chPutFolder, &msz_rnds) ) {
							len = lstrlen(chPutFolder);
							if ( len ) {
								char rndname[MAX_PATH*2 + MAX_PATH*2 + 2];
								int  i;
								WIN32_FIND_DATA520 wfd;
								HANDLE hff;

								hff = FindFirstFile520( chPutFolder, &wfd );
								if ( hff == INVALID_HANDLE_VALUE ) {
									if ( IDYES == MessageBox( hWnd, "指定されたフォルダは存在していません。作成しますか?", "ダイアログ状態をまとめて保存", MB_YESNO | MB_ICONQUESTION ) ) {
										if ( 0 == CreateDirectory( chPutFolder, NULL ) )  {
											MessageBox( hWnd, "フォルダを作成できませんでした。", "ダイアログ状態をまとめて保存", MB_OK | MB_ICONSTOP );
											break;
										}
									}
									else {
										break;
									}
								}
								else {
									FindClose( hff );

									if ( !(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
										MessageBox( hWnd, "指定された名前はフォルダではありません。", "ダイアログ状態をまとめて保存", MB_OK | MB_ICONSTOP );
										break;
									}
								}

								lstrcpy( rndname, chPutFolder );
								lstrcat( rndname, "フォルダへ、機能項目のダイアログ状態を保存します。\n\nこのフォルダに各機能項目のファイル名.rndというファイルがあると上書きされます。\n\nよろしいですか?" );
								if ( IDYES == MessageBox( hWnd, rndname, "ダイアログ状態をまとめて保存", MB_YESNO | MB_ICONQUESTION ) ) {
									if ( isKanji1(chPutFolder,len-2) || chPutFolder[len-1] != '\\' ) {
										chPutFolder[len] = '\\';
										chPutFolder[len+1] = 0;
									}
									int nCnt = 0;

									if (mode == MR_ALL) {
										// スクリプト一覧基準で保存ファイルを決定
										for(i=-invisible_item_num ; i<ItemCount ; i++) { // -invisible_item_numからスタートしているのは、非表示のrscを最初に実行させるため
											lstrcpy( rndname, "*" ); // 頭に*をつけてopenrscに渡すと、連続保存
											lstrcat( rndname, chPutFolder );
											lstrcat( rndname, i < 0 ? invisible_item_rsc[i+invisible_item_num] : mlvi[i].rsc_fname );
											len = lstrlen(rndname);
											if ( len > 2 ) {
												rndname[len-2] = 'n';
												rndname[len-1] = 'd';

												if (FALSE != openrsc( hWnd, rndname, NULL )) {
													++nCnt;
												}
											}
										}

									}
									else if (mode == MR_SELECT) {
										// 選択ダイアログで選択したモノのみ保存
										for(int i=0 ; !(msz_rnds[i]=='\0' && msz_rnds[i+1]=='\0') ; ++i) {
											lstrcpy( rndname, "*" ); // 頭に*をつけてopenrscに渡すと、連続保存
											lstrcat( rndname, chPutFolder );
											lstrcat( rndname, &msz_rnds[i] );
											len = lstrlen(rndname);
											if ( len > 2 ) {
												rndname[len-2] = 'n';
												rndname[len-1] = 'd';

												if (FALSE != openrsc( hWnd, rndname, NULL )) {
													++nCnt;
												}
											}

											// 次の文字列開始位置までスキップ
											while(msz_rnds[++i] != '\0');

											// スキップした先も\0なら終了
											if (msz_rnds[i+1] == '\0') {
												break;
											}
										}

										safefree(msz_rnds);
									}
									
									wsprintf( rndname, "%d個のファイルを処理しました。", nCnt );
									MessageBox( hWnd, rndname, "ダイアログ状態をまとめて保存", MB_OK | MB_ICONINFORMATION );

								}
							}
						}
					}
					break;

				case IDLOAD: // ダイアログ状態をまとめて読み出す
					{ // フォルダの参照
                        char chPutFolder[MAX_PATH*2] = "";
						int  len;
						char mode = -1;

						if ( multirnd(hWnd, mlvi, ItemCount, MR_LOAD, &mode, chPutFolder, NULL) ) {
							len = lstrlen(chPutFolder);
							if ( len ) {
								char rndname[MAX_PATH*2 + MAX_PATH*2 + 2];
								int  i, n_sumi = 0; // i:カウント用, n_sumi:処理したファイルの数を記録し、0なら、エラーメッセージを出す

								if ( isKanji1(chPutFolder,len-2) || chPutFolder[len-1] != '\\' ) {
									chPutFolder[len] = '\\';
									chPutFolder[len+1] = 0;
								}

								lstrcpy( rndname, chPutFolder );
								lstrcat( rndname, "より状態定義ファイルを読み込んでいきます。\n\n読み込んだ内容で問題なければ、[OK]ボタンを押していって下さい。\n\n複数の状態定義ファイルがある場合は、複数回[OK]を押すことになりますが、レジストリを扱うものですので、必ず全てについてよく確認して下さい。\n\n※複数のファイルを処理する場合、次のファイルの処理へ移るときに[Shift]キーを押しておくと、処理が中止されます。\n\n※異なる環境で作られたrndファイルを読み込ませないでください。特にOSが異なる（Windows XPで作られたrndファイルをVistaに入れたり、x86版で作られたrndファイルをx64版に入れたりする）場合、レジストリの使われ方が異なることがあり、予期せぬ結果を招くことがあります。" );
								MessageBox( hWnd, rndname, "ダイアログ状態の読み込み", MB_OK | MB_ICONINFORMATION );

								tp_nreboot = 1; // 一時的に再起動を禁止する

								if (mode == MR_ALL) {
									// スクリプト一覧基準で探す
									for(i=-invisible_item_num ; i<ItemCount ; i++) { // -invisible_item_numからスタートしているのは、非表示のrscを最初に実行させるため
										lstrcpy( rndname, chPutFolder );
										lstrcat( rndname, i < 0 ? invisible_item_rsc[i+invisible_item_num] : mlvi[i].rsc_fname );

										if ( GetAsyncKeyState(VK_SHIFT)&0x8000 ) {
											break; // Shiftキーが押されていると中断
										}

										len = lstrlen(rndname);
										if ( len > 2 ) {
											rndname[len-2] = 'n';
											rndname[len-1] = 'd';

											if ( tFileExist( rndname ) ) {
												openrsc( hWnd, rndname, NULL );
												n_sumi++;
											}
										}
									}
								}
								else if (mode == MR_SELECT) {
									// フォルダ内のrndファイルで探す
									lstrcpy( rndname, chPutFolder );
									lstrcat( rndname, "*.rnd" );

									WIN32_FIND_DATA520 ffd;
									HANDLE ffh;

									if ( INVALID_HANDLE_VALUE != (ffh = FindFirstFile520(rndname, &ffd)) ) {
										do {
											if ( GetAsyncKeyState(VK_SHIFT)&0x8000 ) {
												break; // Shiftキーが押されていると中断
											}

											if ( !(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ) {
												lstrcpy( rndname, chPutFolder );
												lstrcat( rndname, ffd.cFileName );
												openrsc( hWnd, rndname, NULL );
												n_sumi++;
											}
										} while( FindNextFile520( ffh, &ffd ) );
										FindClose( ffh );
									}
								}

								tp_nreboot = 0; // 一時的な再起動禁止を解除

								if ( n_sumi == 0 ) {
									lstrcpy( rndname, chPutFolder );
									lstrcat( rndname, "には処理できるファイルが見つかりませんでした。" );
									MessageBox( hWnd, rndname, "ダイアログ状態の読み込み", MB_OK | MB_ICONSTOP );
								}
								else {
									wsprintf( rndname, "%d個のファイルを処理しました。\n設定が有効にならない場合は、コンピュータを再起動してください。", n_sumi );
									MessageBox( hWnd, rndname, "ダイアログ状態の読み込み", MB_OK | MB_ICONINFORMATION );
								}
							}
						}
					}
					break;

				case IDM_FIND: // 検索
					{
						static char *findbuf;
						static BOOL hf_inc, hf_ncs;
						const char *p;
						const char *fname = NULL;
						int found = 0;
						UINT iInclude = 0;

						hf_inc = rnsf7RegRead( "hf_incs", 0 );
						hf_ncs = rnsf7RegRead( "hf_ncss", 0 );
						if ( findDialog(hWnd, &findbuf, &hf_inc, &hf_ncs, "Includeで指定されたファイルも検索する(&I)", "スクリプト中からInclude指定で読み出されるrssファイルなども検索の対象にします") && findbuf ) {
							rnsf7RegWrite( "hf_incs", hf_inc );
							rnsf7RegWrite( "hf_ncss", hf_ncs );
							setStatusBarText( "全てのスクリプトファイルから、指定された文字列を検索しています...", 0);
							for( int i=0 ; i<ItemCount ; i++ ) {
								fname = mlvi[i].rsc_fname;
								iInclude = 0;
								LOAD_RSC lr, lrh;
								int ec;
								const char *nsrc0;

								if ( LR_OK != lr.source_load(fname) ) {
									continue;
								}
                                lr.searchItem(LR_SI_LOAD, NULL, 0, ec);
								if ( ec != LR_OK ) {
									continue;
								}
								nsrc0 = &(lr.nsrc[0]);

								while(1) {
									if ( hf_ncs )
										p = sjisstri(nsrc0, findbuf);
									else
										p = sjisstr(nsrc0, findbuf);
									if ( p ) {
										if ( found == 0 ) {
											// このファイルで初めて見つかった場合
											for( int j=0 ; j<ItemCount ; j++ )
												mlvi[j].foundflag = 0;
										}
										mlvi[i].foundflag = 1;
										++found;
										break;
									}

									// includeされるファイルも続けて検索
									if ( hf_inc ) {
										fname = lr.searchItem( LR_SI_INCLUDE, NULL, iInclude++, ec );
										if ( fname ) {
											if ( LR_OK != lrh.source_load(fname) )
												break;
											nsrc0 = &(lrh.nsrc[0]);
										}
										else
											break;
									}
									else {
										fname = NULL;
										break;
									}
								}
							}
							if ( found ) {
								// 見つかったものが1つ以上あったら、カテゴリボックスを表示
								showListView( hMainListView, -2 );
								if ( bCategory == 0 ) {
									bCategory = 1;
									// カテゴリボックスの生成または削除
									hCategoryTreeView = createCategoryTreeView( hWnd );

									// 全体のリサイズ
									resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView );
								}
								// リストビューのソート
								startListviewSort( hMainListView, LVORDER_LAST );
								// フォーカスとカーソルを与える
								ListView_SetItemState(hMainListView, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);

								// iImage==2を番号を持つカテゴリ項目名を「検索結果:'〜'」に変える
								char *strbuf = zalloc(10 + lstrlen(findbuf) + 2 + 10 + 4);
								if (strbuf) {
									wsprintf(strbuf, "検索結果:'%s'(%d件)", findbuf, found);
								}

								TVITEM tvi;

								ZeroMemory(&tvi, sizeof(tvi));
								tvi.mask = TVIF_TEXT;
								tvi.hItem = htSearch;
								// テキストを設定
								tvi.pszText = strbuf ? strbuf : "検索結果";
								TreeView_SetItem( hCategoryTreeView, &tvi );

								// 選択
								TreeView_SelectItem( hCategoryTreeView, htSearch );

								safefree(strbuf);

								resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView );
								setStatusBarText( "検索結果は、カテゴリ「検索結果:〜」で表示されます。", 0 );
							}
							else {
								setStatusBarText( "検索結果:見つかりませんでした。", 0 );
								MessageBox( hWnd, "見つかりませんでした。", "検索", MB_OK | MB_ICONINFORMATION );
								setStatusBarText( NULL, 0 );
							}
						}
					}
					break;

				case IDM_SEARCH:	// キーワード検索
					kwdDialog(hWnd);
					break;

				case ID_SETTINGS_OPENDIR: // カレントフォルダを開く
					if ( (HINSTANCE)32 >= ShellExecute(hWnd, "open", ".", NULL, NULL, SW_SHOWNORMAL) ) {
						MessageBox(hWnd, "カレントフォルダを開けません。\nフォルダに関連づけられたアプリケーション(通常はエクスプローラ)が正しく動作することを確認して下さい。", "カレントフォルダを開く", MB_OK | MB_ICONSTOP);
						return false;
					}
					break;

				case ID_SETTINGS_REBOOTWINDOWS: // Windowsの再起動
					WinReboot( hWnd, hWnd );
					break;

				case ID_SETTINGS_REFRESH: // シェルに刺激を与える
					notify_otherapp( hWnd, hWnd, 2 );
					break;

				case ID_SETTINGS_NOTIFY: // 通知メッセージのブロードキャスト
					notify_otherapp( hWnd, hWnd, 1 );
					break;

				case ID_TOOLS_BACKUPREGISTRY:
					backupRegistry( hWnd );
					break;

				case ID_TOOLS_RESTOREREGISTRY:
					restoreRegistry( hWnd );
					break;

				case ID_TOOLS_SYSTEMRESTORE:
					systemRestore( hWnd );
					break;

				case ID_TOOLS_MAKERPXP:
					createRestorePointManual( hWnd );
					break;

#if _MSC_VER < 1500
#ifndef _WIN64
				case ID_TOOLS_OPTIMIZEREGISTRY:
					optimizeRegistry( hWnd );
					break;
#endif // _WIN64
#endif // _MSC_VER < 1500

				case ID_TOOLS_LOGOFF:
					QuitWindows(hWnd, QW_LOGOFF);
					break;

				case ID_TOOLS_REBOOT:
					QuitWindows(hWnd, QW_REBOOT);
					break;

				case ID_TOOLS_FORCEREBOOT:
					QuitWindows(hWnd, QW_REBOOT | QW_FORCE);
					break;

				case ID_TOOLS_SHUTDOWN:
					QuitWindows(hWnd, QW_SHUTDOWN);
					break;

				case IDM_HELP_KIFU:
					callhelp2(hWnd, "kifu.html");
					break;

				case IDM_HELP_HELP:
					callhelp2(hWnd, "HLP000001.html");
					break;

				case IDHELP_RSCRIPT:
					callhelp2(hWnd, "HLP000010.html");
					break;

				case IDHELP_DOCLIB:
					callhelp2(hWnd, "HLP000089.html");
					break;

				case IDM_FEEDBACK:
					{
						TCHAR sysdir[MAX_PATH*2] = "\\";
						GetSystemDirectory(sysdir, _countof(sysdir));
						SetCurrentDirectory(sysdir); // カレントディレクトリのDLLが悪さをするといけないので、一時的にCD
						if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "http://www.inasoft.org/ifa.php?RNSF7", NULL, sysdir, SW_SHOWNORMAL)) {
							// Firefox 4.0の偽エラー問題もあるし、エラーダイアログはとりあえず無しで
							// MessageBox(hWnd, "ブラウザを開けません。\nブラウザが正しくインストールされているかを確認して下さい。\nまたはhttp://www.inasoft.org/ifa.php?RNSF7を直接開いて下さい。", "フィードバックページを表示", MB_OK | MB_ICONSTOP);
						}
						SetCurrentDirectoryOwnDir();
					}
					break;

				case ID_HELP_CCPU:
					CallCcpuWindow( hWnd );
					break;

				case IDM_HELP_ABOUT:
					CallAboutWindow( hWnd );
					break;

				case ID_HELP_GOWEBSITE:
					{
						TCHAR sysdir[MAX_PATH*2] = "\\";
						GetSystemDirectory(sysdir, _countof(sysdir));
						SetCurrentDirectory(sysdir); // カレントディレクトリのDLLが悪さをするといけないので、一時的にCD
						if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "http://www.inasoft.org/", NULL, sysdir, SW_SHOWNORMAL)) {
							// Firefox 4.0の偽エラー問題もあるし、エラーダイアログはとりあえず無しで
							// MessageBox(hWnd, "ブラウザを開けません。\nブラウザが正しくインストールされているかを確認して下さい。\nまたはhttp://www.inasoft.org/を直接開いて下さい。", "INASOFTのWebサイトを表示", MB_OK | MB_ICONSTOP);
						}
						SetCurrentDirectoryOwnDir();
					}
					break;

				case ID_HELP_UPDATECHECK:
					UpdateCheck( hWnd, 0 );
					break;

				case ID_HELP_UPDATECHECKSET:
					SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
					bNotAddRecent = 1; // 「最近使った機能項目」への追加（更新）処理を一時的に抑止する
                    openrsc( hWnd, "R7UPDATE.RSC", NULL );
					bNotAddRecent = 0; // 「最近使った機能項目」への追加（更新）抑止を解除
					break;

				case IDM_SETTINGS_EXIT:
					DestroyWindow( hWnd );
					break;

				case ICO_LARGE:
					ChangeLVStyle(hWnd, hMainListView, wLVStyle = 1, true);
					break;
				case ICO_SMALL:
					ChangeLVStyle(hWnd, hMainListView, wLVStyle = 2, true);
					break;
				case ICO_LIST:
					ChangeLVStyle(hWnd, hMainListView, wLVStyle = 3, true);
					break;
				case ICO_REPORT:
					ChangeLVStyle(hWnd, hMainListView, wLVStyle = 0, true);
					break;

				case IDM_VIEW_LISTBOX: // カテゴリ分類を利用する
	                bCategory = !bCategory;
					showListView( hMainListView, -1 );
					// リストビューのソート
					startListviewSort( hMainListView, LVORDER_LAST );

					// カテゴリボックスの生成または削除
					if ( bCategory ) {
                        hCategoryTreeView = createCategoryTreeView( hWnd );
					}
					else {
						if ( hCategoryTreeView ) {
							DestroyWindow( hCategoryTreeView );
							hCategoryTreeView = NULL;
						}
					}

					// 各ペインのリサイズ
					resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView );

					// ナビゲータの表示
					OpenNavigator(hWnd, hCategoryTreeView, hMainListView, hStatusBar);

					// フォーカスとカーソルを与える
					ListView_SetItemState(hMainListView,0,LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);

					// ステータスバーの描画
					setStatusBarText( NULL, 0 );
					break;

				case IDM_VIEW_NAVIGATOR: // ナビゲータを利用する
	                bNavigator = !bNavigator;

					// 各ペインのリサイズ
					resizeListView(hWnd, hCategoryTreeView, hStatusBar, hMainListView );

					// ナビゲータの表示
					OpenNavigator(hWnd, hCategoryTreeView, hMainListView, hStatusBar);
					break;

				case IDM_VIEW_FIRSTITEMFILE: // 第1項目をファイル名する
					if ( LOWORD(wParam) == IDM_VIEW_FIRSTITEMFILE ) {
	                    bLVFirstItemFile = !bLVFirstItemFile;
					}
					// そのまま下へ
				case IDM_VIEW_RELOAD:
					{
						int n;
						REG reg;

						if ( wLVStyle == 0 ) { // 詳細モードだったら、各カラムのサイズを保存する
							if ( reg.OpenKey(HKEY_CURRENT_USER, RNSF7REGKEY, TREG_OPEN_CREATE) ) {
								char lvColumnWidthValue[20];

								// リストビューの各カラムのサイズ
								for(n=0 ; n<NUMCOLUMN ; n++) {
									wsprintf( lvColumnWidthValue, "lvColumnWidth%d", n );
									reg.WriteInteger(lvColumnWidthValue, ListView_GetColumnWidth(hMainListView, n));
								}

								reg.CloseKey();
							}
						}

						// リロード前に、現状のリストビュー／カテゴリボックスを削除する
						// （でないと、これらのコントロールが２重に表示されてしまうので）

						// リストビューの削除
						if ( hMainListView ) {
							// アイテムの削除
							ListView_DeleteAllItems(hMainListView);
							// グループの削除（可能な場合）
							if (winver >= 501) ListView_RemoveAllGroups(hMainListView);
							// イメージリストの削除
							ImageList_Destroy(ListView_GetImageList(hMainListView, LVSIL_NORMAL));
							ImageList_Destroy(ListView_GetImageList(hMainListView, LVSIL_SMALL));
							// リストビューの破棄
							DestroyWindow( hMainListView );
							hMainListView = NULL;
						}

						// (あれば)カテゴリボックスの削除
						if ( hCategoryTreeView ) {
							DestroyWindow( hCategoryTreeView );
							hCategoryTreeView = NULL;
						}

						// リロード
						SendMessage( hWnd, R7MW_READY, 0, NULL );
					}
					if ( LOWORD(wParam) != IDM_VIEW_FIRSTITEMFILE ) {
						break;
					}
					// そのまま下へ : IDM_VIEW_FIRSTITEMFILEが原因でリロードになった場合は、カラム幅の自動調整を行う
				case IDM_VIEW_AUTOCOLUMN:
					if ( wLVStyle == 0 && ListView_GetItemCount(hMainListView) > 0 ) { // 詳細モードで、アイテムの数が1以上ある場合のみ機能する
						for(int n=0 ; n<NUMCOLUMN ; n++) {
							ListView_SetColumnWidth(hMainListView, n, LVSCW_AUTOSIZE);
						}
					}
					break;

				case IDM_VIEW_ITEM: // 項目名でソート（昇／降 切替）
					startListviewSort( hMainListView, LVORDER_NAME_ASC );
					break;

				case IDM_VIEW_INFORMATION: // 情報でソート（昇／降 切替）
					startListviewSort( hMainListView, LVORDER_INFO_ASC );
					break;

				case IDM_VIEW_FILE: // ファイル名でソート（昇／降 切替）
					startListviewSort( hMainListView, LVORDER_FILE_ASC );
					break;

				case IDM_VIEW_TIME: // 最終更新日時でソート（昇／降 切替）
					startListviewSort( hMainListView, LVORDER_DATE_ASC );
					break;

				case IDM_VIEW_SIZE: // サイズでソート（昇／降 切替）
					startListviewSort( hMainListView, LVORDER_SIZE_ASC );
					break;

				case IDM_VIEW_AUTHOR: // 作者名でソート（昇／降 切替）
					startListviewSort( hMainListView, LVORDER_AUTH_ASC );
					break;

				case IDM_VIEW_GROUPVIEW: // グループ分けして表示
					startListviewSort( hMainListView, LVORDER_GROUPVIEW );
					break;

				case IDM_ITEMHELP: // 各アイテムのヘルプを呼び出す
					{
						int n;

						if (-1 != (n = GetLVCursor( hMainListView )) ) {
							int ilp = (int)lvGetLParam(hMainListView, n);
							callhelp(hWnd, mlvi[ilp].help, mlvi[ilp].contextid );
						}
					}
					break;

				case ID_ITEMWEB: // 各アイテムのWebサイトを開く
					{
						int n;

						if ( -1 != (n = GetLVCursor( hMainListView )) ) {
							int ilp = (int)lvGetLParam(hMainListView, n);
							if ( mlvi[ilp].url && mlvi[ilp].url[0] ) {
								if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", mlvi[ilp].url, NULL, NULL, SW_SHOWNORMAL)) {
									MessageBox(hWnd, "ブラウザを開けません。\nブラウザが正しくインストールされているかを確認して下さい。", "URLを開く", MB_OK | MB_ICONSTOP);
								}
							}
						}
					}
					break;

				case ID_ITEMEDIT: // スクリプトファイルを「編集」
					{
						int n;

						if ( -1 != (n = GetLVCursor( hMainListView )) ) {
							if ((HINSTANCE)32 >= ShellExecute(hWnd, "edit", mlvi[(int)lvGetLParam(hMainListView, n)].rsc_fname, NULL, NULL, SW_SHOWNORMAL)) {
								MessageBox(hWnd, "編集プログラムを開けません。\n「オプション」で、スクリプトを編集するプログラムが正しく設定されているかどうか、確認してみて下さい。", "スクリプトファイルを編集", MB_OK | MB_ICONSTOP);
							}
						}
					}
					break;

				case IDM_VIEWSOURCE: // スクリプトファイルを閲覧
					{
						int n = 0;
						const char *rscbuf = NULL;
						const char *fname = NULL;
						UINT iInclude = 0;
						bool viewed = 0;

						if ( -1 != (n = GetLVCursor( hMainListView )) ) {
							fname = mlvi[(int)lvGetLParam(hMainListView, n)].rsc_fname;
							helpdoc_start( fname, 1 );

							LOAD_RSC lr, lri;
							int      ec;

							// ソースをロード・解析する
							if ( LR_OK != lr.source_load(fname) ) {
								lr.errmes(hWnd);
								break;
							}

							lr.searchItem( LR_SI_LOAD, NULL, 0, ec );
							if ( ec != LR_OK ) {
								lr.errmes(hWnd);
								break;
							}
							rscbuf = &(lr.nsrc[0]);

							iInclude = 0;
							while( 1 ) {
								helpdoc_section( fname, 1 );
								helpdoc_text( rscbuf, 1 );

								// includeされるファイルも続けて表示
								fname = lr.searchItem( LR_SI_INCLUDE, NULL, iInclude++, ec );
								if ( ec != LR_OK ) {
									lr.errmes(hWnd);
									break;
								}

								// 本来ならば fname は _strdup して渡すんだけど、ここでは他に使うこともないのでそのまま
								if ( !fname ) {
									helpdoc_open( hWnd, 1 );
									viewed = 1;
									break;
								}

								if ( LR_OK != lri.source_load(fname) ) {
									lri.errmes(hWnd);
									break;
								}
								else {
									rscbuf = &(lri.nsrc[0]);
								}
							}

							if ( !viewed ) {
								MessageBox( hWnd, "ソースファイルを開けませんでした。", fname, MB_OK | MB_ICONSTOP );
							}
						}
					}
					break;

				case IDM_ITEMPROP:	// 機能項目のプロパティ
					if (0 <= (n = GetLVCursor( hMainListView ))) {
						openItemProp( hWnd, &mlvi[(int)lvGetLParam(hMainListView, n)] );
					}
					break;

				case IDC_CONTROLPANEL: // コントロール パネルを開く
					if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "control.exe", NULL, NULL, SW_SHOWNORMAL)) {
						MessageBox(hWnd, "「コントロール パネル」の起動に失敗しました。", "コントロール パネルの起動", MB_OK | MB_ICONSTOP);
					}
					break;

				case ID_TOOLS_REGEDIT: // レジストリ エディタ
					if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "regedit.exe", NULL, NULL, SW_SHOWNORMAL)) {
						MessageBox(hWnd, "「レジストリ エディタ」の起動に失敗しました。", "レジストリ エディタの起動", MB_OK | MB_ICONSTOP);
					}
					break;

				case ID_TOOLS_KEYREGEDIT: // キーを指定してレジストリ エディタを開く
					if (winver >= 490) {
						regOpenKeyDlg(hWnd, NULL);
					}
					break;

				case ID_TOOLS_SYSEDIT: // システム エディタ
					if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "sysedit.exe", NULL, NULL, SW_SHOWNORMAL)) {
						MessageBox(hWnd, "「システム エディタ」の起動に失敗しました。", "システム エディタの起動", MB_OK | MB_ICONSTOP);
					}
					break;

				case ID_TOOLS_MSCONFIG: // システム構成ユーティリティ
					if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "msconfig.exe", NULL, NULL, SW_SHOWNORMAL)) {
						MessageBox(hWnd, "「システム構成ユーティリティ」の起動に失敗しました。", "システム構成ユーティリティの起動", MB_OK | MB_ICONSTOP);
					}
					break;

				case ID_TOOLS_WIN7GM: // GodModeの呼び出し … Windowsの管理機能を集約した「GodMode」を呼び出します。
					{
						char tmppath[MAX_PATH*2] = ".";

						GetTempPath(_countof(tmppath), tmppath);
						if ((HINSTANCE)32 >= ShellExecute(hWnd, "open", "cmd.exe", "/c (mkdir GodMode.{ED7BA470-8E54-465E-825C-99712043E01C})&(explorer GodMode.{ED7BA470-8E54-465E-825C-99712043E01C})", tmppath, SW_SHOWNORMAL)) {
							MessageBox(hWnd, "「GodMode」の呼出しに失敗しました。", "GodModeの呼び出し", MB_OK | MB_ICONSTOP);
						}
					}
					break;

				case ID_RECENT_1: // 最近使った機能項目
				case ID_RECENT_2:
				case ID_RECENT_3:
				case ID_RECENT_4:
				case ID_RECENT_5:
				case ID_RECENT_6:
				case ID_RECENT_7:
				case ID_RECENT_8:
				case ID_RECENT_9:
				case ID_RECENT_10:
					{
						REG reg;
						char s[50], *rscname;

						if ( reg.OpenSubKey(HKEY_CURRENT_USER, RNSF7REGKEY, "R7RECENT", TREG_OPEN_READONLY) ) {
							wsprintf(s, "r7r_rsc%d", LOWORD(wParam)-ID_RECENT_1+1);
							rscname = reg.new_ReadString(s);
							reg.CloseKey();

							if ( rscname ) {
								openrsc(hWnd, rscname, NULL);
								safedelete(rscname);
							}
						}
					}
					break;

				case IDM_FAVORITE_ADD: // お気に入りメニューへ追加
					if ( 0 <= (n = GetLVCursor( hMainListView )) ) {
						REG    reg;
						char   *mes;
						int    ilp = (int)lvGetLParam(hMainListView, n);

						SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
						mes = zalloc(lstrlen(mlvi[ilp].item)+80);
						if ( mes ) {
							wsprintf(mes, "お気に入りメニューへ「%s」を追加します。\r\nよろしいですか?", mlvi[ilp].item);
							if ( IDYES == MessageBox(hWnd, mes, "お気に入りへの追加", MB_YESNO | MB_ICONQUESTION) ) {
								if ( reg.OpenSubKey(HKEY_CURRENT_USER, RNSF7REGKEY, "R7FAV", TREG_OPEN_CREATE) ) {
									reg.WriteString(mlvi[ilp].item, mlvi[ilp].rsc_fname, TREG_SZ);
									reg.CloseKey();
								}
							}
						}
					}
					break;

				case IDM_FAVORITE_EDIT: // お気に入りメニューの整理
					SendMessage( hWnd, R7MW_SAVESETTINGS, 0, NULL );
					bNotAddRecent = 1; // 「最近使った機能項目」への追加（更新）処理を一時的に抑止する
                    openrsc( hWnd, "R7FAV.RSC", NULL );
					bNotAddRecent = 0; // 「最近使った機能項目」への追加（更新）抑止を解除
					break;

				case IDM_HELP_RNSF7T: // チュートリアル
					{
						int i;
						for(i=0 ; rnsf7tfiles[i] ; ++i) {
							if ( tFileExist(rnsf7tfiles[i]) ) {
								if ( i == 0 ) { // iが0のときはrscファイルと決め撃ち
                                    openrsc(hWnd, rnsf7tfiles[i], NULL);
									break;
								}
								else {
									if ( runProgram(hWnd, rnsf7tfiles[i]) )
										break;
								}
							}
						}

						if ( rnsf7tfiles[i] == NULL ) {
                            MessageBox(hWnd, "実行できませんでした。", "チュートリアル", MB_OK | MB_ICONSTOP);
						}
					}
					break;

				case IDM_CREATESHORTCUT: // デスクトップにこの編集項目を直接開くためのショートカットを作成
					if (IDOK == MessageBox(hWnd, "この編集項目を直接開くためのショートカットを、デスクトップに作成します。", "ショートカットの作成", MB_OKCANCEL | MB_ICONQUESTION)) {
						if ( 0 <= (n = GetLVCursor( hMainListView )) ) {
							char exename[MAX_PATH*2+2];
							char desktopfile[MAX_PATH*2+2];
							int i = (int)lvGetLParam(hMainListView, n);

							GetModuleFileName(NULL, exename, _countof(exename));
							_makepath_s(desktopfile, _countof(desktopfile), NULL, GetDesktopFolder(), mlvi[i].item, ".lnk");

							if (MakeLinkIcon(exename, mlvi[i].rsc_fname, desktopfile, exename, -232)) {
								MessageBox(hWnd, "デスクトップにアイコンを作成しました。", "ショートカットの作成", MB_OK | MB_ICONINFORMATION);
							}
							else {
								MessageBox(hWnd, "デスクトップにアイコンを作成できませんでした。", "ショートカットの作成", MB_OK | MB_ICONSTOP);
							}
						}
					}
					break;

				default: // お気に入り機能項目
					// IDM_FAVORITE_001 から 100個まで
					{
						int i;

						// お気に入りの選択
						for(i=IDM_FAVORITE_001 ; i<=IDM_FAVORITE_100 ; ++i) {
							if ( LOWORD(wParam) == i ) {
								char *name = NULL, *rsc = NULL;
								int m = GetMenuString(hMainMenu, i, NULL, 0, MF_BYCOMMAND);

								++m;
								name = zalloc(m);
								if ( name ) {
									if ( GetMenuString(hMainMenu, i, name, m, MF_BYCOMMAND) ) {
                                        REG reg;

										if( reg.OpenSubKey(HKEY_CURRENT_USER, RNSF7REGKEY, "R7FAV", TREG_OPEN_READONLY) ) {
											rsc = reg.new_ReadString(name);                                            
											reg.CloseKey();
										}

										if ( rsc ) {
											openrsc(hWnd, rsc, NULL);
											safedelete(rsc);
										}
									}
									safefree(name);
								}
								break;
							}
						}
					}
					break;
			}
			break;

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	return 0;
}
