フィロさんの「お気に入り」C#コードを改造
フィロさんのタブブラウザの「お気に入り」のC#コード
http://note.phyllo.net/?eid=540651
これを、少し改造してみました。
・右クリックしてからのお気に入り削除後、TreeNodeが折りたたまれるのを回避。
・新規フォルダ作成
・お気に入り登録(ブックマーク)
・TreeNoeクリック時、OnUrlOpenイベントを発行。(Webブラウザ側に通知)
久々に再帰関数を書いてみたらヘボくなった。。。(;´Д`A ```
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Drawing; using System.Text.RegularExpressions; using Microsoft.VisualBasic; using ABCS.Forms; namespace ABCS.Classes { //==クラス定義== //IEお気に入りツリークラス class MyBookmarkTree:TreeView { //==デリゲート定義== private delegate bool SetNodesDelegate(string vDirPath); //URLオープンデリゲート&イベント public delegate void OnURLOpenDelegate(string url); public event OnURLOpenDelegate OnUrlOpen = null; //ファイル・フォルダ変更してTreeを再構築後、Treeの最後に選択していたのノードを //選択するためのキーとなる最新のTag private string lastTag = ""; //ファイルウォッチイベントはスレッドが違うため、Invkeを使うが、 //そのInvokeで呼び出すメソッドとデリゲート public delegate void selectTargetNodeDelegate(); public void selectTargetNode() { TreeNode t = this.SelectNodeByTag(this.lastTag); if (t != null) { this.SelectedNode = t; t.Expand(); } } //--------------------------------------------- //==Private変数定義== //タブブラウザ //private MyTabBrowser prTabBrowser; //IEお気に入りフォルダパス private string prBookmarkDirPath; //右クリックメニュー private ContextMenuStrip prMenu; //ファイル変更監視 FileSystemWatcher prFileStytemWatcher; //---------------------------------------------- //コンストラクタ public MyBookmarkTree(/*MyTabBrowser rTabBrowser*/) { try { //this.frmmain_ = frmmain; //prTabBrowser = rTabBrowser; //---------------------------------- //IEお気に入りフォルダパスを取得 prBookmarkDirPath = Environment.GetFolderPath(Environment.SpecialFolder.Favorites); //---------------------------------- //IEお気に入りをツリーに設置 if (!SetNodes(prBookmarkDirPath)) { //エラー } //---------------------------------- //==右クリックメニュー== prMenu = new ContextMenuStrip(); ToolStripItem wItem; //メニュー項目「開く」を作成 wItem = prMenu.Items.Add("開く"); wItem.Click += new EventHandler(MenuOpen_Click); //メニュー項目「お気に入りから削除」を作成 wItem = prMenu.Items.Add("お気に入りから削除"); wItem.Click += new EventHandler(MenuDelete_Click); //メニュー項目「新規フォルダ」を作成 wItem = prMenu.Items.Add("新規フォルダ作成"); wItem.Click += new EventHandler(MenuNewDir_Click); //---------------------------------- //==フォルダの変更監視== prFileStytemWatcher = new FileSystemWatcher(prBookmarkDirPath); //監視対象のフォルダ prFileStytemWatcher.Path = prBookmarkDirPath; //サブフォルダまで監視 prFileStytemWatcher.IncludeSubdirectories = true; //全てを監視 prFileStytemWatcher.Filter = ""; //ディレクトリ名、ファイル名、最終更新時間、サイズの変更を監視 prFileStytemWatcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Size; //監視を開始 prFileStytemWatcher.EnableRaisingEvents = true; //---------------------------------- //==イベント設定== //ノードクリックイベント this.NodeMouseClick += new TreeNodeMouseClickEventHandler(BookmarkTree_NodeMouseClick); //------------------ //フォルダ内の作成イベント prFileStytemWatcher.Created += new FileSystemEventHandler(FileStytemWatcher_Created); //フォルダ内の変更イベント prFileStytemWatcher.Changed += new FileSystemEventHandler(FileStytemWatcher_Changed); //フォルダ内の削除イベント prFileStytemWatcher.Deleted += new FileSystemEventHandler(FileStytemWatcher_Deleted); //フォルダ内のリネームイベント prFileStytemWatcher.Renamed += new RenamedEventHandler(FileStytemWatcher_Renamed); } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //---------------------------------------------- //==Privateメソッド定義== //ツリーにノードを設置 private bool SetNodes(string vDirPath) { bool wRet = true; try { //ツリーのノードをクリアする this.Nodes.Clear(); //------------------------------------ //ルートノード作成 TreeNode wRootNode = new TreeNode("ルート"); //フォルダの階層 int wNodeLv = 0; //---------------------------------- //IEお気に入りをルートノードに配置 wNodeLv = SetChildNodes(wRootNode, vDirPath, wNodeLv); //ルートノードの子ノードをツリーに配置 foreach(TreeNode wNode in wRootNode.Nodes) { //ツリーにノードを配置 this.Nodes.Add(wNode); } this.SelectNode(wRootNode); } catch(Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = false; } return wRet; } //親ノードに子ノードを追加する private int SetChildNodes(TreeNode rNode, string vDirPath, int vNodeLv) { try { TreeNode wNode; //上位フォルダ内にフォルダノードを作成 foreach (string wDirPath in Directory.GetDirectories(vDirPath)) { //親ノードにフォルダノードを追加する wNode = rNode.Nodes.Add(getFileName(wDirPath)); //再起処理でフォルダノードの下位ノードを設置する vNodeLv = SetChildNodes(wNode, wDirPath, vNodeLv); //ノードにフォルダパスを格納 wNode.Tag = (string)wDirPath; } //親フォルダ内のファイルノードを作成 foreach (string wFilePath in Directory.GetFiles(vDirPath, "*.url")) { //上位ノードにファイルノードを追加する wNode = rNode.Nodes.Add(getFileName(wFilePath)); //ノードにURLファイルパスを格納 wNode.Tag = (string)wFilePath; } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); vNodeLv = -1; } return vNodeLv; } //新規ノードを作成 private TreeNode newTreeNode(string vPath) { TreeNode wTreeNode; try { //フォルダ名またはファイル名を取得 string wName = getFileName(vPath); //取得した名称でノードを作成 wTreeNode = new TreeNode(wName); } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wTreeNode = null; } //作成したノードを返す return wTreeNode; } //パスからフォルダ名・ファイル名を取得 private string getFileName(string vFilePath) { string wName; string[] wFileNameArray; try { char y = '\\'; //パスを\で区切り配列に格納 wFileNameArray = vFilePath.Split(y); //最下位のフォルダ名またはファイル名を取得 wName = wFileNameArray[wFileNameArray.Length - 1]; //ファイル名の.url拡張子をなくす wName = wName.Replace(".url", ""); } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); //エラーの場合は空白 wName = ""; } return wName; } //ノードに設定されたURLファイルの内容でWebページを開く private bool OpenPage(string vPath) { bool wRet = true; try { string wLine; string wUrl; //ファイルがある場合 if (File.Exists(vPath)) { //ファイルを開く StreamReader reader = new StreamReader(vPath, Encoding.Default); //1行ずつ読み込む while (!reader.EndOfStream) { wLine = reader.ReadLine(); //「URL=」を含む行を取得 if (wLine.IndexOf("URL=") == 0) { //「URL=」を除き、URLを取得する wUrl = wLine.Replace("URL=", ""); //タブブラウザにタブを追加 //prTabBrowser.AddNewTabPage(); //指定URLでWebページを開く //prTabBrowser.ActiveTabPage.WebBrowser.Navigate(wUrl); //Webページを開いたらループ終了 this.OnUrlOpen(wUrl); break; } } //ファイルを閉じる reader.Close(); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = false; } return wRet; } //引数Tagに一致するTreeNodeを検索する private TreeNode SelectNodeByTag(string tag) { foreach (TreeNode t in this.Nodes) { if (t.Tag.ToString() == tag) { return t; } TreeNode r = childNodeByTag(t, tag); if (r != null) { return r; } } return null; } //SelectNodeByTagから呼び出され、再帰検索する private TreeNode childNodeByTag(TreeNode pNode, string tag) { foreach (TreeNode t in pNode.Nodes) { if (t.Tag.ToString() == tag) { return t; } TreeNode r = childNodeByTag(t, tag); if (r != null) { return r; } } return null; } //ノードが選択された場合の処理 private bool SelectNode(TreeNode vNode) { bool wRet = true; try { //ノードからお気に入りのパスを取得 string wPath = (string)vNode.Tag; //----------------------------------- //ファイルの場合 if (File.Exists(wPath)) { //WEBページを開く if (!OpenPage(wPath)) { //エラー } } //フォルダの場合 else if (Directory.Exists(wPath)) { //ノードが展開している場合 if (vNode.IsExpanded) { //ノードの展開を閉じる vNode.Collapse(); } //ノードが見展開の場合 else { //ノードを展開する vNode.Expand(); } } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = false; } return wRet; } //フルパスからベースフォルダ名を取得する private string getBaseDir(string strgFullPath) { if (File.Exists(strgFullPath)) { Regex reg = new Regex("[\\\\][^\\\\]*$"); return reg.Replace(strgFullPath, ""); } else { return strgFullPath; } } //ノードに設定されたパスを削除する private bool FileDelete(string vPath) { bool wRet = true; try { string wMsg = "お気に入りから[ " + getFileName(vPath) + " ]を削除して宜しいですか?"; if (MessageBox.Show(wMsg, "確認メッセージ", MessageBoxButtons.OKCancel) == DialogResult.OK) { if (File.Exists(vPath)) { File.Delete(vPath); } else if (Directory.Exists(vPath)) { //フォルダ内にフォルダまたはファイルが存在しない場合は削除 if (Directory.GetFiles(vPath).Length == 0 && Directory.GetDirectories(vPath).Length == 0) { Directory.Delete(vPath); } else { MessageBox.Show("フォルダ内が空でない場合は、削除できません。"); } } } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = false; } return wRet; } //新規ノードを追加する private bool CreateNode(TreeNode vNode) { bool wRet = true; try { //ノードからお気に入りのパスを取得 string wPath = (string)vNode.Tag; //----------------------------------- //ファイルの場合 if (File.Exists(wPath)) { string basedir = this.getBaseDir(wPath); InputForm ipt = new InputForm("フォルダ名を入力してください。",""); ipt.ShowDialog(); string dirname = ipt.returnString; if (dirname == "") { return true; } //string dirname = Interaction.InputBox("フォルダ名を入力してください。", "", "", -1, -1); string fullpath = basedir + "\\" + dirname; Directory.CreateDirectory(fullpath); this.lastTag = fullpath; } //フォルダの場合 else if (Directory.Exists(wPath)) { string basedir = this.getBaseDir(wPath); InputForm ipt = new InputForm("フォルダ名を入力してください。", ""); ipt.ShowDialog(); string dirname = ipt.returnString; if (dirname == "") { return true; } //string dirname = Interaction.InputBox("フォルダ名を入力してください。", "", "", -1, -1); string fullpath = basedir + "\\" + dirname; Directory.CreateDirectory(fullpath); this.lastTag = fullpath; //ノードを展開する vNode.Expand(); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = false; } return wRet; } //urlをお気に入りにする public bool RegistURL(string url, string title) { TreeNode vNode = this.SelectedNode; bool wRet = true; try { //ノードからお気に入りのパスを取得 string wPath = (string)vNode.Tag; string fullpath = ""; //----------------------------------- //ファイルの場合 if (File.Exists(wPath)) { fullpath = this.getBaseDir(wPath); } //フォルダの場合 else if (Directory.Exists(wPath)) { fullpath = wPath; } System.IO.StreamWriter sw = null; try { //FileStream fm = File.Create(fullpath + "\\" + title + ".url"); sw = new System.IO.StreamWriter( fullpath + "\\" + title + ".url", false, System.Text.Encoding.UTF8); sw.Write("URL=" + url); } catch (Exception excp) { MessageBox.Show("エラーのため、お気に入りに登録できませんでした。"); } finally { if (sw != null) { sw.Close(); } } this.lastTag = fullpath; } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = false; } return wRet; } //---------------------------------------------- //==イベント定義== //ノードクリックイベント private void BookmarkTree_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e) { try { //左クリックの場合 if (e.Button == MouseButtons.Left) { TreeNode wNode = (TreeNode)e.Node; //----------------------------------- //ノードの選択処理 if (!SelectNode(wNode)) { //エラー } } //右クリックの場合 else if (e.Button == MouseButtons.Right) { //マウス位置にあるノードを取得 TreeNode wNode = this.GetNodeAt(e.X, e.Y); //取得したノードを選択状態にする this.SelectedNode = wNode; //----------------------------------- //右クリックメニューを表示 prMenu.Show(this, new Point(e.X, e.Y)); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //----------------------- //メニュー項目「開く」クリックイベント private void MenuOpen_Click(object sender, EventArgs e) { try { //選択状態のノードを取得 TreeNode wNode = this.SelectedNode; //----------------------------------- //ノードの選択処理 if (!SelectNode(wNode)) { //エラー } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //メニュー項目「削除」クリックイベント private void MenuDelete_Click(object sender, EventArgs e) { try { //選択状態のノードを取得 TreeNode wNode = this.SelectedNode; //ツリー再表示ため、Tagを保持 this.lastTag = wNode.Parent.Tag.ToString(); if (!FileDelete*1 { //エラー } //TreeNode選択 this.selectTargetNode(); } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //----------------------- //メニュー項目「新規フォルダ」クリックイベント private void MenuNewDir_Click(object sender, EventArgs e) { try { //選択状態のノードを取得 TreeNode wNode = this.SelectedNode; //ツリー再表示ため、Tagを保持 this.lastTag = wNode.Tag.ToString(); //ノードの選択処理 if (!CreateNode(wNode)) { //エラー } //TreeNode選択 this.selectTargetNode(); } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //----------------------- //フォルダ内の作成イベント private void FileStytemWatcher_Created(object sender, FileSystemEventArgs e) { try { if (!this.InvokeRequired) { //IEお気に入りをツリーに再設置 if (!SetNodes(prBookmarkDirPath)) { //エラー } //TreeNode選択 this.selectTargetNode(); } else { //IEお気に入りをツリーに再設置(監視クラスはスレッドが違う為、Invokeでツリーにスレッドを戻す) this.Invoke(new SetNodesDelegate(SetNodes), prBookmarkDirPath); //TreeNode選択 this.Invoke(new selectTargetNodeDelegate(this.selectTargetNode)); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //フォルダ内の変更イベント private void FileStytemWatcher_Changed(object sender, FileSystemEventArgs e) { try { TreeNode t = this.SelectNodeByTag(this.lastTag); if (!this.InvokeRequired) { //IEお気に入りをツリーに再設置 if (!SetNodes(prBookmarkDirPath)) { //エラー } //TreeNode選択 this.selectTargetNode(); } else { //IEお気に入りをツリーに再設置(監視クラスはスレッドが違う為、Invokeでツリーにスレッドを戻す) this.Invoke(new SetNodesDelegate(SetNodes), prBookmarkDirPath); //TreeNode選択 this.Invoke(new selectTargetNodeDelegate(this.selectTargetNode)); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //フォルダ内の削除イベント private void FileStytemWatcher_Deleted(object sender, FileSystemEventArgs e) { try { if (!this.InvokeRequired) { //IEお気に入りをツリーに再設置 if (!SetNodes(prBookmarkDirPath)) { //エラー } //TreeNode選択 this.selectTargetNode(); } else { //IEお気に入りをツリーに再設置(監視クラスはスレッドが違う為、Invokeでツリーにスレッドを戻す) this.Invoke(new SetNodesDelegate(SetNodes), prBookmarkDirPath); //TreeNode選択 this.Invoke(new selectTargetNodeDelegate(this.selectTargetNode)); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //フォルダ内のリネームイベント void FileStytemWatcher_Renamed(object sender, RenamedEventArgs e) { try { if (!this.InvokeRequired) { //IEお気に入りをツリーに再設置 if (!SetNodes(prBookmarkDirPath)) { //エラー } this.selectTargetNode(); } else { //IEお気に入りをツリーに再設置(監視クラスはスレッドが違う為、Invokeでツリーにスレッドを戻す) this.Invoke(new SetNodesDelegate(SetNodes), prBookmarkDirPath); this.Invoke(new selectTargetNodeDelegate(this.selectTargetNode)); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); } } //お気に入りフォルダ内のファイル名(お気に入り名)とURLから //keywordにマッチしたファイル名とURLを返す //(再帰処理用) private ListfindChildNode(string keyword, TreeNode childNode, out List urls) { urls = new List (); List bookmarks = new List (); foreach (TreeNode node in childNode.Nodes) { //ノードからお気に入りのパスを取得 string wPath = (string)node.Tag; //----------------------------------- //ファイルの場合 if (File.Exists(wPath)) { string url = OpenFile(wPath); if *2 >= 0) || (getFileName(wPath).ToLower().IndexOf(keyword.ToLower()) >= 0)) { urls.Add(url); bookmarks.Add(getFileName(wPath)); } } //サブノード検索 List sub_urls = null; List sub_bookmarks = findChildNode(keyword, node, out sub_urls); urls.AddRange(sub_urls); bookmarks.AddRange(sub_bookmarks); } return bookmarks; } //お気に入りフォルダ内のファイル名(お気に入り名)とURLから //keywordにマッチしたファイル名とURLを返す public List getBookmarks(string keyword, out List urls) { urls = new List (); List bookmarks = new List (); foreach (TreeNode node in this.Nodes) { //サブノード検索 List sub_urls = null; List sub_bookmarks = findChildNode(keyword, node, out sub_urls); urls.AddRange(sub_urls); bookmarks.AddRange(sub_bookmarks); } return bookmarks; } //ノードに設定されたURLファイル内のUrlをString型で返す private string OpenFile(string vPath) { string wRet = ""; try { string wLine; string wUrl; //ファイルがある場合 if (File.Exists(vPath)) { //ファイルを開く StreamReader reader = new StreamReader(vPath, Encoding.Default); //1行ずつ読み込む while (!reader.EndOfStream) { wLine = reader.ReadLine(); //「URL=」を含む行を取得 if (wLine.IndexOf("URL=") == 0) { //「URL=」を除き、URLを取得する wUrl = wLine.Replace("URL=", ""); //タブブラウザにタブを追加 //prTabBrowser.AddNewTabPage(); //指定URLでWebページを開く //prTabBrowser.ActiveTabPage.WebBrowser.Navigate(wUrl); //Webページを開いたらループ終了 return wUrl; break; } } //ファイルを閉じる reader.Close(); } } catch (Exception ex) { Console.WriteLine("例外エラー:" + ex.Message); wRet = ""; } return wRet; } } }