開発環境 Microsoft Visual C# 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 空のプロジェクト
プロジェクト名 Jien2ch

listViewEx1を削除。

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

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

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

listViewEx1にSelectedIndexChangedイベントハンドラを追加。

Lib2ch.DataにDatクラスを追加。
Lib2ch.DataにDatResクラスを追加。
Lib2ch.ModelにThreadDatクラスを追加。

+Jien2ch		プロジェクト
  +Form1.cs		フォームクラス
   +Form1.Designer.cs	フォームデザイナー
  +ListViewEx.cs	リストビュークラス
  +Program.cs		プログラムクラス
 +Lib2ch		クラスライブラリ
  +Data			データ名前空間
   +Data.cs		データクラス
  +IO			IO名前空間
   +File.cs		ファイルクラス
   +FileManager.cs	ファイル管理クラス
  +Model		モデル名前空間
   +BbsMenu.cs		板一覧クラス
   +Subject.cs		スレッド一覧クラス
   +ThreadDat.cs	スレッドdatクラス
 


namespace Jien2ch


Program.cs
using System;
using System.Windows.Forms;
 
namespace Jien2ch
{
	class Program
	{
		[STAThread]	// Single-Threaded Apartment
		static void Main()
		{
			Application.Run(new Form1());
		}
	}
}
 

Form1.cs
using System;
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();
		ThreadDat _ThreadDat = new ThreadDat();
 
		public Form1()
		{
			InitializeComponent();
		}
 
		private void Form1_Load(object sender, EventArgs e)
		{
			#region 板一覧
			BbsMenu bbsMenu = new BbsMenu();
			List<BbsMenuItem> bbsMenuList = bbsMenu.GetMenuList();
			foreach (BbsMenuItem item in bbsMenuList)
			{
				TreeNode childNode = new TreeNode();
				//childNode.Name = item.Name;
				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 = parent.Name;	// 表示用
					parent.Nodes.Add(childNode);
					treeView1.Nodes.Add(parent);
				}
				else
				{
					node[0].Nodes.Add(childNode);
				}
			}
			#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
 
		#region スレッド一覧アイテム選択時
		private void listViewEx1_SelectedIndexChanged(object sender, EventArgs e)
		{
			ListViewEx listView = (ListViewEx)sender;
			if (listView.SelectedItems.Count == 0) return;
			SubjectData subjectData = (SubjectData)listView.SelectedItems[0].Tag;
//			textBox1.Text = subjectData.FileName + subjectData.Title;
			ThreadViewAdd(subjectData);
		}
 
		void ThreadViewAdd(SubjectData subjectData)
		{
			Dat dat = _ThreadDat.Get(subjectData);
//			webBrowserEx1.ItemSet();
 
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			int num = 0;	// 番号
			foreach (DatRes datRes in dat.Res)
			{
				num++;
				sb.Append(num + ":[" + datRes.Data + "]\r\n");
			}
			textBox1.Text = sb.ToString();
		}
		#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[0] = ;
				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;
		}
	}
}
 


namespace Lib2ch.Data


Data.cs
using System;
using System.Collections.Generic;
 
namespace Lib2ch.Data
{
	// 板一覧アイテム
	public class BbsMenuItem
	{
		public string Category;	// カテゴリ名
		public string BbsName;	// 板名
		public string Url;	// URL
 
		public string Directory
		{
			get
			{
				return "/" + Category + "/" + BbsName;
			}
		}
	}
 
	// ファイル結果
	class FileResult
	{
		public List<string> Line = new List<string>();	// 行リスト
	}
 
	// スレッドデータ
	public class SubjectData : BbsMenuItem
	{
		public 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 void Parsing(List<string> data)
		{
			foreach (string line in data)
			{
				SubjectData subjectData = new SubjectData(line);
				subjectData.Category = Category;
				subjectData.BbsName = BbsName;
				subjectData.Url = Url;
				List.Add(subjectData);
			}
		}
	}
 
	// スレッドデータ
	public class Dat : SubjectData
	{
		public List<DatRes> Res = new List<DatRes>();
 
		public Dat() : base("")
		{
		}
 
		public void Parsing(List<string> data)
		{
			if (data.Count > 1)
			{
				DatRes datRes = new DatRes();
				data[0] = datRes.Title(data[0]);
				datRes.Res(data[0]);
				Res.Add(datRes);
			}
			for (int n = 1; n < data.Count; n++)
			{
				DatRes datRes = new DatRes();
				datRes.Res(data[n]);
				Res.Add(datRes);
			}
		}
	}
 
	public class DatRes
	{
		public string Data;
 
		public void Res(string line)
		{
			Data = line;
		}
 
		public string Title(string line)
		{
			return line;
		}
	}
}
 


namespace Lib2ch.IO


File.cs
using System.IO;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Lib2ch.Data;
 
namespace Lib2ch.IO
{
	class File
	{
		Encoding _Type = Encoding.GetEncoding("Shift_JIS");
 
		protected FileResult LocalReader(string path)
		{
			try
			{
				FileResult fileResult = new FileResult();
				using (StreamReader sr = new StreamReader(path, _Type))
				{
					string line;
					while ((line = sr.ReadLine()) != null)
					{
						fileResult.Line.Add(line);
					}
				}
				return fileResult;
			}
			catch
			{
				return null;
			}
		}
 
		protected FileResult UrlReader(string url)
		{
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
			req.UserAgent = "Monazilla/1.00(Jien2ch/Lib2ch)";
			req.AddRange(0);
			req.KeepAlive = false;
			req.Headers.Add("Pragma", "no-cache");
			req.Headers.Add("Cache-Control", "no-cache");
			WebResponse res = null;
			FileResult fileResult = new FileResult();
			try
			{
				res = req.GetResponse();
			}
			catch (WebException)
			{
				return fileResult;
			}
			using (Stream stream = res.GetResponseStream())
			{
				using (StreamReader sr = new StreamReader(stream, _Type))
				{
					string line;
					while ((line = sr.ReadLine()) != null)
					{
						fileResult.Line.Add(line);
					}
				}
			}
			return fileResult;
		}
 
		protected bool LocalWriter(string dir, string file, List<string> writeData)
		{
			if (!Directory.Exists(dir))
			{
				Directory.CreateDirectory(dir);
			}
			try
			{
				using (StreamWriter sw = new StreamWriter(dir + file, false, _Type))
				{
					sw.NewLine = "\n";
					foreach (string line in writeData)
					{
						sw.WriteLine(line);
					}
				}
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
}
 

FileManager.cs
using Lib2ch.Data;
 
namespace Lib2ch.IO
{
	class FileManager : File
	{
		public FileResult StandardCheck(string path, string host, string fileName)
		{
			FileResult fileResult = new FileResult();
			fileResult = LocalReader(path + fileName);
			if (fileResult == null)
			{
				// サーバーからダウンロード
				fileResult = UrlReader(host + fileName);
				if (fileResult == null) return null;
				// ファイルの書き込み
				if (!LocalWriter(path, fileName, fileResult.Line))
				{
					return null;
				}
			}
			return fileResult;
		}
	}
}
 


namespace Lib2ch.Model


BbsMenu.cs
using System.Collections.Generic;
using Lib2ch.Data;
using Lib2ch.IO;
 
namespace Lib2ch.Model
{
	// 板一覧
	public class BbsMenu
	{
		string _Path = "./Log";
		string _FileName = "/bbsmenu.html";
		string _Host = "http://menu.2ch.net";
 
		string _CateStart = "<BR><BR><B>";
		string _CateEnd = "</B>";
		string _BbsStart = "<A HREF=";
		string _UrlEnd1 = "/>";
		string _UrlEnd2 = "/ TARGET=_blank>";
		string _BbsEnd = "</A>";
 
		FileManager _File = new FileManager();
 
		public List<BbsMenuItem> GetMenuList()
		{
			// ファイルの有無
			FileResult fileResult = _File.StandardCheck(_Path, _Host, _FileName);
			if (fileResult == null) return null;
			// 解析処理
			return BbsMenuParsing(fileResult.Line);
		}
 
		List<BbsMenuItem> BbsMenuParsing(List<string> data)
		{
			List<BbsMenuItem> list = new List<BbsMenuItem>();
			string parent = null;
			foreach (string line in data)
			{
				// カテゴリ
				// <BR><BR><B>(parent)</B>
				int index1 = line.IndexOf(_CateStart);
				if (index1 != -1)
				{
					int index2 = line.IndexOf(_CateEnd);
					if (index2 != -1)
					{
						int start = index1 + _CateStart.Length;
						parent = line.Substring(start, index2 - start);
					}
				}
				if (parent == null) continue;
 
				BbsMenuItem item = BbsMenuFindLine(line, _BbsStart, _UrlEnd1, _BbsEnd);
				if (item == null)
				{
					item = BbsMenuFindLine(line, _BbsStart, _UrlEnd2, _BbsEnd);
				}
				if (item != null)
				{
					item.Category = parent;
					list.Add(item);
				}
			}
			return list;
		}
 
		// 板のURLと名前を取得
		// <A HREF=(Url)/>(Name)</A>
		// <A HREF=(Url)/ TARGET=_blank>(Name)</A>
		BbsMenuItem BbsMenuFindLine(string line, string word1, string word2, string word3)
		{
			int index1 = line.IndexOf(word1);
			if (index1 == -1) return null;
			int index2 = line.IndexOf(word2);
			if (index2 == -1) return null;
			int index3 = line.IndexOf(word3);
			if (index3 == -1) return null;
 
			BbsMenuItem item = new BbsMenuItem();
			int start1 = index1 + word1.Length;
			int start2 = index2 + word2.Length;
			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)
		{
			SubjectList subjectList = new SubjectList();
			subjectList.BbsName = bbsMenuItem.BbsName;
			subjectList.Url = bbsMenuItem.Url;
			subjectList.Category = bbsMenuItem.Category;
			FileResult fileResult = _File.StandardCheck(
				"./Log" + subjectList.Directory, subjectList.Url, "/subject.txt");
			if (fileResult == null) return null;
			subjectList.Parsing(fileResult.Line);
			return subjectList;
		}
	}
}
 

ThreadDat.cs
using Lib2ch.Data;
using Lib2ch.IO;
 
namespace Lib2ch.Model
{
	public class ThreadDat
	{
		FileManager _File = new FileManager();
 
		public Dat Get(SubjectData subjectData)
		{
			Dat dat = new Dat();
			dat.Category	= subjectData.Category;
			dat.BbsName	= subjectData.BbsName;
			dat.Url		= subjectData.Url;
			dat.FileName	= "/" + subjectData.FileName;
			dat.Title	= subjectData.Title;
			dat.Count	= subjectData.Count;
			FileResult fileResult = _File.StandardCheck(
				"./Log" + dat.Directory, dat.Url + "/dat/", dat.FileName);
			if (fileResult == null) return null;
			dat.Parsing(fileResult.Line);
			return dat;
		}
	}
}
 
最終更新:2012年11月13日 18:25