/////////////////////
// PropertyAny.cs
// 参考サイト：https://dobon.net/vb/dotnet/control/propertygrid.html
/////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Imaging;
using System.ComponentModel;			//PropertyGridの[]機能を使う為
using System.IO;						//FileInfoオブジェクト取得の為
using System.Diagnostics;				//GetProcessを使う為
using System.Runtime.InteropServices;	//GetWindowRectを使用するために必要

namespace PropertyAny
{
	public class App : Form
	{
		private SplitContainer split;
		private PropertyGrid propGrid;
		private Button btnExit;
		private Button btnFile;
		private Button btnImage;
		private Button btnPickWindow;
		private Panel panel;

		[STAThread]
		public static void Main()
		{
			Application.Run(new App());
		}

		public App()
		{
			this.Text = "PropertyAny";
			this.Width = 640;
			this.Height = 480;
			this.MinimumSize = new Size(640, 240);
			//Drag and Dropでの処理
			this.AllowDrop = true;
			this.DragEnter += PropGrid_DragEnter;
			this.DragDrop += PropGrid_DragDrop;

			//スプリッター
			split = new SplitContainer();
			split.Dock = DockStyle.Fill;
			split.Orientation = Orientation.Vertical;
			split.SplitterDistance = 240;
			this.Controls.Add(split);
			//左PropertyGrid
			propGrid = new PropertyGrid();
			propGrid.Dock = DockStyle.Fill;
			propGrid.SelectedObject = this;
			split.Panel1.Controls.Add(propGrid);
			//右側側パネル
			panel = new Panel();
			panel.Dock = DockStyle.Fill;
			split.Panel2.Controls.Add(panel);
			//ボタン
			btnExit = new Button {Text = "終了", Dock = DockStyle.Bottom};
			btnExit.Height = 30;
			btnExit.Click += BtnExit_Click;
			panel.Controls.Add(btnExit);
			btnPickWindow = new Button {Text = "ウィンドウ情報", Dock = DockStyle.Top};
			btnPickWindow.Height = 30;
			btnPickWindow.Click += BtnPickWindow_Click;
			panel.Controls.Add(btnPickWindow);
			btnImage = new Button {Text = "画像情報", Dock = DockStyle.Top};
			btnImage.Height = 30;
			btnImage.Click += BtnImage_Click;
			panel.Controls.Add(btnImage);
			btnFile = new Button {Text = "ファイル情報", Dock = DockStyle.Top};
			btnFile.Height = 30;
			btnFile.Click += BtnFile_Click;
			panel.Controls.Add(btnFile);
		}

		//終了処理
		private void BtnExit_Click(object sender, EventArgs e)
		{
			DialogResult dr = MessageBox.Show("終了しますか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
			if(dr == DialogResult.Yes)
				Close();	//終了する
		}

		//ファイル情報
		private void BtnFile_Click(object sender, EventArgs e)
		{
			using(OpenFileDialog dlg = new OpenFileDialog())
			{
				dlg.Filter = "すべてのファイル|*.*";
				if(dlg.ShowDialog() == DialogResult.OK)
				{
					propGrid.SelectedObject = new FileInfo(dlg.FileName);
				}
			}
		}

		//画像情報
		private void BtnImage_Click(object sender, EventArgs e)
		{
			using(OpenFileDialog dlg = new OpenFileDialog())
			{
				dlg.Filter = "画像ファイル|*.bmp;*.png;*.jpg;*.jpeg;*.gif;*.ico";
				if (dlg.ShowDialog() == DialogResult.OK)
				{
					propGrid.SelectedObject = new ImageInfo(dlg.FileName);
				}
			}
		}

		//ウィンドウ情報
		private void BtnPickWindow_Click(object sender, EventArgs e)
		{
			WindowInfo wi = new WindowInfo();
			using(WinSelect wsDlg = new WinSelect(ref wi))
			{
				wsDlg.ShowDialog();
				propGrid.SelectedObject = wi;
			}	
		}

		private void PropGrid_DragEnter(object sender, DragEventArgs e)
		{
			if(e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				e.Effect = DragDropEffects.Copy;
			}
		}

		private void PropGrid_DragDrop(object sender, DragEventArgs e)
		{
			string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
			if(files.Length > 0)
			{
				string ImgExtentions = ".bmp, .png, .jpg, .jpeg, .gif, .ico";
				if(ImgExtentions.Contains(Path.GetExtension(files[0]).ToLower()))
				{
					DialogResult dr = MessageBox.Show("ファイル情報にしますか（はい）、またはイメージ情報にしますか（いいえ）？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
					if(dr == DialogResult.Yes)
						propGrid.SelectedObject = new FileInfo(files[0]);
					else
						propGrid.SelectedObject = new ImageInfo(files[0]);
				}
				else
					propGrid.SelectedObject = new FileInfo(files[0]);
			}
		}
	}

	//イメージ情報取得クラス
	[DefaultProperty("Path")]
	public class ImageInfo
	{
		private Image image;
		private string path;

		[Description("イメージファイルのパスです。")]
		public string Path {get{return path;}}
		[Description("イメージファイルのサイズです。")]
		public Size Size {get{return image.Size;}}
		[Description("イメージファイルのピクセルフォーマットです。")]
		public PixelFormat PixelFormat{get{return image.PixelFormat;}}
		[Description("イメージファイルの画像フォーマットです。")]
		public ImageFormat Format{get{return image.RawFormat;}}

		public ImageInfo(string filePath)
		{
			path = filePath;
			image = Image.FromFile(filePath);
		}
	}

	//ウィンドウ情報取得クラス
	[DefaultProperty("wTitle")]
	public class WindowInfo
	{
		//メンバープロパティ
		[Description("ウィンドウタイトルです。")]
		public string wTitle {get; set;}
		[Description("プロセス名です。")]
		public string wProc {get; set;}
		[Description("ウィンドウハンドルの値です。")]
		public ulong wHnd {get; set;}
		[Description("ウィンドウの幅です。")]
		public int wWidth {get; set;}
		[Description("ウィンドウの高さです。")]
		public int wHeight {get; set;}
		[Description("ウィンドウプログラムのファイルパスです。")]
		public string wPath {get; set;}
	}

	//ウィンドウ選択ダイアログ
	public partial class WinSelect : Form
	{
		//RECT構造体を定義
		[StructLayout(LayoutKind.Sequential)]
		public struct RECT
		{
			public int Left;
			public int Top;
			public int Right;
			public int Bottom;
		}
		//GetWindowRect関数を宣言
		[DllImport("user32.dll")]
		[return: MarshalAs(UnmanagedType.Bool)]
		static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

		//メンバーコントロール
		ListView listView;
		Button btnOK, btnCancel;
		//メンバーフィールド
		WindowInfo wi;

		//コンストラクター
		public WinSelect(ref WindowInfo WinInfo)
		{
			wi = WinInfo;
			//this.AutoSize = true;	//trueにすると縮まらなくなる
			this.FormBorderStyle = FormBorderStyle.Sizable;	//FormBorderStyle.Fixed3D;
			this.MinimizeBox = false;
			this.MaximizeBox = false;
			this.Width = 420;
			this.Height = 240;
			this.Text = "Select Windows";
			this.Load += WinSelect_Load;
		}
 
	 	//WM_CLOSE時処理
		protected override void OnFormClosing(FormClosingEventArgs e)
		{
			base.OnFormClosing(e);
			string msg;
			if(listView.SelectedItems.Count > 0)
				msg = "\"" + listView.SelectedItems[0].Text + "\"が選択されました。\r\n";
			else
				msg = "何も選択されていませんが、";
			DialogResult dr = MessageBox.Show(msg + "宜しいですか？", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
			if(dr == DialogResult.No)
			{
				listView.SelectedItems.Clear();
				e.Cancel = true;
			}
		}

		//WM_CREATE時処理
		private void WinSelect_Load(object sender, EventArgs e)
		{
			//OKボタン
			btnOK = new Button();
			btnOK.Location = new Point(ClientSize.Width - btnOK.Width - 10, ClientSize.Height - btnOK.Height - 10);
			btnOK.Text = "OK";
			btnOK.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
			btnOK.Click += btnOK_Click;
			this.Controls.Add(btnOK);

			//Cancelボタン
			btnCancel = new Button();
			btnCancel.Location = new Point(10, ClientSize.Height - btnCancel.Height - 10);
			btnCancel.Text = "Cancel";
			btnCancel.Anchor = (AnchorStyles.Bottom | AnchorStyles.Left);
			btnCancel.Click += btnCancel_Click;
			this.Controls.Add(btnCancel);

			//リストビュー
			listView = new ListView();
			//位置
			listView.Location = new Point(10, 10);
			listView.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
			//サイズ
			listView.Width = ClientSize.Width - 20;
			listView.Height = ClientSize.Height - btnOK.Height - 30;
			//複数選択
			listView.MultiSelect = false;
			//一行選択
			listView.FullRowSelect = true;
			//グリッドラインの表示
			listView.GridLines = true;
			//並び替え表示
			listView.Sorting = SortOrder.Ascending;
			//ポイントで選択できるようにする
			listView.HoverSelection = false;
			//シングルクリック選択
			listView.Activation = ItemActivation.OneClick;
			//チェックボックス有効化
			listView.CheckBoxes = false;
			//リストビューの表示方法
			listView.View = View.Details;
			//ヘッダー定義
			ColumnHeader columnTitle = new ColumnHeader{Text = "タイトル", Width = 140};
			ColumnHeader columnProc = new ColumnHeader{Text = "プロセス", Width = 140};
			ColumnHeader columnHdl = new ColumnHeader{Text = "ハンドル", Width = 100};
			ColumnHeader columnWid = new ColumnHeader{Text = "幅", Width = 50};
			ColumnHeader columnHgt = new ColumnHeader{Text = "高さ", Width = 50};
			ColumnHeader columnPath = new ColumnHeader{Text = "ファイルパス", Width = 240};
			ColumnHeader[] colHeaderRegValue = {				//ヘッダー設定
				columnTitle,
				columnProc,
				columnHdl,
				columnWid,
				columnHgt,
				columnPath
			};
			listView.Columns.AddRange(colHeaderRegValue);		//ヘッダー追加
			//データ設定
			foreach (Process proc in Process.GetProcesses())	//全てのプロセスを列挙する
			{
				//メインウィンドウのタイトルがある時だけ列挙する
				if(proc.MainWindowTitle.Length > 0)
				{
					ListViewItem item = listView.Items.Add(proc.MainWindowTitle);
					item.SubItems.Add(proc.ProcessName);
					item.SubItems.Add(proc.MainWindowHandle.ToString());
					RECT rec;
					GetWindowRect(proc.MainWindowHandle, out rec);
					int w = rec.Right - rec.Left;
					int h = rec.Bottom - rec.Top;
					item.SubItems.Add(w.ToString());
					item.SubItems.Add(h.ToString());
					item.SubItems.Add(proc.MainModule.FileName);
				}
			}
			//FormにListViewを追加
			this.Controls.Add(listView);
		}

		private void btnOK_Click(object sender, EventArgs e)
		{
			if(listView.SelectedItems.Count == 0)
			{
				MessageBox.Show("リスト項目が未選択です。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				return;
			}
			wi.wTitle = listView.SelectedItems[0].SubItems[0].Text;
			wi.wProc = listView.SelectedItems[0].SubItems[1].Text;
			ulong val;
			if(!ulong.TryParse(listView.SelectedItems[0].SubItems[2].Text, out val))
			{
				MessageBox.Show("ハンドルの値が不正です。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				wi.wHnd = 0;
			}
			else
				wi.wHnd = val;
			int len;
			if(!int.TryParse(listView.SelectedItems[0].SubItems[3].Text, out len))
			{
				MessageBox.Show("幅の値が不正です。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				wi.wWidth = 0;
			}
			wi.wWidth = len;
			if(!int.TryParse(listView.SelectedItems[0].SubItems[4].Text, out len))
			{
				MessageBox.Show("高さの値が不正です。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);
				wi.wHeight = 0;
			}
			wi.wHeight = len;
			wi.wPath = listView.SelectedItems[0].SubItems[5].Text;
			Close();
		}

		private void btnCancel_Click(object sender, EventArgs e)
		{
			listView.SelectedItems.Clear();
			wi.wTitle = "";
			wi.wProc = "";
			wi.wHnd = 0;
			wi.wWidth = 0;
			wi.wHeight = 0;
			wi.wPath = "";
			Close();
		}
	}
}
