///////////////////////////////////////
// ResReader.cs - Resource File Reader
// Copyright (c) 2022 by Ysama
///////////////////////////////////////

using System;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.Reflection;		//Assemblyを使う為
using System.Resources;			//リソース関係クラス等の使用の為
using System.IO;				//Stream関係クラス等の使用の為

//エントリーポイントクラス
class WinMain
{
	[STAThread]
	public static void Main()
	{
		MainForm mf = new MainForm();
		Application.Run(mf);
	}
}

///////////////////////
//メインフォームクラス
///////////////////////
public partial class MainForm : Form
{
	//クラスメンバー変数
	ToolStrip toolStrip;						//ツールバー
	ToolStripButton[] toolStripButton;			//ツールバーボタン
	StatusStrip statusStrip;					//ステータスバー
	ToolStripStatusLabel[] tssl;				//ステータスバーラベル
	ListView listView;							//リストビュー
	bool FileType = true;						//ファイル種類（*.resources−true、*.resx−false）
	string ResFileName = "";					//読み込むリソースファイル名

	//コンストラクター
	public MainForm()
	{
		Assembly myOwn = Assembly.GetEntryAssembly();
		this.Icon = Icon.ExtractAssociatedIcon(myOwn.Location);	//プログラムアイコンをフォームにつける
		this.Load += new EventHandler(MainForm_Load);
		this.Text = "ResReader";
		this.ClientSize = new Size(724, 262);
		this.MinimumSize = new Size(372, 258);
		this.BackColor = SystemColors.Window;
	}

	//WM_CREATE時処理
	private void MainForm_Load(object sender, EventArgs e)
	{
		//メニュー作成
		SetMenu();
		//ツールバーとステータスバー作成
		SetBars();
		//リストビュー作成
		SetListView();
	}

	//メニューの設定
	protected void SetMenu()
	{
		//メニュー作成
		MainMenu menu = new MainMenu();
		Menu = menu;
		//メニューアイテム付加
		MenuItem miFile = new MenuItem();		//「ファイル」メニュー
		miFile.Text = "ファイル(&F)";
		miFile.Index = 0;
		menu.MenuItems.Add(miFile);
		MenuItem miHelp = new MenuItem();		//「ヘルプ」メニュー
		miHelp.Text = "ヘルプ(&H)";
		miHelp.Index = 1;
		menu.MenuItems.Add(miHelp);
		MenuItem miOpen = new MenuItem();		//「開く」メニューアイテム
		miOpen.Text = "開く(&O)";
		miOpen.Index = 0;
		miOpen.Click += OnOpen_Click;
		miOpen.Shortcut = Shortcut.CtrlO;
		miFile.MenuItems.Add(miOpen);
		MenuItem miSave = new MenuItem();		//「保存」メニューアイテム
		miSave.Text = "保存(&S)";
		miSave.Index = 1;
		miSave.Click += OnSave_Click;
		miSave.Shortcut = Shortcut.CtrlS;
		miFile.MenuItems.Add(miSave);
		miFile.MenuItems.Add("-");				//セパレーター
		MenuItem miExit = new MenuItem();		//「終了」メニューアイテム
		miExit.Text = "終了(&X)";
		miExit.Index = 2;
		miExit.Click += OnExit_Click;
		miExit.Shortcut = Shortcut.CtrlX;
		miFile.MenuItems.Add(miExit);
		MenuItem miHowtoUse = new MenuItem();	//「使い方」メニューアイテム
		miHowtoUse.Text = "使い方(&U)";
		miHowtoUse.Index = 0;
		miHowtoUse.Click += OnHowtoUse_Click;
		miHelp.MenuItems.Add(miHowtoUse);
		MenuItem miVer = new MenuItem();		//「バージョン」メニューアイテム
		miVer.Text = "バージョン(&V)";
		miVer.Index = 1;
		miVer.Click += OnVersion_Click;
		miVer.Shortcut = Shortcut.CtrlV;
		miHelp.MenuItems.Add(miVer);
	}

	//ツールバーとステータスバーの設定
	protected void SetBars()
	{
		//フォームのレイアウトを一時停止
		this.SuspendLayout();
		//ToolStripクラスインスタンスの生成
		this.toolStrip = new ToolStrip();
		//ツールバーのレイアウトを一時停止
		this.toolStrip.SuspendLayout();
		//ToolStripButton配列を作成
		this.toolStripButton = new ToolStripButton[5];
		//本プログラムの埋め込みリソース（ResReader）のリソースマネージャーを作成
		Assembly asm = Assembly.GetExecutingAssembly();
		ResourceManager rm = new ResourceManager("ResReader", asm);
		//ToolStripButton[0]を作成
		this.toolStripButton[0] = new ToolStripButton();
		this.toolStripButton[0].Text = "開く(&O)";								//テキスト設定
		this.toolStripButton[0].Image = (Bitmap)rm.GetObject("bmpOpen");		//画像設定
		this.toolStripButton[0].DisplayStyle = ToolStripItemDisplayStyle.Image;	//画像表示のみ
		this.toolStripButton[0].Click += OnOpen_Click;							//Clickイベントハンドラ追加
		this.toolStrip.Items.Add(this.toolStripButton[0]);						//ボタンを追加
		//ToolStripButton[1]を作成
		this.toolStripButton[1] = new ToolStripButton();
		this.toolStripButton[1].Text = "保存(&S)";								//テキスト設定
		this.toolStripButton[1].Image = (Bitmap)rm.GetObject("bmpSave");		//画像設定
		this.toolStripButton[1].DisplayStyle = ToolStripItemDisplayStyle.Image;	//画像表示のみ
		this.toolStripButton[1].Click += OnSave_Click;							//Clickイベントハンドラ追加
		this.toolStrip.Items.Add(this.toolStripButton[1]);						//ボタンを追加
		//セパレーターを挿入
		this.toolStrip.Items.Add(new ToolStripSeparator());
		//ToolStripButton[2]を作成
		this.toolStripButton[2] = new ToolStripButton();
		this.toolStripButton[2].Text = "終了(&X)";								//テキスト設定
		this.toolStripButton[2].Image = (Bitmap)rm.GetObject("bmpExit");		//画像設定
		this.toolStripButton[2].DisplayStyle = ToolStripItemDisplayStyle.Image;	//画像表示のみ
		this.toolStripButton[2].Click += OnExit_Click;							//Clickイベントハンドラ追加
		this.toolStrip.Items.Add(this.toolStripButton[2]);						//ボタンを追加
		//セパレーターを挿入
		this.toolStrip.Items.Add(new ToolStripSeparator());
		//ToolStripButton[3]を作成
		this.toolStripButton[3] = new ToolStripButton();
		this.toolStripButton[3].Text = "使い方(&U)";							//テキスト設定
		this.toolStripButton[3].Image = (Bitmap)rm.GetObject("bmpHelp");		//画像設定
		this.toolStripButton[3].DisplayStyle = ToolStripItemDisplayStyle.Image;	//画像表示のみ
		this.toolStripButton[3].Click += OnHowtoUse_Click;						//Clickイベントハンドラ追加
		this.toolStrip.Items.Add(this.toolStripButton[3]);						//ボタンを追加
		//ToolStripButton[4]を作成
		this.toolStripButton[4] = new ToolStripButton();
		this.toolStripButton[4].Text = "バージョン情報(&V)";					//テキスト設定
		this.toolStripButton[4].Image = (Bitmap)rm.GetObject("bmpVersion");		//画像設定
		this.toolStripButton[4].DisplayStyle = ToolStripItemDisplayStyle.Image;	//画像表示のみ
		this.toolStripButton[4].Click += OnVersion_Click;						//Clickイベントハンドラ追加
		this.toolStrip.Items.Add(this.toolStripButton[4]);						//ボタンを追加
		//ツールバーの設定
		this.Controls.Add(this.toolStrip);
		//ツールバーのレイアウトを再開
		this.toolStrip.ResumeLayout(false);
		this.toolStrip.PerformLayout();

		//StatusStripクラスインスタンスの生成
		this.statusStrip = new StatusStrip();
		//ステータスバーにパネルとテキストを追加
		tssl = new ToolStripStatusLabel[3];
		tssl[0] = new ToolStripStatusLabel();
		tssl[0].BorderSides = ToolStripStatusLabelBorderSides.All;
		tssl[0].BorderStyle = Border3DStyle.SunkenInner;
		tssl[0].BackColor = SystemColors.Control;
		tssl[0].Text = "ResReader Version 1.0";
		tssl[0].AutoSize = true;
		tssl[0].TextAlign = ContentAlignment.MiddleLeft;
		tssl[1] = new ToolStripStatusLabel();
		tssl[1].BorderSides = ToolStripStatusLabelBorderSides.All;
		tssl[1].BorderStyle = Border3DStyle.SunkenInner;
		tssl[1].BackColor = SystemColors.Control;
		tssl[1].Text = "（選択リソースファイル）";
		tssl[1].AutoSize = true;
		tssl[1].TextAlign = ContentAlignment.MiddleLeft;
		tssl[2] = new ToolStripStatusLabel();
		tssl[2].BorderSides = ToolStripStatusLabelBorderSides.All;
		tssl[2].BorderStyle = Border3DStyle.SunkenInner;
		tssl[2].BackColor = SystemColors.Control;
		tssl[2].Text = "（リソースファイル名）";
		tssl[2].ToolTipText = "（リソースファイル名）";	//ToolTip設定
		tssl[2].Spring = true;
		tssl[2].TextAlign = ContentAlignment.MiddleLeft;
		statusStrip.Items.AddRange(tssl);
		statusStrip.ShowItemToolTips = true;			//ToolTip表示
		this.Controls.Add(this.statusStrip);	//StatusStrip(ステータスバー)を追加

		//メインフォームのレイアウトを再開
		this.ResumeLayout(false);
		this.PerformLayout();
	}

	protected void SetListView()
	{
		//リストビュー
		listView = new ListView();
		//境界
		listView.BorderStyle = BorderStyle.Fixed3D;
		//位置
		listView.Location = new Point(0, toolStrip.Height);
		//サイズ
		listView.Width = ClientSize.Width;
		listView.Height = ClientSize.Height - toolStrip.Height - statusStrip.Height;
		//アンカー固定
		listView.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
		//一行選択
		listView.FullRowSelect = true;
		//グリッドラインの表示
		listView.GridLines = true;
		//並び替え表示
		listView.Sorting = SortOrder.Ascending;
		//ポイントで選択できるようにする
		listView.HoverSelection = false;
		//シングルクリック選択
		listView.Activation = ItemActivation.OneClick;
		//チェックボックス有効化
		listView.CheckBoxes = false;
		//リストビューの表示方法
		listView.View = View.Details;
		//イベントハンドラの追加
		listView.ItemActivate += new EventHandler(ListView_ItemActivate);
		listView.ColumnClick += new ColumnClickEventHandler(ListView_ColumnClick);
		listView.ItemSelectionChanged += new ListViewItemSelectionChangedEventHandler(ListView_ItemChanged);
		//ヘッダー定義
		ColumnHeader columnNo = new ColumnHeader{Text = "名前", Width = 100};
		ColumnHeader columnType = new ColumnHeader{Text = "種類", Width = 60};
		ColumnHeader columnData = new ColumnHeader{Text = "データ", Width = 558};
		ColumnHeader[] colHeaderRegValue = {columnNo, columnType, columnData};	//ヘッダー設定
		listView.Columns.AddRange(colHeaderRegValue);	//ヘッダー追加
		//FormにListViewを追加
		this.Controls.Add(listView);
	}

	private void ListView_ItemActivate(object sender, EventArgs e)
	{
		//アイテムがアクティブになった時
		ListView lv = (ListView)sender;
		//フォーカスのあるアイテムのTextを表示する
		tssl[1].Text = lv.FocusedItem.Text;
	}

	private void ListView_ColumnClick(object sender, ColumnClickEventArgs e)
	{
		//ListViewItemSorterを指定する
		listView.ListViewItemSorter = new ListViewItemComparer(e.Column);
		//並び替える（ListViewItemSorterを設定するとSortが自動的に呼び出される）
	}

	private void ListView_ItemChanged(object sender, ListViewItemSelectionChangedEventArgs e)
	{
		//フォーカスのあるアイテムのTextを表示する
		ListView lv = (ListView)sender;
		tssl[1].Text = lv.FocusedItem.Text;
	}

	//終了時処理
	protected override void OnFormClosing(FormClosingEventArgs e)
	{
		base.OnFormClosing(e);
		DialogResult dr = MessageBox.Show("終了しますか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
		if(dr == DialogResult.No)
		{
			e.Cancel = true;
		}
	}

	//「ファイルを開く」処理
	private void OnOpen_Click(object sender, EventArgs e)
	{
		DialogResult dr = MessageBox.Show(".resourcesファイルを開きますか？（「はい」）\r\nそれとも.resxファイルですか？（「いいえ」）\r\n中止しますか？（「キャンセル」）", "ファイル種類確認", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
		switch(dr)
		{
		case DialogResult.Yes:
			MessageBox.Show(".resourcesファイルを開きます。", "ファイルを開く", MessageBoxButtons.OK, MessageBoxIcon.Information);
			FileType = true;
			break;
		case DialogResult.No:
			MessageBox.Show(".resxファイルを開きます。", "ファイルを開く", MessageBoxButtons.OK, MessageBoxIcon.Information);
			FileType = false;
			break;
		default:
			return;
		}
		OpenFileDialog ofDlg = new OpenFileDialog();
		ofDlg.AddExtension = true;	//拡張子自動付加
		if(FileType)				//拡張子指定
			ofDlg.FileName = "*.resources";
		else
			ofDlg.FileName = "*.resx";
		//ファイルフィルターの指定
		ofDlg.Filter = "リソースファイル(*.resources)|*.resources|XMLリソースファイル(*.resx)|*.resx";
		if(FileType)	//ファイルフィルターインデックスの指定
			ofDlg.FilterIndex = 1;
		else
			ofDlg.FilterIndex = 2;
		ofDlg.RestoreDirectory = true;	//初期ディレクトリへ復帰
		ofDlg.CheckFileExists = true;	//ファイルの存在チェック
		ofDlg.CheckPathExists = true;	//ファイルパスの存在チェック
		ofDlg.InitialDirectory = ".";	// デフォルトのフォルダーの指定
		ofDlg.Title = "ファイルを開く";	//ダイアログのタイトルを指定する
		if(ofDlg.ShowDialog() == DialogResult.OK)	//ダイアログを表示する
		{
			ResFileName = ofDlg.FileName;		//リソースファイルのパス、名を保存
			tssl[2].Text = ResFileName;			//ステータスバーにファイルパス、名を表示
			tssl[2].ToolTipText = ResFileName;	//ステータスバーツールチップにファイルパス、名を設定
			listView.Items.Clear();				//既存のリストビューのデータを消去する
			if(FileType)
			{	//*.resourcesファイルの読み込み(usingを使ってDisposeする)
				using(ResourceReader resReader = new ResourceReader(ResFileName))
				{
					IDictionaryEnumerator iDict = resReader.GetEnumerator();
					string str;
					ListViewItem add_item;
					while(iDict.MoveNext())
					{
						str = String.Format("{0}", iDict.Key);
						add_item = listView.Items.Add(str);
						str = String.Format("{0}", iDict.Value.GetType().Name);
						add_item.SubItems.Add(str);
						str = String.Format("{0}", iDict.Value);
						add_item.SubItems.Add(str);
					}
				}
			}
			else
			{	//*.resxファイルの読み込み(usingを使ってDisposeする)
				using (ResXResourceReader resxReader = new ResXResourceReader(ResFileName))
				{
					IDictionaryEnumerator iDict = resxReader.GetEnumerator();
					string str;
					ListViewItem add_item;
					while(iDict.MoveNext())
					{
						str = String.Format("{0}", iDict.Key);
						add_item = listView.Items.Add(str);
						str = String.Format("{0}", iDict.Value.GetType().Name);
						add_item.SubItems.Add(str);
						str = String.Format("{0}", iDict.Value);
						add_item.SubItems.Add(str);
					}
				}
			}
		}
		else
		{
			MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
		}
		// オブジェクトを破棄する
		ofDlg.Dispose();
	}

	//「保存」処理
	private void OnSave_Click(object sender, EventArgs e)
	{
		//選択された行数を確認する
		if(listView.SelectedItems.Count == 0)
			MessageBox.Show("データが選択されていません", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
		else
		{
			//選択されたアイテムを保存する
			foreach(ListViewItem item in listView.SelectedItems)
			{
				SaveDlg savedlg = new SaveDlg(item.SubItems[0].Text, item.SubItems[1].Text, item.SubItems[2].Text, FileType, ResFileName);
				savedlg.ShowDialog();
				//すべてのStringリソースを".restext"ファイルとして保存する
				if(savedlg.ResType == "StrResCollection")
				{
					string res_str = "";
					foreach(ListViewItem str_item in listView.Items)
					{
						if(str_item.SubItems[1].Text == "String")
						{
							res_str += (str_item.SubItems[0].Text + "=" + str_item.SubItems[2].Text + "\n");
						}
					}
					//Textリソースの保存
					string path = savedlg.ResData;
					path = Path.ChangeExtension(path, ".restext");
					using(StreamWriter sw = new StreamWriter(path))
					{
						sw.Write(res_str);
						sw.Close();
					}
				}
				savedlg.Dispose();
			}
		}
	}

	//「終了」処理
	private void OnExit_Click(object sender, EventArgs e)
	{
		Close();	//修了確認はOnClosingメソッドで行う
	}

	//「使い方」処理
	private void OnHowtoUse_Click(object sender, EventArgs e)
	{
		MessageBox.Show("使い方処理です", "メニューアイテム", MessageBoxButtons.OK, MessageBoxIcon.Information);
	}

	//「バージョン」処理
	private void OnVersion_Click(object sender, EventArgs e)
	{
		VersionDlg verDlg = new VersionDlg(this.Icon);
		verDlg.ShowDialog();
		verDlg.Dispose();
	}
}

///////////////////////////////////////////
//ListViewの項目の並び替えに使用するクラス
///////////////////////////////////////////
public class ListViewItemComparer : IComparer
{
	private int m_column;

	// ListViewItemComparerクラスのコンストラクタ
	public ListViewItemComparer(int col)
	{
		m_column = col;
	}

	//xがyより小さいときはマイナスの数、大きいときはプラスの数、同じときは0を返す
	public int Compare(object x, object y)
	{
		//ListViewItemの取得
		ListViewItem itemx = (ListViewItem) x;
		ListViewItem itemy = (ListViewItem) y;
		//xとyを文字列として比較する
		return string.Compare(itemx.SubItems[m_column].Text, itemy.SubItems[m_column].Text);
	}
}

/////////////////////////
//リソース保存ダイアログ
/////////////////////////
class SaveDlg : Form
{
	//プロパティ
	string m_Name = "";
	public string ResName
	{
		get
		{
			return m_Name;
		}
		set
		{
			m_Name = value;
		}
	}

	protected string m_Type = "";
	public string ResType
	{
		get
		{
			return m_Type;
		}
		set
		{
			m_Type = value;
		}
	}

	protected string m_Data = "";
	public string ResData
	{
		get
		{
			return m_Data;
		}
		set
		{
			m_Data = value;
		}
	}

	//リソースファイルとタイプ
	bool FileType = true;
	string ResFileName = "";

	//ダイアログのコントロール
	Button BtnOK;
	Button BtnCancel;
	Label labelName;
	TextBox txbName;
	GroupBox gBox;
	RadioButton rdBtnImg;
	RadioButton rdBtnFile;
	RadioButton rdBtnStr;
	Button BtnShow;
	Label labelData;
	Button BtnSelFile;
	TextBox txbPath;

	public SaveDlg(string arg_name, string arg_type, string arg_data, bool arg_ftype, string arg_filename)
	{
		//引数の記録
		m_Name = arg_name;
		m_Type = arg_type;
		m_Data = arg_data;
		FileType = arg_ftype;
		ResFileName = arg_filename;

		//ダイアログの属性設定
		this.Text = "リソース保存ダイアログ";
		this.ClientSize = new Size(320, 220);
		this.MaximizeBox = false;		// 最大化ボタン
		this.MinimizeBox = false;		// 最小化ボタン
		this.ShowInTaskbar = false;		//タスクバー上表示
		this.FormBorderStyle = FormBorderStyle.FixedDialog;		// 境界のスタイル
		this.StartPosition = FormStartPosition.CenterParent;	// 親フォームの中央に配置

		//コントロールの属性設定
		BtnOK = new Button();
		BtnOK.TabIndex = 2;
		BtnOK.Location = new Point(20, ClientSize.Height - BtnOK.Height - 10);
		BtnOK.Text = "OK";
		BtnOK.AutoSize = true;
		BtnOK.Click += new EventHandler(OnOK_Click);

		BtnCancel = new Button();
		BtnCancel.TabIndex = 3;
		BtnCancel.Location = new Point(ClientSize.Width - BtnCancel.Width - 20, ClientSize.Height - BtnCancel.Height - 10);
		BtnCancel.Text = "Cancel";
		BtnCancel.AutoSize = true;
		BtnCancel.Click += new EventHandler(OnCancel_Click);

		labelName = new Label();
		labelName.Text = "リソース名";
		labelName.Location = new Point(10, 10);
		labelName.AutoSize = true;

		txbName = new TextBox();
		txbName.Text = m_Name;
		txbName.ReadOnly = true;
		txbName.BorderStyle = BorderStyle.Fixed3D;
		txbName.Location = new Point(20 + labelName.Width, 10);
		txbName.Size = new Size(ClientSize.Width - labelName.Width - 30, 16);

		gBox = new GroupBox();
		gBox.Text = "リソース区分";
		gBox.Location = new Point(5, labelName.Height + 10);
		gBox.Size = new Size(ClientSize.Width - 10, 40);

		rdBtnImg = new RadioButton();
		rdBtnImg.Location = new Point(10, 15);
		rdBtnImg.Size = new Size(80, 16);
		rdBtnImg.Text = "イメージ";
		rdBtnImg.AutoCheck = false;
		if(m_Type == "Bitmap" || m_Type == "Icon")
			rdBtnImg.Checked = true;

		rdBtnFile = new RadioButton();
		rdBtnFile.Location = new Point(gBox.Width / 3 + 10, 15);
		rdBtnFile.Size = new Size(80, 16);
		rdBtnFile.Text = "ファイル";
		rdBtnFile.AutoCheck = false;
		if(m_Type == "Byte[]" || m_Type == "Metafile" || m_Type == "MemoryStream" || m_Type == "PinnedBufferMemoryStream")
			rdBtnFile.Checked = true;

		rdBtnStr = new RadioButton();
		rdBtnStr.Location = new Point(gBox.Width * 2 / 3 + 20, 15);
		rdBtnStr.Size = new Size(80, 16);
		rdBtnStr.Text = "文字列";
		rdBtnStr.AutoCheck = false;
		if(m_Type == "String")
			rdBtnStr.Checked = true;

		BtnShow = new Button();
		BtnShow.TabIndex = 0;
		BtnShow.Location = new Point(ClientSize.Width - BtnShow.Width - 20, labelName.Height + gBox.Height + 15);
		BtnShow.Text = "表示";
		BtnShow.AutoSize = true;
		BtnShow.Click += new EventHandler(OnShow_Click);

		labelData = new Label();
		labelData.Text = "リソースデータ";
		labelData.Location = new Point(10, labelName.Height + gBox.Height + 20);
		labelData.AutoSize = true;

		BtnSelFile = new Button();
		BtnSelFile.TabIndex = 1;
		BtnSelFile.Location = new Point(10, labelName.Height + gBox.Height + labelData.Height + 20);
		BtnSelFile.Size = new Size(ClientSize.Width - 20, 24);
		BtnSelFile.Text = "保存ファイルの指定";
		BtnSelFile.Click += new EventHandler(OnSelFIle_Click);

		txbPath = new TextBox();
		txbPath.Multiline = true;
		txbPath.Text = "";
		txbPath.ReadOnly = true;
		txbPath.BorderStyle = BorderStyle.Fixed3D;
		txbPath.Location = new Point(10, labelName.Height + gBox.Height + labelData.Height + BtnSelFile.Height + 20);
		txbPath.Size = new Size(ClientSize.Width - 20, 48);

		this.Controls.Add(labelName);
		this.Controls.Add(txbName);
		this.Controls.Add(gBox);
		gBox.Controls.Add(rdBtnImg);
		gBox.Controls.Add(rdBtnFile);
		gBox.Controls.Add(rdBtnStr);
		this.Controls.Add(BtnShow);
		this.Controls.Add(labelData);
		this.Controls.Add(BtnSelFile);
		this.Controls.Add(txbPath);
		this.Controls.Add(BtnOK);
		this.Controls.Add(BtnCancel);
	}

	protected void OnShow_Click(object sender, EventArgs e)
	{
		if(FileType)	//*.resourcesファイル
		{
			//ResourceSetを作成する
			ResourceSet rs = new ResourceSet(ResFileName);
			if(m_Type == "Bitmap")
			{
				//Bitmapリソースの読み込み
				Image img = (Bitmap)rs.GetObject(m_Name);
				ImgShow imgdlg = new ImgShow(img);
				imgdlg.ShowDialog();
				imgdlg.Dispose();
			}
			else if(m_Type == "Icon")
			{
				//Iconリソースの読み込み
				Image img = ((Icon)rs.GetObject(m_Name)).ToBitmap();
				ImgShow imgdlg = new ImgShow(img);
				imgdlg.ShowDialog();
				imgdlg.Dispose();
			}
			else if(m_Type == "String")
			{
				StrShow strdlg = new StrShow(m_Data);
				strdlg.ShowDialog();
				strdlg.Dispose();
			}
			else if(m_Type == "Byte[]" || m_Type == "Metafile" || m_Type == "MemoryStream" || m_Type == "PinnedBufferMemoryStream")
			{
				StrShow strdlg = new StrShow(m_Data);
				strdlg.ShowDialog();
				strdlg.Dispose();
			}
			else
				MessageBox.Show("違法なイメージリソースです", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			rs.Dispose();
		}
		else			//*.resxファイル
		{
			//ResXResourceSetを作成する
			ResXResourceSet rsx = new ResXResourceSet(ResFileName);
			if(m_Type == "Bitmap")
			{
				//Bitmapリソースの読み込み
				Image img = (Bitmap)rsx.GetObject(m_Name);
				ImgShow imgdlg = new ImgShow(img);
				imgdlg.ShowDialog();
				imgdlg.Dispose();
			}
			else if(m_Type == "Icon")
			{
				//Iconリソースの読み込み
				Image img = ((Icon)rsx.GetObject(m_Name)).ToBitmap();
				ImgShow imgdlg = new ImgShow(img);
				imgdlg.ShowDialog();
				imgdlg.Dispose();
			}
			else if(m_Type == "String")
			{
				StrShow strdlg = new StrShow(m_Data);
				strdlg.ShowDialog();
				strdlg.Dispose();
			}
			else if(m_Type == "Byte[]" || m_Type == "Metafile" || m_Type == "MemoryStream" || m_Type == "PinnedBufferMemoryStream")
			{
				StrShow strdlg = new StrShow(m_Data);
				strdlg.ShowDialog();
				strdlg.Dispose();
			}
			else
				MessageBox.Show("違法なイメージリソースです", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			rsx.Dispose();
		}
	}

	protected void OnSelFIle_Click(object sender, EventArgs e)
	{
		SaveFileDialog sfDlg = new SaveFileDialog();
		//ファイルフィルターの指定
		sfDlg.Filter = "イメージファイル|*.bmp;*.ico|テキストファイル(*.txt, *.restext)|*.txt;*.restext|すべてのファイル(*.*)|*.*";
		//ファイルフィルターインデックスの指定
		if(m_Type == "Bitmap" || m_Type == "Icon")
			sfDlg.FilterIndex = 1;
		else if(m_Type == "String")
			sfDlg.FilterIndex = 2;
		else
			sfDlg.FilterIndex = 3;
		//ダイアログボックスを閉じる前に現在のディレクトリを復元するようにする
		sfDlg.RestoreDirectory = true;
		//存在しないパスが指定されたとき警告を表示する
		sfDlg.CheckPathExists = true;
		// デフォルトのフォルダを指定する
		sfDlg.InitialDirectory = @".";
		//ダイアログのタイトルを指定する
		sfDlg.Title = "保存するファイルの指定";
		//ダイアログを表示する
		if(sfDlg.ShowDialog() == DialogResult.OK)
		{
			txbPath.Text = sfDlg.FileName;
 		}
		else
		{
			txbPath.Text = "";
			MessageBox.Show("保存ファイルの指定がキャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
		}
		// オブジェクトを破棄する
		sfDlg.Dispose();
	}

	protected void OnOK_Click(object sender, EventArgs e)
	{
		if(String.IsNullOrEmpty(txbPath.Text))
		{
			MessageBox.Show("保存ファイル名が指定されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			return;
		}
		if(FileType)	//*.resourcesファイル
		{
			//ResourceSetを作成する
			ResourceSet rs = new ResourceSet(ResFileName);
			if(m_Type == "Bitmap")
			{
				//Bitmapリソースの保存
				Image img = (Bitmap)rs.GetObject(m_Name);
				img.Save(txbPath.Text, ImageFormat.Bmp);
			}
			else if(m_Type == "Icon")
			{
				//Iconリソースの保存
				Image img = ((Icon)rs.GetObject(m_Name)).ToBitmap();
				img.Save(txbPath.Text, ImageFormat.Icon);
			}
			else if(m_Type == "String")
			{
				//すべての文字列リソースを取得ファイル出力する選択
				DialogResult dr = MessageBox.Show("指定出力ファイルを\".restext\"に変更し、すべての文字列リソースをまとめて出力しますか？", "restextファイル出力確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
				if(dr == DialogResult.Yes)
				{
					m_Name = m_Type = "StrResCollection";
					m_Data = txbPath.Text;
				}
				else
				{
					//Textリソースの保存
					using (StreamWriter sw = new StreamWriter(txbPath.Text))
					{
						sw.WriteLine(m_Data);
						sw.Close();
					}
				}
			}
			else if(m_Type == "Byte[]")
			{
				//Byte[]リソースの保存
				Byte[] bytes = (Byte[])rs.GetObject(m_Name);
				File.WriteAllBytes (txbPath.Text, bytes);
			}
			else if(m_Type == "Metafile")
			{
				Metafile metaFile = (Metafile)rs.GetObject(m_Name);
				Image img = (Metafile)metaFile;
				img.Save(txbPath.Text, ImageFormat.Wmf);
			}
			else if(m_Type == "MemoryStream")
			{
				using (FileStream file = new FileStream(txbPath.Text, FileMode.Create, FileAccess.Write))	//FileMode.Createは既存のファイルがあれば上書きする
				{
					MemoryStream mStream = (MemoryStream)rs.GetObject(m_Name);
					mStream.WriteTo(file);
				}
				/* MemoryStreamリソースの保存の他の方法
				MemoryStream mStream = (MemoryStream)rsx.GetObject(m_Name);
				File.WriteAllBytes(txbPath.Text, mStream.ToArray()); 
				*/
			}
			else if(m_Type == "PinnedBufferMemoryStream")
			{
				ResourceReader rr = new ResourceReader(ResFileName);
				string resType = "";
				byte[] resData;
				rr.GetResourceData(m_Name, out resType, out resData);
				try
				{
					BinaryWriter bWriter = new BinaryWriter(new FileStream(txbPath.Text, FileMode.Create));	//FileMode.Createは既存のファイルがあれば上書きする
					bWriter.Write(resData);	//書き出されるが0バイトファイルになっている。
				}
				catch
				{}
				finally
				{
					MessageBox.Show("PinnedBufferMemoryStreamリソースは保護されており、アクセスも他の形にキャストもできません。", "保存不能", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				}
				/*
				//ResourceSetでは対応できないので、ResourceReaderのGetResourceDataメソッドを使ってみたらすんなり決まった！
				ResourceReader rr = new ResourceReader(ResFileName);
				string resType = "";
				byte[] resData;
				rr.GetResourceData(m_Name, out resType, out resData);
				resType = String.Format("Resource Type: {0} and the Size : {1}", resType, resData.Length);
				MessageBox.Show(resType, "PinnedBufferMemoryStream 情報", MessageBoxButtons.OK, MessageBoxIcon.Information);
				//使用されたパラメーターが有効ではありません。
				//場所 System.Drawing.Image.FromStream(Stream stream, Boolean useEmbeddedColorManagement, Boolean validateImageData)
				MemoryStream mstream = new MemoryStream(resData);
				Image img = Image.FromStream(mstream);
				ImgShow imgdlg = new ImgShow(img);
				imgdlg.ShowDialog();

				//ImageConverter imgconv = new ImageConverter();
				//Image img = (Image)imgconv.ConvertFrom(resData);
				*/

				/* http://www.dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/IO/PinnedBufferMemoryStream@cs/1305376/PinnedBufferMemoryStream@cs
					↑によればunmanagedMemoryStreamから派生させたクラスなので、↓で行けるかと思ったのですが「'System.IO.PinnedBufferMemoryStream' はアクセスできない保護レベルになっています」エラーが出ます。
				using (FileStream file = new FileStream(txbPath.Text, FileMode.Create, FileAccess.Write))	//FileMode.Createは既存のファイルがあれば上書きする
				{
					PinnedBufferMemoryStream pbms  = (PinnedBufferMemoryStream)rs.GetObject(m_Name);
					pbms.WriteTo(file);
				}
				仕方がないので、無理やりMemoryStreamで読む実験をします。
				using(FileStream file = new FileStream(txbPath.Text, FileMode.Create, FileAccess.Write))	//FileMode.Createは既存のファイルがあれば上書きする
				{
					MemoryStream mStream = (MemoryStream)rs.GetObject(m_Name);
					mStream.WriteTo(file);
				}
				矢張り「System.InvalidCastException: 型 'System.IO.PinnedBufferMemoryStream' のオブジェクトを型 'System.IO.MemoryStream' にキャストできません」エラーが出ます。
				PinnedBufferMemoryStream pbms  = (PinnedBufferMemoryStream)rs.GetObject(m_Name);
				File.WriteAllBytes(txbPath.Text, pbms.ToArray()); 
				これもダメ。「PinnedBufferMemoryStream」は保護されており、使えません。
				*/
			}
			else
				MessageBox.Show("違法なイメージリソースです", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			rs.Dispose();
		}
		else			//*.resxファイル
		{
			//ResXResourceSetを作成する
			ResXResourceSet rsx = new ResXResourceSet(ResFileName);
			if(m_Type == "Bitmap")
			{
				//Bitmapリソースの読み込み
				Image img = (Bitmap)rsx.GetObject(m_Name);
				img.Save(txbPath.Text, ImageFormat.Bmp);
			}
			else if(m_Type == "Icon")
			{
				//Iconリソースの読み込み
				Image img = ((Icon)rsx.GetObject(m_Name)).ToBitmap();
				img.Save(txbPath.Text, ImageFormat.Icon);
			}
			else if(m_Type == "String")
			{
				//すべての文字列リソースを取得ファイル出力する選択
				DialogResult dr = MessageBox.Show("指定出力ファイルを\".restext\"に変更し、すべての文字列リソースをまとめて出力しますか？", "restextファイル出力確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
				if(dr == DialogResult.Yes)
				{
					m_Name = m_Type = "StrResCollection";
					m_Data = txbPath.Text;
				}
				else
				{
					//Textリソースの保存
					using (StreamWriter sw = new StreamWriter(txbPath.Text))
					{
						sw.WriteLine(m_Data);
						sw.Close();
					}
				}
			}
			else if(m_Type == "Byte[]")
			{
				//Byte[]リソースの保存
				Byte[] bytes = (Byte[])rsx.GetObject(m_Name);
				File.WriteAllBytes(txbPath.Text, bytes);
			}
			else if(m_Type == "Metafile")
			{
				Metafile metaFile = (Metafile)rsx.GetObject(m_Name);
				Image img = (Metafile)metaFile;
				img.Save(txbPath.Text, ImageFormat.Wmf);
			}
			else if(m_Type == "MemoryStream")
			{
				// Case 2 MemoryStreamリソースの保存（保存確認◎−jpgファイル使用）
				using (FileStream file = new FileStream(txbPath.Text, FileMode.Create, FileAccess.Write))	//FileMode.Createは既存のファイルがあれば上書きする
				{
					MemoryStream mStream = (MemoryStream)rsx.GetObject(m_Name);
					mStream.WriteTo(file);
				}
				/* MemoryStreamリソースを保存する他の方法
				MemoryStream mStream = (MemoryStream)rsx.GetObject(m_Name);
				File.WriteAllBytes(txbPath.Text, mStream.ToArray()); 
				*/
			}
			else if(m_Type == "PinnedBufferMemoryStream")
			{
				//ResXResourceReaderクラスはあるが、GetResourceDataメソッドがないので省略。（*.resxファイルでは"PinnedBufferMemoryStream"は出来ないので実質的に問題なし。
				MessageBox.Show("PinnedBufferMemoryStreamリソースは保護されており、アクセスも他の形にキャストもできません。", "保存不能", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				//http://www.dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/IO/PinnedBufferMemoryStream@cs/1305376/PinnedBufferMemoryStream@cs
				
			}
			else
				MessageBox.Show("違法なイメージリソースです", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			rsx.Dispose();
		}
		Close();
	}

	protected void OnCancel_Click(object sender, EventArgs e)
	{
		Close();
	}
}

///////////////////////
//ImgShow ダイアログ
///////////////////////
class ImgShow : Form
{
	public ImgShow(Image img)
	{
		//表示用ウィンドウフォームの作成
		this.Size = new Size(300, 300);
		this.Text = "画像リソースデータ";	//タイトル
		this.MaximizeBox = false;			// 最大化ボタン
		this.MinimizeBox = false;			// 最小化ボタン
		this.StartPosition = FormStartPosition.CenterScreen;	//画面中央に配置
		this.ShowInTaskbar = false;			//タスクバー上非表示
		this.ShowInTaskbar = false;			//タスクバー上非表示
		//表示用ピクチャーボックスの作成
		PictureBox picbox = new PictureBox();
		picbox.Bounds = this.RestoreBounds;
		picbox.BorderStyle = BorderStyle.Fixed3D;
		picbox.Image = img;					//表示用Bitmapデータの設定
		picbox.SizeMode = PictureBoxSizeMode.StretchImage;
		picbox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
		picbox.Click += new EventHandler(Dlg_OnClick);
		this.Controls.Add(picbox);			//ピクチャーボックスをウィンドウに張り付ける
	}

	private void Dlg_OnClick(Object sender, EventArgs e)
	{
		Close();
		Dispose();
	}
}

///////////////////////
//StrShow ダイアログ
///////////////////////
class StrShow : Form
{
	public StrShow(string str)
	{
		//表示用ウィンドウフォームの作成
		this.Size = new Size(360, 180);
		this.Text = "その他リソースデータ";	//タイトル
		this.MaximizeBox = false;		// 最大化ボタン
		this.MinimizeBox = false;		// 最小化ボタン
		this.StartPosition = FormStartPosition.CenterScreen;	//画面中央に配置
		this.ShowInTaskbar = false;		//タスクバー上表示
		//表示用テキストボックスの作成
		TextBox txtbox = new TextBox();
		txtbox.Bounds = this.RestoreBounds;
		txtbox.ScrollBars = ScrollBars.Vertical;
		txtbox.Multiline = true;
		txtbox.ReadOnly = true;
		txtbox.BorderStyle = BorderStyle.Fixed3D;
		txtbox.Text = str;				//表示用strデータ
		txtbox.Click += new EventHandler(Dlg_OnClick);
		txtbox.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
		this.Controls.Add(txtbox);		//テキストボックスをウィンドウに張り付ける
	}

	private void Dlg_OnClick(object sender, EventArgs e)
	{
		Close();
		Dispose();
	}
}

/////////////////////
//Version ダイアログ
/////////////////////
class VersionDlg : Form
{
	public VersionDlg(Icon ico)
	{
		//ダイアログの属性設定
		this.Text = "バーション情報";
		this.ClientSize = new Size(320, 100);
		this.MaximizeBox = false;		// 最大化ボタン
		this.MinimizeBox = false;		// 最小化ボタン
		this.ShowInTaskbar = false;		//タスクバー上表示
		this.FormBorderStyle = FormBorderStyle.FixedDialog;		// 境界のスタイル
		this.StartPosition = FormStartPosition.CenterParent;	// 親フォームの中央に配置
		//コントロールの属性設定
		Button btnOK = new Button();
		btnOK.Size = new Size(40, 28);
		btnOK.Location = new Point(ClientSize.Width - btnOK.Width - 10, (ClientSize.Height - btnOK.Height) / 2);
		btnOK.Text = "OK";
		btnOK.Click += new EventHandler(OnOK_Click);
		Label imglabel = new Label();
		imglabel.Size = new Size(40, 40);
		imglabel.Location = new Point(10, (ClientSize.Height - imglabel.Height) / 2);
		imglabel.BorderStyle = BorderStyle.Fixed3D;
		imglabel.Image = ico.ToBitmap();	//親のシステムアイコン
		Label label = new Label();
		label.Size = new Size(ClientSize.Width - imglabel.Width - btnOK.Width - 40, ClientSize.Height- 20);
		label.Location = new Point(imglabel.Width + 20, (ClientSize.Height - label.Height) / 2);
		label.BorderStyle = BorderStyle.Fixed3D;
		label.Text = "ResReader Version 1.0\r\nCopyright (c) 2022 by Ysama\r\n(written in Microsoft C#)";
		label.TextAlign = ContentAlignment.MiddleCenter;
		label.Font = new Font("Times New Roman", 10, FontStyle.Bold);
		this.Controls.Add(btnOK);
		this.Controls.Add(imglabel);
		this.Controls.Add(label);
	}

	private void OnOK_Click(object sender, EventArgs e)
	{
		Close();
	}
}
