開発環境 Microsoft Visual C# 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 Windows フォーム アプリケーション
プロジェクト名 Jien2ch

Jien2chプロジェクトにクラスを追加。
テンプレート:クラス
名前:ListViewEx

textBox1を削除。

コンテナー/SplitContainerをPanel2上にドロップ。
名前:splitContainer2
プロパティ FixedPanel:Panel1 Orientation:Horizontal

Jien2ch コンポーネント/ListViewExをsplitContainer2.Panel1上にドロップ。
名前:listViewEx1
プロパティ Dock:Fill

コモン コントロール/TextBoxをsplitContainer2.Panel2上にドロップ。
名前:textBox1
プロパティ Dock:Fill MultiLine:True ScrollBars:Vertical

treeView1にAfterSelectイベントハンドラを追加。

+Jien2ch
 +Form1.cs
  +Form1.Designer.cs
 +ListViewEx.cs
 +Program.cs
+Lib2ch
 +Data
  +Data.cs
 +IO
  +IO.cs
 +Model
  +BbsMenu.cs
  +Subject.cs

Form1.cs
using System.Collections.Generic;
using System.Windows.Forms;
using Lib2ch.Data;
using Lib2ch.Model;
 
namespace Jien2ch
{
	public partial class Form1 : Form
	{
		Subject _Subject = new Subject();
 
		public Form1()
		{
			InitializeComponent();
 
			#region 板一覧
			BbsMenu bbsMenu = new BbsMenu();
			List<BbsMenuItem> bbsMenuList = bbsMenu.GetMenuList();
 
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			foreach (BbsMenuItem item in bbsMenuList)
			{
				TreeNode childNode = new TreeNode();
				childNode.Text = item.BbsName;
				childNode.Tag = item;
				// 親ノード検索
				TreeNode[] node = treeView1.Nodes.Find(item.Category, false);
				if (node.Length == 0)
				{
					TreeNode parent = new TreeNode();
					parent.Name = item.Category;	// 検索用
					parent.Text = item.Category;	// 表示用
					parent.Nodes.Add(childNode);
					treeView1.Nodes.Add(parent);
				}
				else
				{
					node[0].Nodes.Add(childNode);
				}
				sb.Append(item.Category + item.BbsName + item.Url + "\r\n");
			}
			textBox1.Text = sb.ToString();
			#endregion
		}
 
		#region 板一覧アイテム選択時
		private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
		{
			if (e.Node.Tag != null)
			{
				ThreadListAdd((BbsMenuItem)e.Node.Tag);
			}
		}
 
		// スレッド一覧
		void ThreadListAdd(BbsMenuItem bbsMenuItem)
		{
			SubjectList subjectList = _Subject.Get(bbsMenuItem);
			listViewEx1.ItemSet(subjectList);
		}
		#endregion
	}
}
 

ListViewEx.cs
using System.Windows.Forms;
using Lib2ch.Data;
 
namespace Jien2ch
{
	class ListViewEx : ListView
	{
		public ListViewEx()
		{
			// プロパティ
			View = View.Details;
			FullRowSelect = true;
			GridLines = true;
 
			// 列ヘッダ
			Columns.Add("!", 20);	// 1列目は右寄せできないのでダミー
			Columns.Add("番号", 40, HorizontalAlignment.Right);
			Columns.Add("タイトル", 450);
			Columns.Add("レス", 40, HorizontalAlignment.Right);
		}
 
		public void ItemSet(SubjectList subjectList)
		{
			ListViewItem[] item = new ListViewItem[subjectList.List.Count];
			int num = 0;	// 番号
			foreach (SubjectData data in subjectList.List)
			{
				string[] line = new string[4];
				line[1] = (num + 1).ToString();
				line[2] = data.Title;
				line[3] = data.Count.ToString();
				item[num] = new ListViewItem(line);
				item[num].Tag = data;
				num++;
			}
			Items.AddRange(item);
			Tag = subjectList;
		}
	}
}
 

Data.cs
using System;
using System.Collections.Generic;
 
namespace Lib2ch.Data
{
	// ファイル結果
	class FileResult
	{
		public string[] Line;	// 行リスト
	}
 
	// 板一覧アイテム
	public class BbsMenuItem
	{
		public string Category;	// カテゴリ
		public string BbsName;	// 板名
		public string Url;	// URL
 
		public string Directory
		{
			get { return Category + "/" + BbsName + "/"; }
		}
	}
 
	// スレッドデータ
	public class SubjectData
	{
		string FileName;	// スレッドファイル名(.dat)
		public string Title;	// タイトル
		public int Count;	// レス数
 
		public SubjectData(string line)
		{
			if (line == "") return;
			FileName	= line.Substring(0, 14);
			int start	= line.LastIndexOf("(");
			int end		= line.LastIndexOf(")");
			Count = Convert.ToInt32(line.Substring(start + 1, end - (start + 1)));
			Title		= line.Substring(16, start - 16);
		}
	}
 
	// スレッド一覧
	public class SubjectList : BbsMenuItem
	{
		public List<SubjectData> List = new List<SubjectData>();
 
		public SubjectList(BbsMenuItem item)
		{
			Category= item.Category;
			BbsName	= item.BbsName;
			Url	= item.Url;
		}
 
		public void Parsing(string[] data)
		{
			foreach (string line in data)
			{
				SubjectData subjectData = new SubjectData(line);
				List.Add(subjectData);
			}
		}
	}
}
 

IO.cs
using System.IO;
using System.Net;
using System.Text;
using Lib2ch.Data;
 
namespace Lib2ch.IO
{
	class FileManager
	{
		public FileResult StandardCheck(string dir, string host, string file)
		{
			FileResult fileResult = LocalReader(dir + file);
			if (fileResult == null)
			{
				// サーバーからダウンロード
				Download(dir, host, file);
				fileResult = LocalReader(dir + file);
			}
			return fileResult;
		}
 
		FileResult LocalReader(string path)
		{
			try
			{
				FileResult fileResult = new FileResult();
				fileResult.Line = File.ReadAllLines(path, Encoding.Default);
				return fileResult;
			}
			catch
			{
				return null;
			}
		}
 
		bool Download(string dir, string host, string file)
		{
			if (!Directory.Exists(dir))
			{
				Directory.CreateDirectory(dir);
			}
			try
			{
				WebClient wc = new WebClient();
				wc.DownloadFile(host + file, dir + file);
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
}
 

BbsMenu.cs
using System.Collections.Generic;
using Lib2ch.Data;
using Lib2ch.IO;
 
namespace Lib2ch.Model
{
	public class BbsMenu
	{
		const string _CateStart = "<BR><BR><B>";
		const string _CateEnd = "</B>";
		const string _BbsStart = "<A HREF=";
		const string _UrlEnd1 = " TARGET=_blank>";
		const string _UrlEnd2 = ">";
		const string _BbsEnd = "</A>";
 
		FileManager _File = new FileManager();
 
		public List<BbsMenuItem> GetMenuList()
		{
			// ファイルの有無
			FileResult fileResult = _File.StandardCheck(
				"./Log/", "http://menu.2ch.net/", "bbsmenu.html");
			if (fileResult == null) return null;
 
			// 解析処理
			return BbsMenuParsing(fileResult.Line);
		}
 
		List<BbsMenuItem> BbsMenuParsing(string[] data)
		{
			List<BbsMenuItem> list = new List<BbsMenuItem>();
			string category = null;
			foreach (string line in data)
			{
				int index1 = line.IndexOf(_CateStart);
				if (index1 != -1)
				{
					int index2 = line.IndexOf(_CateEnd);
					if (index2 != -1)
					{
						int start = index1 + _CateStart.Length;
						category = line.Substring(start, index2 - start);
					}
				}
				if (category == null) continue;
				BbsMenuItem item = BbsMenuFindLine(line, _BbsStart, _UrlEnd1, _BbsEnd);
				if (item == null)
				{
					item = BbsMenuFindLine(line, _BbsStart, _UrlEnd2, _BbsEnd);
				}
				if (item != null)
				{
					item.Category = category;
					list.Add(item);
				}
			}
			return list;
		}
 
		BbsMenuItem BbsMenuFindLine(string line, string word1, string word2, string word3)
		{
			int index1 = line.IndexOf(word1);
			if (index1 == -1) return null;
			int start1 = index1 + word1.Length;
 
			int index2 = line.IndexOf(word2, start1);
			if (index2 == -1) return null;
			int start2 = index2 + word2.Length;
 
			int index3 = line.IndexOf(word3, start2);
			if (index3 == -1) return null;
 
			BbsMenuItem item = new BbsMenuItem();
			item.Url = line.Substring(start1, index2 - start1);
			item.BbsName = line.Substring(start2, index3 - start2);
			return item;
		}
	}
}
 

Subject.cs
using Lib2ch.Data;
using Lib2ch.IO;
 
namespace Lib2ch.Model
{
	public class Subject
	{
		FileManager _File = new FileManager();
 
		public SubjectList Get(BbsMenuItem bbsMenuItem)
		{
			FileResult fileResult = _File.StandardCheck(
				"./Log/" + bbsMenuItem.Directory, bbsMenuItem.Url, "subject.txt");
			if (fileResult == null) return null;
 
			SubjectList subjectList = new SubjectList(bbsMenuItem);
			subjectList.Parsing(fileResult.Line);
			return subjectList;
		}
	}
}
 
最終更新:2012年11月17日 21:14