///////////////////////////////
//		IDList_CS.cs
// Copyright (c) 2026 by ysama
// https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.datagridview?view=windowsdesktop-10.0
///////////////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;		//[DisplayName()]使用の為
using System.IO;					//StreamReader使用の為
using System.Text;  				//Encoding.GetEncoding使用の為
using System.Security.Cryptography;	//データの暗号化の為

namespace IDList_CS
{
	///////////////////////////////////
	//IDListで使用するIDデータのクラス
	///////////////////////////////////
	public class idItem
	{
 		[DisplayName("メンバーシップ")]
		public string Membership {get; set;}
 		[DisplayName("ログインID")]
		public string ID {get; set;}
 		[DisplayName("パスワード")]
		public string Password {get; set;}
 		[DisplayName("備考")]
		public string Remark {get; set;}

		//比較メソッドの定義
		public int CompareMembershipTo(idItem other)
		{
			if(ReferenceEquals(other, null))		//参照比較
				return 1;							//thisが大きい
			//0なら等しい、負なら小さい、正なら大きい
			return this.Membership.CompareTo(other.Membership);
		}

		public int CompareIDTo(idItem other)
		{
			if(ReferenceEquals(other, null))		//参照比較
				return 1;							//thisが大きい
			//0なら等しい、負なら小さい、正なら大きい
			return this.ID.CompareTo(other.ID);
		}

		public int ComparePasswordTo(idItem other)
		{
			if(ReferenceEquals(other, null))		//参照比較
				return 1;							//thisが大きい
			//0なら等しい、負なら小さい、正なら大きい
			return this.Password.CompareTo(other.Password);
		}

		public int CompareRemarkTo(idItem other)
		{
			if(ReferenceEquals(other, null))		//参照比較
				return 1;							//thisが大きい
			//0なら等しい、負なら小さい、正なら大きい
			return this.Remark.CompareTo(other.Remark);
		}
	}

	/////////////////////////////////////
	//idListクラス（DataGridViewから派生）
	/////////////////////////////////////
	public class idList : DataGridView
	{
		//idItemのデータリスト
		List <idItem> idItems = new List <idItem> ();
		//DataGridViewのバインディングデータソース
		BindingSource bs = new BindingSource();
		//システムデータファイルパス
		const string dfPath = ".\\IDListFiles\\IDList.dat";
		//コンテキストメニュー
		ContextMenuStrip cms = new ContextMenuStrip();
		//並び替え順（true - 昇順、false - 降順）
		bool sortOrder = true;
		//コンストラクター
		public idList()
		{
			//DataGridViewの設定
			this.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
			this.EditMode = DataGridViewEditMode.EditProgrammatically;		//ダブルクリック編集不可
			this.SelectionMode = DataGridViewSelectionMode.FullRowSelect;	//一行選択
			this.AllowUserToAddRows = false;								//末尾の空行禁止
			bs.DataSource = idItems;	//bsのデータソースにidItemsをセット
			this.DataSource = bs;		//DataGridViewのデータソースにidItemsをセット
			this.DataBindingComplete += On_DataBindingComplete;
			this.ColumnHeaderMouseClick += On_ColumnHeaderMouseClick;
			this.CellDoubleClick += On_CellDoubleClick;
			//コンテキストメニュー設定
		    cms.Items.Add("追加", null, AddItem_Click);
		    cms.Items.Add("検索", null, FindItem_Click);
		    cms.Items.Add("編集", null, EditItem_Click);
		    cms.Items.Add("削除", null, DeleteItem_Click);
			this.ContextMenuStrip = cms;
			//*.datファイル用ディレクトリーの作成（初回のみ）
			Directory.CreateDirectory(".\\IDListFiles");
			//dfPathファイルのデータを読み込む
			DataRead(dfPath, true);		//dfPathを暗号化で読む
		}

		//サイズ変更時処理
		protected override void OnResize(EventArgs e)
		{
			base.OnResize(e);
			//起動時はColumnCount == 0でエラーになる為
			if(this.ColumnCount > 3 && this.ClientSize.Width >= 560)
				this.Columns[3].Width = this.ClientSize.Width - 560;
		}

		//終了時ファイル保存処理
		protected override void OnHandleDestroyed(EventArgs e)
		{
			if (this.IsCurrentCellInEditMode)
			{
				this.EndEdit();				//編集中データを確定させる
			}
			DataWrite(dfPath, true, true);	//dfPathを暗号化、隠しファイルで保存
			base.OnHandleDestroyed(e);
 		}

		//DataGridViewのデータバインディング完了イベント
		private void On_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
		{
			//列幅の設定
			this.Columns[0].Width = 240;
			this.Columns[1].Width = 160;
			this.Columns[2].Width = 160;
			if(this.Width < 560)	//「備考」幅は560以下にはしない
				this.Columns[3].Width = 560;
			else
				this.Columns[3].Width = this.ClientSize.Width - 560;
			//第2、3列は中央揃えにする
			this.Columns[1].DefaultCellStyle.Alignment =DataGridViewContentAlignment.MiddleCenter;
			this.Columns[2].DefaultCellStyle.Alignment =DataGridViewContentAlignment.MiddleCenter;
		}

		//DataGridViewの列ヘッダークリックイベント
		private void On_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
		{
			//クリックされた列の番号を取得
			int colIndex = e.ColumnIndex;
			string colName = (sender as DataGridView).Columns[colIndex].Name;
			switch(colName)
			{
				case "Membership":
					if(sortOrder)
						idItems.Sort((x, y) => x.CompareMembershipTo(y));
					else
						idItems.Sort((x, y) => y.CompareMembershipTo(x));
					break;
				case "ID":
					if(sortOrder)
						idItems.Sort((x, y) => x.CompareIDTo(y));
					else
						idItems.Sort((x, y) => y.CompareIDTo(x));
					break;
				case "Password":
					if(sortOrder)
						idItems.Sort((x, y) => x.ComparePasswordTo(y));
					else
						idItems.Sort((x, y) => y.ComparePasswordTo(x));
					break;
				case "Remark":
					if(sortOrder)
						idItems.Sort((x, y) => x.CompareRemarkTo(y));
					else
						idItems.Sort((x, y) => y.CompareRemarkTo(x));
					break;
			}
			bs.ResetBindings(false);
			sortOrder = !sortOrder;		//トグル変更（昇順←→降順）
		}

		//DataGridViewのダブルクリックイベント
		private void On_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
		{
			DataGridViewRow target = this.Rows[e.RowIndex];
			//編集処理
			AddEditDlg aeDlg = new AddEditDlg(target);
			aeDlg.ShowDialog();						//AddEditDlg表示
			bs.EndEdit();							//編集データのListとの同期
			aeDlg.Dispose();
		}

		//追加の公開メソッドと内部イベントメソッド
		public void Add()
		{
			AddItem_Click(cms, null);
		}

		private void AddItem_Click(object sender, EventArgs e)
		{
			//追加処理
			AddEditDlg aeDlg = new AddEditDlg();	//AddEditDlg表示
			aeDlg.ShowDialog();
			if(!ReferenceEquals(aeDlg.iditem, null))
			{
				idItems.Add(aeDlg.iditem);			//追加データのListへの追加
				bs.ResetBindings(false);			//idItems変更をDataGridViewへ反映する
			}
			else
				MessageBox.Show("新データは追加されませんでした。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
			aeDlg.Dispose();
		}

		//編集の公開メソッドと内部イベントメソッド
		public void Edit()
		{
			EditItem_Click(cms, null);
		}

		private void EditItem_Click(object sender, EventArgs e)
		{
			//選択がなければその旨確認して何もしない
			if(this.SelectedRows.Count == 0)
			{
				MessageBox.Show("選択された行がありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}
			//編集処理（複数行可）
			foreach (DataGridViewRow sel in this.SelectedRows)
			{
				//編集処理
				AddEditDlg aeDlg = new AddEditDlg(sel);	//AddEditDlg表示
				aeDlg.ShowDialog();
				bs.EndEdit();							//編集データのListとの同期
				aeDlg.Dispose();
			}
		}

		//検索の公開メソッドと内部イベントメソッド
		public void Find()
		{
			FindItem_Click(cms, null);
		}

		private void FindItem_Click(object sender, EventArgs e)
		{
			//検索処理（検索結果の行をSelectedRowとして表示する）
			FindDlg findDlg = new FindDlg(this);	//FindDlg表示
			findDlg.ShowDialog();					//List（idItems）の検索は行わない
			findDlg.Dispose();
		}

		//削除の公開メソッドと内部イベントメソッド
		public void Delete()
		{
			DeleteItem_Click(cms, null);
		}

		private void DeleteItem_Click(object sender, EventArgs e)
		{
			//選択がなければその旨確認して何もしない
			if(this.SelectedRows.Count == 0)
			{
				MessageBox.Show("選択された行がありません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
				return;
			}
			//削除処理（複数行可）－コントロールの選択行を基にidItemsの要素を削除
			if(MessageBox.Show("本当に削除しますか？", "確認", MessageBoxButtons.YesNo,
				MessageBoxIcon.Question) == DialogResult.Yes)
			{
				foreach (DataGridViewRow sel in this.SelectedRows)
				{
					idItems.RemoveAt(sel.Index);
				}
			}
			bs.ResetBindings(false);	//idItems変更をDataGridViewへ反映する
			this.ClearSelection();		//選択を解除する
		}

		//データの並び替え
		public void Sort()
		{
			SortDlg sortDlg = new SortDlg();	//SortDlg表示
			sortDlg.ShowDialog();
			//列番号に基づいて並び変える
			switch(sortDlg.ColIndex)
			{
				case 0:
					if(sortDlg.IsAscending)
						idItems.Sort((x, y) => x.CompareMembershipTo(y));
					else
						idItems.Sort((x, y) => y.CompareMembershipTo(x));
					break;
				case 1:
					if(sortDlg.IsAscending)
						idItems.Sort((x, y) => x.CompareIDTo(y));
					else
						idItems.Sort((x, y) => y.CompareIDTo(x));
					break;
				case 2:
					if(sortDlg.IsAscending)
						idItems.Sort((x, y) => x.ComparePasswordTo(y));
					else
						idItems.Sort((x, y) => y.ComparePasswordTo(x));
					break;
				case 3:
					if(sortDlg.IsAscending)
						idItems.Sort((x, y) => x.CompareRemarkTo(y));
					else
						idItems.Sort((x, y) => y.CompareRemarkTo(x));
					break;
			}
			bs.ResetBindings(false);
			sortDlg.Dispose();
		}

		//データ入力
		public bool DataRead(string fn, bool crypt)
		{
			//ファイル入出力用データ
			string fData = String.Empty;
			//ファイル読み込み（入力UTF-8）
			try
			{
				using(StreamReader file = new StreamReader(fn, Encoding.UTF8))
				{
					if(crypt)					//暗号化ファイルを読む
						fData = DecryptData(file.ReadToEnd());
					else						//平文ファイルを読む
						fData = file.ReadToEnd();
					file.Close();				//ファイルを閉じる
				}
			}
			catch(Exception e)					//エラー表示
			{
				MessageBox.Show("エラーが発生しました。\r\n" + e.Message , "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			//既存のidItemsデータを"IDList.dbk"（暗号化、非隠しファイル）で保存
			if(idItems.Count > 0)				//起動時の自動読み込みでは実行しない
				DataWrite(".\\IDListFiles\\IDList.dbk", true, false);
			//平文のCSVデータ文字列（fData）をidItemsへ登録
			idItems.Clear();					//idItemsを初期化する
			while(fData.Length > 0)				//fDataは切り取られてゆく
			{
				idItem item = new idItem();		//入力用局所変数
				for(int i = 0; i < 4; i++)
				{
					string token = GetDelimitStr(ref fData);
					switch(i)
					{
						case 0:
							item.Membership = token;
							break;
						case 1:
							item.ID = token;
							break;
						case 2:
							item.Password = token;
							break;
						case 3:
							item.Remark = token;
							break;
					}
					if(fData.Length == 0)		//不完全idItemの場合
						break;
				}
				idItems.Add(item);				//idItemをidItemsへ登録
			}
			//idItemsの内容をDataGridViewに表示する
			bs.ResetBindings(false);
			return true;
		}

		//文字列の復号化
		static string DecryptData(string data)
		{
			byte[] dataBytes = Convert.FromBase64String(data);
			byte[] decryptedBytes = ProtectedData.Unprotect(dataBytes,  null, DataProtectionScope.CurrentUser);
			return Encoding.UTF8.GetString(decryptedBytes);
		}

		/////////////////////////////////////
		//カンマ区切り文字列切り出しメソッド
		// str : 切り出すcsvファイル
		//★strは切り出した文字列分短縮され、
		//（ループ条件：str.Length > 0）
		/////////////////////////////////////
		public string GetDelimitStr(ref string str)
		{
			//空文字列チェック
			if(String.IsNullOrEmpty(str))
				return "Error: Empty data.";		//本来str.Lengthが0で呼ばれない
			//フィールド宣言
			char[] cArr = str.ToCharArray();		//長さcArr.Lengthのヌル端末無しの配列
			int cPtr = 0;							//文字列ポインター
			string buff = String.Empty;				//文字列バッファ
			bool dblQuo = false;					//「"～"内」フラグ
			//カンマ区切り文字列切り出しループ
			while(cArr[cPtr] != ',' && cArr[cPtr] != '\r' && cArr[cPtr] != '\n')
			{
				if(cArr[cPtr] == '"')				//「"」があった場合
				{
					//「\"」を除き「"～"」内モードになる
					if(cPtr == 0 || cArr[cPtr - 1] != '\\')
					{
						dblQuo = !dblQuo;				//dblQuoフラグを立てる／下す
						cPtr++;							//'\"'の次に進める
						if(!dblQuo)						//既に「"～"」内ならば
							break;						//ループ終了
						else							//「"～"」内に入ったら
							continue;					//仕切り直し
					}
				}
				buff += cArr[cPtr];					//cArrデータをbuffにコピーし
				cPtr++;								//ポインターを進める
				if(cPtr < cArr.Length && dblQuo)	//既に「"～"」内ならば
				{	//区切り文字があってもコピーし、パスする
					while(cArr[cPtr] == ',' || cArr[cPtr] == '\r' || cArr[cPtr] == '\n')
					{
						buff += cArr[cPtr];			//cArrデータをbuffにコピーし
						cPtr++;						//ポインターを進める
						if(cPtr == cArr.Length)		//括弧が閉じられず、文字列が終了した場合
						{
							buff = "Error: Double quotation marked string not closed.";
							break;
						}
					}
				}
				//文字列終了チェック
				if(cPtr == cArr.Length)				//文字列が終了した場合
						break;						//ループ終了
			}
			//文字列が終了していない場合、区切り文字をスキップする
			if(cPtr < cArr.Length)
			{
				//','、'\r'、'\n'があれば（カンマ、CR、LF単体）
				if(cArr[cPtr] == ',' || cArr[cPtr] == '\r' || cArr[cPtr] == '\n')
					cPtr++;		//スキップする
				//更に文字があり、改行文字（CR、LF）の片割れがあれば
				if(cPtr < cArr.Length && (cArr[cPtr] == '\n' || cArr[cPtr] == '\r'))
					cPtr++;		//もう一文字スキップする
			}
			//strを残余の文字列に切り詰める
			str = new string(cArr, cPtr, cArr.Length - cPtr);
			//切り取った文字列またはエラーメッセージを返す
			return buff;
		}

		//データ出力
		public bool DataWrite(string fn, bool crypt, bool hide)
		{
			FileInfo fi = new FileInfo(fn);						//FileInfoはfnがなくとも例外にならない
			if(fi.Exists &&										//fnが存在し且つ
				fi.Attributes.HasFlag(FileAttributes.Hidden))	//隠しファイル属性があれば
				fi.Attributes &= ~FileAttributes.Hidden;		//隠しファイル属性を外す
			//（C++のように）if((fi.Attributes & FileAttributes.Hidden))だけではbool値を返してくれない。
			//C++のように数値の0を偽（false）、それ以外を真（true）とみなす自動変換（暗黙の型変換）がC#にはない。
			//C#ではif文の条件式に必ずbool型（true または false）を渡す必要があり、エラーとなる。
			//ファイル入出力用データ
			string fData = String.Empty;
			//idItemsデータのCSV化
			foreach(idItem item in idItems)
			{
				//最終列（「備考」）はコントロールコードが入るかもしれないので""で括る
				fData += item.Membership + "," + item.ID + "," + item.Password + ","
						+ "\"" + item.Remark + "\"" + Environment.NewLine;
			}
			fData = fData.TrimEnd();							//最後のCRLFを削除
			//ファイル書き込み（出力UTF-8）
			try
			{
				using (StreamWriter file = new StreamWriter(fn, false, Encoding.UTF8))
				{
					if(crypt)
						file.Write(EncryptData(fData));		//暗号化ファイルを書く
					else
						file.Write(fData);					//平文ファイルを書く
					file.Close();							//ファイルを閉じる
					if(hide)								//隠しファイル属性を追加する
						fi.Attributes |= FileAttributes.Hidden;	
				}
			}
			catch(Exception e)					//エラー表示
			{
				MessageBox.Show("エラーが発生しました。\r\n" + e.Message , "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return false;
			}
			return true;
		}

		//文字列の暗号化
		static string EncryptData(string data)
		{
			byte[] dataBytes = Encoding.UTF8.GetBytes(data);
			byte[] encryptedBytes = ProtectedData.Protect(dataBytes, null, DataProtectionScope.CurrentUser);
			return Convert.ToBase64String(encryptedBytes);
		}
	}

	///////////////////////
	//入力・編集ダイアログ
	///////////////////////
	class AddEditDlg : Form
	{
		//追加データの受け渡し用idItemインスタンス
		public idItem iditem;
		//編集対象となるDataGridViewRow
		DataGridViewRow target;
		//ダイアログのコントロール
		Button BtnOK, BtnCancel;
		Label MsLabel, IdLabel, PwLabel, RmLabel;
		TextBox MsBox, IdBox, PwBox, RmBox;

		public AddEditDlg(DataGridViewRow dgvr = null)
		{
			//対象行を保存
			target = dgvr;
			//ダイアログの属性設定
			this.Text = ReferenceEquals(target, null) ? "データの追加" : "データの編集";
			this.ClientSize = new Size(420, 240);
			this.ControlBox = false;		//システムボタン無効
			this.ShowInTaskbar = false;		//タスクバー上非表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;		//境界のスタイル
			this.StartPosition = FormStartPosition.CenterParent;	//親ダイアログ中央に配置
			this.Load += Form_Load;
		}

		//OnLoad処理
		private void Form_Load(object sender, EventArgs e)
		{
			BtnOK = new Button();
			BtnOK.Location = new Point(ClientSize.Width - BtnOK.Width - 30, ClientSize.Height - BtnOK.Height - 10);
			BtnOK.Text = "OK";
			BtnOK.AutoSize = true;
			BtnOK.DialogResult = DialogResult.OK;
			BtnOK.Click += new EventHandler(OnOK_Click);
			this.AcceptButton = BtnOK;
			this.Controls.Add(BtnOK);

			BtnCancel = new Button();
			BtnCancel.Location = new Point(30, ClientSize.Height - BtnCancel.Height - 10);
			BtnCancel.Text = "Cancel";
			BtnCancel.AutoSize = true;
			BtnCancel.DialogResult = DialogResult.Cancel;
			BtnCancel.Click += new EventHandler(OnCancel_Click);
			this.CancelButton = BtnCancel;
			this.Controls.Add(BtnCancel);

			MsLabel = new Label();
			MsLabel.Size = new Size(120, 20);
			MsLabel.Location = new Point(10, 10);
			MsLabel.BorderStyle = BorderStyle.Fixed3D;
			MsLabel.TextAlign = ContentAlignment.MiddleCenter;
			MsLabel.Text = "メンバーシップ";
			this.Controls.Add(MsLabel);

			MsBox = new TextBox();
			MsBox.Size = new Size(270, 24);
			MsBox.Location = new Point(140, 10);
			MsBox.Text = ReferenceEquals(target, null) ? String.Empty : target.Cells[0].Value.ToString();
			this.Controls.Add(MsBox);

			IdLabel = new Label();
			IdLabel.Size = new Size(120, 20);
			IdLabel.Location = new Point(10, MsLabel.Height + 15);
			IdLabel.BorderStyle = BorderStyle.Fixed3D;
			IdLabel.TextAlign = ContentAlignment.MiddleCenter;
			IdLabel.Text = "ログインID";
			this.Controls.Add(IdLabel);

			IdBox = new TextBox();
			IdBox.Size = new Size(270, 24);
			IdBox.Location = new Point(140, MsLabel.Height + 15);
			IdBox.Text = ReferenceEquals(target, null) ? String.Empty : target.Cells[1].Value.ToString();
			this.Controls.Add(IdBox);

			PwLabel = new Label();
			PwLabel.Size = new Size(120, 20);
			PwLabel.Location = new Point(10, MsLabel.Height + IdLabel.Height + 20);
			PwLabel.BorderStyle = BorderStyle.Fixed3D;
			PwLabel.TextAlign = ContentAlignment.MiddleCenter;
			PwLabel.Text = "パスワード";
			this.Controls.Add(PwLabel);

			PwBox = new TextBox();
			PwBox.Size = new Size(270, 24);
			PwBox.Location = new Point(140, MsLabel.Height + IdLabel.Height + 20);
			PwBox.Text = ReferenceEquals(target, null) ? String.Empty : target.Cells[2].Value.ToString();
			this.Controls.Add(PwBox);

			RmLabel = new Label();
			RmLabel.Size = new Size(120, 110);
			RmLabel.Location = new Point(10, MsLabel.Height + IdLabel.Height + PwLabel.Height + 25);
			RmLabel.BorderStyle = BorderStyle.Fixed3D;
			RmLabel.TextAlign = ContentAlignment.MiddleCenter;
			RmLabel.Text = "備考";
			this.Controls.Add(RmLabel);

			RmBox = new TextBox();
			RmBox.Size = new Size(270, 114);
			RmBox.Location = new Point(140, MsLabel.Height + IdLabel.Height + PwLabel.Height + 25);
			RmBox.Multiline = true;
			RmBox.AcceptsReturn = true;
			RmBox.Text = ReferenceEquals(target, null) ? String.Empty : target.Cells[3].Value.ToString();
			this.Controls.Add(RmBox);
		}

		//OKボタン処理
		protected void OnOK_Click(object sender, EventArgs e)
		{
			if(ReferenceEquals(target, null))	//追加処理
			{
				iditem = new idItem() {Membership = MsBox.Text, ID = IdBox.Text, Password = PwBox.Text, Remark = RmBox.Text};
			}
			else								//編集処理
			{
				target.Cells[0].Value = MsBox.Text;
				target.Cells[1].Value = IdBox.Text;
				target.Cells[2].Value = PwBox.Text;
				target.Cells[3].Value = RmBox.Text;
			}
			Close();
		}

		//Cancelボタン処理
		protected void OnCancel_Click(object sender, EventArgs e)
		{
			Close();
		}
	}

	/////////////////
	//検索ダイアログ
	/////////////////
	class FindDlg : Form
	{
		//対象となるDataGridView
		DataGridView target;
		//ダイアログのコントロール
		Button BtnOK;
		Label label;
		TextBox tBox;

		public FindDlg(DataGridView dgv)
		{
			//ダイアログの属性設定
			this.Text = "検索";
			this.ClientSize = new Size(160, 100);
			this.ControlBox = false;		//システムボタン無効
			this.ShowInTaskbar = false;		//タスクバー上非表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;		//境界のスタイル
			this.StartPosition = FormStartPosition.CenterParent;	//親ダイアログ中央に配置
			this.Load += Form_Load;
			target = dgv;					//DataGridViewを記録
		}

		//OnLoad処理
		private void Form_Load(object sender, EventArgs e)
		{
			//コントロールの属性設定
			tBox = new TextBox();
			tBox.Size = new Size(140, 24);
			tBox.Location = new Point((ClientSize.Width - tBox.Width) / 2, 30);
			this.Controls.Add(tBox);

			BtnOK = new Button();
			BtnOK.Location = new Point((ClientSize.Width - BtnOK.Width) / 2, ClientSize.Height - BtnOK.Height - 10);
			BtnOK.Text = "OK";
			BtnOK.AutoSize = true;
			BtnOK.DialogResult = DialogResult.OK;
			BtnOK.Click += new EventHandler(OnOK_Click);
			this.Controls.Add(BtnOK);

			label = new Label();
			label.Size = new Size(140, 20);
			label.Location = new Point((ClientSize.Width - label.Width) / 2, 4);
			label.Text = "検索する文字列";
			this.Controls.Add(label);

			this.AcceptButton = this.BtnOK;
			this.KeyPreview = true;
		}

		//OKボタン処理
		protected void OnOK_Click(object sender, EventArgs e)
		{
			if(tBox.Text == String.Empty)
				MessageBox.Show("検索文字列が入力されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			else
			{
				//選択を一旦クリア
				target.ClearSelection();
				bool found = false;
				foreach(DataGridViewRow row in target.Rows)
				{
					foreach(DataGridViewCell cell in row.Cells)
					{
						if(cell.Value != null && cell.Value.ToString().Contains(tBox.Text))
						{
							//セルを選択状態にする
							cell.Selected = true;
							//最初に見つかったセルにフォーカスを合わせる
							if(!found)
							{
								target.CurrentCell = cell;
								found = true;
							}
						}
					}
				}
				Close();
			}
		}
	}

	///////////////////
	//ソートダイアログ
	///////////////////
	class SortDlg : Form
	{
		//ダイアログのフィールド
		public int ColIndex;
		public bool IsAscending;

		//ダイアログのコントロール
		Button BtnOK;
		ComboBox ColList;		//DropDownStyleプロパティをDropDownList
		ComboBox ADList;		//Ascending|Decending（昇順、降順指定）

		public SortDlg()
		{
			//ダイアログの属性設定
			this.Text = "データの並び替え";
			this.ClientSize = new Size(160, 100);
			this.ControlBox = false;		//システムボタン無効
			this.ShowInTaskbar = false;		//タスクバー上非表示
			this.FormBorderStyle = FormBorderStyle.FixedDialog;		//境界のスタイル
			this.StartPosition = FormStartPosition.CenterParent;	//親ダイアログ中央に配置
			this.Load += Form_Load;
		}

		//OnLoad処理
		private void Form_Load(object sender, EventArgs e)
		{
			//コントロールの属性設定
			BtnOK = new Button();
			BtnOK.Location = new Point((ClientSize.Width - BtnOK.Width) / 2, ClientSize.Height - BtnOK.Height - 10);
			BtnOK.Text = "完了";
			BtnOK.AutoSize = true;
			BtnOK.Click += new EventHandler(OnOK_Click);
			this.Controls.Add(BtnOK);

			ColList = new ComboBox();
			ColList.DropDownStyle = ComboBoxStyle.DropDownList;
			ColList.Location = new Point((ClientSize.Width - ColList.Width) / 2, 10);
			ColList.MaxDropDownItems = 4;
			ColList.Items.Add("メンバーシップ");
			ColList.Items.Add("ログインID");
			ColList.Items.Add("パスワード");
			ColList.Items.Add("備考");
			ColList.SelectedIndex = 0;
			this.Controls.Add(ColList);

			ADList = new ComboBox();
			ADList.DropDownStyle = ComboBoxStyle.DropDownList;
			ADList.Location = new Point((ClientSize.Width - ADList.Width) / 2, 40);
			ADList.MaxDropDownItems = 2;
			ADList.Items.Add("昇順");
			ADList.Items.Add("降順");
			ADList.SelectedIndex = 0;
			this.Controls.Add(ADList);
		}

		//OKボタン処理
		protected void OnOK_Click(object sender, EventArgs e)
		{
			if(ColList.SelectedIndex == -1)
				MessageBox.Show("並び替えが選択されていません。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
			else
			{
				ColIndex = ColList.SelectedIndex;
				IsAscending = (ADList.SelectedIndex == 0);
				Close();
			}
		}
	}
}
