お手製アドレス帳のCSVインポート機能のコードを書いていたのですが、
if(hoge.Text.Contains(“ZONU”)){
hoge.Text = hoge.Text.Replace(“ZONU”, “DQN”);
huga.Test = hoge.Text;
}
みたいなコードを書いて3行目のコードは動いて、2行目では置換されないってどういうことですか…?二日三日悩んでどうにもならなくてどうでも良くなりました。
Vectorでも漁ってればそのうち良いアドレス帳が見付かるでしょう。
お手製アドレス帳のCSVインポート機能のコードを書いていたのですが、
if(hoge.Text.Contains(“ZONU”)){
hoge.Text = hoge.Text.Replace(“ZONU”, “DQN”);
huga.Test = hoge.Text;
}
みたいなコードを書いて3行目のコードは動いて、2行目では置換されないってどういうことですか…?二日三日悩んでどうにもならなくてどうでも良くなりました。
Vectorでも漁ってればそのうち良いアドレス帳が見付かるでしょう。
どう書く?orgのお題、文字列の八方向検索投稿用に書きました。
using System.Collections.Generic;
using System.Text;
using Microsoft.VisualBasic;
namespace どう書く_org文字列の八方向検索 {
class Program {
static string search;
static List<string> list;
static void Main(string[] args) {
string sample =
@"リオウウリウ
ウオリウオリ
オリリオリウ
リリオオウオ";
search = "ウオリ";
char sp = new char { '\n' };
int width = sample.Split(sp)[0].Length;
int height = sample.Split(sp).Length;
list = new List<string>(sample.Split(sp));
for(int y = 0; y < list.Count; y++) {
for(int x = 0; x < list[y].Length; x++) {
if(list[y][x] == search[0]) {
if(E(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "右");
}
if(W(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "左");
}
if(S(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "下");
}
if(N(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "上");
}
if(NE(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "右上");
}
if(SE(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "右下");
}
if(NW(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "左上");
}
if(SW(x, y) == search) {
Console.WriteLine("(" + x + "," + y + ")" + "," + "左下");
}
}
}
}
Console.ReadLine();
}
static string E(int x, int y) {
try {
return list[y].Substring(x, search.Length);
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string W(int x, int y) {
try {
return Strings.StrReverse(E(x - search.Length + 1, y));
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string S(int x, int y) {
try {
StringBuilder strb = new StringBuilder();
for(int i = 0; i < search.Length; i++) {
strb.Append(list[y + i][x]);
}
return strb.ToString();
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string N(int x, int y) {
try {
return Strings.StrReverse(S(x, y - search.Length + 1));
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string SE(int x, int y) {
try {
StringBuilder strb = new StringBuilder();
for(int i = 0; i < search.Length; i++) {
strb.Append(list[y + i][x + i]);
}
return strb.ToString();
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string NW(int x, int y) {
try {
return Strings.StrReverse(SE(x - search.Length + 1, y - search.Length + 1));
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string NE(int x, int y) {
try {
StringBuilder strb = new StringBuilder();
for(int i = 0; i < search.Length; i++) {
strb.Append(list[y - i][x + i]);
}
return strb.ToString();
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
static string SW(int x, int y) {
try {
return Strings.StrReverse(NE(x - search.Length + 1, y + search.Length - 1));
} catch(ArgumentOutOfRangeException) { return ""; }
catch(IndexOutOfRangeException) { return ""; }
}
}
}
多言語度を上げる為にVB.NETに書き換えました。ついでに一番乗りです。
'http://ja.doukaku.org/ 'http://ja.doukaku.org/102/投稿用 Imports System Imports System.Windows.Forms NameSpace どう書く_orgフォルダパス一覧のツリー構造への変換 Class Program <STAThread> _ Shared Sub Main(byval args() As String) Application.Run(new Form1()) End Sub End Class class Form1:Inherits Form 'treeView1 Dim treeView1 As TreeView = New TreeView() '起動時引数でパス一覧のファイルを指定 Dim pathListFilePath As String = System.Environment.GetCommandLineArgs()(1) Public Sub New() 'treeView1 treeView1.Parent = Me treeView1.Dock = DockStyle.Fill End Sub Private Sub Form1_Load(byval sender As object, byval e As EventArgs)handles Me.Load 'ROOTNode Dim rootNode As TreeNode = New TreeNode("ROOT") treeView1.Nodes.Add(rootNode) For Each fullPath As String In System.IO.File.ReadAllLines(pathListFilePath) Dim addNode As TreeNode = rootNode For Each path As String In fullPath.Split(New char(){"\"c}) Dim flag As Boolean = True For Each node As TreeNode in addNode.Nodes If node.Text = path Then addNode = node flag = False End If Next if flag Then Dim newnode As TreeNode = New TreeNode(path) addNode.Nodes.Add(newnode) addNode = newnode End If Next Next rootNode.ExpandAll() End Sub End Class End NameSpace
どう書く?orgのトピックフォルダパス一覧のツリー構造への変換への投稿用に書きました。
//http://ja.doukaku.org/ //http://ja.doukaku.org/102/投稿用 using System; using System.Windows.Forms; namespace どう書く_orgフォルダパス一覧のツリー構造への変換 { class Program { [STAThread] static void Main(string[] args) { Application.Run(new Form1()); } } class Form1:Form { //treeView1 TreeView treeView1 = new TreeView(); //起動時引数でパス一覧のファイルを指定 string pathListFilePath = System.Environment.GetCommandLineArgs()[1]; public Form1() { //Form1 this.Load += new EventHandler(Form1_Load); //treeView1 treeView1.Parent = this; treeView1.Dock = DockStyle.Fill; } void Form1_Load(object sender, EventArgs e) { //ROOTNode TreeNode rootNode = new TreeNode("ROOT"); treeView1.Nodes.Add(rootNode); foreach(string fullPath in System.IO.File.ReadAllLines(pathListFilePath)) { TreeNode addNode = rootNode; foreach(string path in fullPath.Split(new char[] { '\\' })) { bool flag = true; foreach(TreeNode node in addNode.Nodes) { if(node.Text == path) { addNode = node; flag = false; } } if(flag) { TreeNode newnode = new TreeNode(path); addNode.Nodes.Add(newnode); addNode = newnode; } } } rootNode.ExpandAll(); } } }
C#|TabControlでクリックされたタブが判らないのコードを手直ししました。デザイナー上でタブを切り替えると怒られるというどうしようもない失敗です。原因が良くわからなかったのでtry-catchで無理やり直しました。(こんなんでいいのか?)
ついでにClickイベントだけじゃ物足りないと思ったのでコピペ&力技でイベントを増設しました。偉い人はもっとスマートに書けるのでしょうか?
そして本題です。ついでにタブのD&Dに対応しちゃえ!って思ったのです。それ自体は簡単に出来ました。しかし、そこから苦労しました。と言うのも、タブが切り替わるタイミングがボタンを押して離した時ではなくて、ボタンを押し下げた瞬間なんです。つまり、ドラッグするとそのタブが選択されてしまうのです。そしてそのままドロップすると、移動したタブではなくて一番左のタブが選択されているのです。
僕が望んだ仕様は、選択されていないタブを選択しないまま並び替えられるというものです。せめてドラッグしたときはそのタブが選択されても、ドロップが終わったときには元のタブに戻るようにしようと思いました。そこで選択されたタブの履歴を取って、そこから戻すようにしてみました。でも、選択されているタブをD&Dしたら全く関係ないタブが選択されています。
色々試しましたが、制御仕切れなかったので諦めました。D&Dしたタブを選択するようにしました。
ちょっと長いけど晒します。どなたか添削してくれると嬉すぃです…。
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Anis.Controls {
/// <summary>TabMouseClickイベントを処理するメソッドを表します。</summary>
public delegate void TabMouseEventHandler(object sender, TabMouseEventArgs e);
/// <summary>タブ部分がクリックされた際に、
/// クリックされたタブを取得出来るTabMouseClickイベントを備えたTabControl</summary>
public class AnisTabControl: TabControl {
#region//各種TabMouseEvent定義
/// <summary>クリックされたタブが取得可能なMouseDownイベント</summary>
[Category("アクション"),
Description("マウスでタブをクリックした時に発生します。")]
public event TabMouseEventHandler TabMouseDown;
/// <summary>クリックされたタブが取得可能なMouseClickイベント</summary>
[Category("アクション"),
Description("マウスでタブをクリックした時に発生します。")]
public event TabMouseEventHandler TabMouseClick;
/// <summary>クリックされたタブが取得可能なMouseUpイベント</summary>
[Category("アクション"),
Description("マウスでタブをクリックした時に発生します。")]
public event TabMouseEventHandler TabMouseUp;
/// <summary>クリックされたタブが取得可能なMouseDoubleClickイベント</summary>
[Category("アクション"),
Description("マウスでタブをダブルクリックした時に発生します。")]
public event TabMouseEventHandler TabMouseDoubleClick;
/// <summary>クリックされたタブが取得可能なMouseWheelイベント</summary>
[Category("アクション"),
Description("マウスホイールがタブ上で動かされた時に発生します。")]
public event TabMouseEventHandler TabMouseWheel;
/// <summary>クリックされたタブが取得可能なMouseMoveイベント</summary>
[Category("アクション"),
Description("マウスポインタがコントロール上を移動すると発生します。")]
public event TabMouseEventHandler TabMouseMove;
#endregion
/// <summary>XMLコメントが無いって警告うざい</summary>
public AnisTabControl() {
#region//TabMouseEvent関連イベント登録
this.MouseDown += new MouseEventHandler(AnisTabControl_MouseDown);
this.MouseClick += new MouseEventHandler(AnisTabControl_MouseClick);
this.MouseUp += new MouseEventHandler(AnisTabControl_MouseUp);
this.MouseDoubleClick += new MouseEventHandler(AnisTabControl_MouseDoubleClick);
this.MouseWheel += new MouseEventHandler(AnisTabControl_MouseWheel);
this.MouseMove += new MouseEventHandler(AnisTabControl_MouseMove);
#endregion
}
/// <summary>Point上のタブコントロールの
///タブ部分に対応したTabPageのインデックスを取得</summary>
/// <param name="point">インデックスを取得するPoint</param>
/// <returns>Point上にタブが無ければ-1が返ります。。</returns>
private int TabIndexFromPoint(Point point) {
for(int i = 0; i <= this.TabPages.Count - 1; i++) {
if(this.GetTabRect(i).Contains(point)) {
return i;
}
}
return -1;
}
#region//Tabマウスイベント
void AnisTabControl_MouseDown(object sender, MouseEventArgs e) {
try {
int index = TabIndexFromPoint(e.Location);
if(index != -1) {
TabMouseEventArgs E = new TabMouseEventArgs(
index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
this.TabMouseDown(sender, E);
}
} catch(NullReferenceException) {}
}
void AnisTabControl_MouseClick(object sender, MouseEventArgs e) {
try {
int index = TabIndexFromPoint(e.Location);
if(index != -1) {
TabMouseEventArgs E = new TabMouseEventArgs(
index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
this.TabMouseClick(sender, E);
}
} catch(NullReferenceException) {}
}
void AnisTabControl_MouseUp(object sender, MouseEventArgs e) {
try {
int index = TabIndexFromPoint(e.Location);
if(index != -1) {
TabMouseEventArgs E = new TabMouseEventArgs(
index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
this.TabMouseUp(sender, E);
}
} catch(NullReferenceException) {}
}
void AnisTabControl_MouseDoubleClick(object sender, MouseEventArgs e) {
try {
int index = TabIndexFromPoint(e.Location);
if(index != -1) {
TabMouseEventArgs E = new TabMouseEventArgs(
index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
this.TabMouseDoubleClick(sender, E);
}
} catch(NullReferenceException) {}
}
void AnisTabControl_MouseWheel(object sender, MouseEventArgs e) {
try {
int index = TabIndexFromPoint(e.Location);
if(index != -1) {
TabMouseEventArgs E = new TabMouseEventArgs(
index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
this.TabMouseWheel(sender, E);
}
} catch(NullReferenceException) {}
}
void AnisTabControl_MouseMove(object sender, MouseEventArgs e) {
try {
int index = TabIndexFromPoint(e.Location);
if(index != -1) {
TabMouseEventArgs E = new TabMouseEventArgs(
index, e.Button, e.Clicks, e.X, e.Y, e.Delta);
this.TabMouseMove(sender, E);
}
} catch(NullReferenceException) {}
}
#endregion
#region//ドラッグ&ドロップ
Point mouseDownPoint = Point.Empty;
bool sortTabDragDrop;
/// <summary>trueでドラッグ&ドロップによるタブの
///並び替えを可能にします。</summary>
[Category("動作"),
Description("trueでドラッグ&ドロップによるタブの並び替えを可能にします。")]
public bool SortTabDragDrop {
set {
sortTabDragDrop = value;
if(value) {
this.MouseDown += new MouseEventHandler(AnisTabControl_MouseDown1);
this.MouseUp += new MouseEventHandler(AnisTabControl_MouseUp1);
this.TabMouseMove += new TabMouseEventHandler(AnisTabControl_TabMouseMove);
this.DragEnter += new DragEventHandler(AnisTabControl_DragEnter);
this.DragOver += new DragEventHandler(AnisTabControl_DragOver);
this.DragDrop += new DragEventHandler(AnisTabControl_DragDrop);
} else {
this.MouseDown -= new MouseEventHandler(AnisTabControl_MouseDown1);
this.MouseUp -= new MouseEventHandler(AnisTabControl_MouseUp1);
this.TabMouseMove -= new TabMouseEventHandler(AnisTabControl_TabMouseMove);
this.DragEnter -= new DragEventHandler(AnisTabControl_DragEnter);
this.DragOver -= new DragEventHandler(AnisTabControl_DragOver);
this.DragDrop -= new DragEventHandler(AnisTabControl_DragDrop);
}
}
get {
return sortTabDragDrop;
}
}
void AnisTabControl_MouseDown1(object sender, MouseEventArgs e) {
if(e.Button == MouseButtons.Left) {
mouseDownPoint = e.Location;
} else {
mouseDownPoint = Point.Empty;
}
}
void AnisTabControl_MouseUp1(object sender, MouseEventArgs e) {
mouseDownPoint = Point.Empty;
}
void AnisTabControl_TabMouseMove(object sender, TabMouseEventArgs e) {
if(mouseDownPoint != Point.Empty) {
Rectangle mouseMoveRectangle = new Rectangle(
mouseDownPoint.X - 5, mouseDownPoint.Y - 5,
10, 10);
if(!mouseMoveRectangle.Contains(e.Location)){
this.DoDragDrop(this.TabPages[e.TabIndex], DragDropEffects.Move);
}
}
}
void AnisTabControl_DragOver(object sender, DragEventArgs e) {
mouseDownPoint = Point.Empty;
}
void AnisTabControl_DragEnter(object sender, DragEventArgs e) {
if(e.Data.GetDataPresent(typeof(TabPage)) &&
this.TabPages.Contains((TabPage)(e.Data.GetData(typeof(TabPage)))) &&
this.TabIndexFromPoint(this.PointToClient(new Point(e.X,e.Y))) != -1){
e.Effect = DragDropEffects.Move;
} else {
e.Effect = DragDropEffects.None;
}
}
void AnisTabControl_DragDrop(object sender, DragEventArgs e) {
int index = TabIndexFromPoint(this.PointToClient(new Point(e.X,e.Y)));
TabPage tabPage = (TabPage)(e.Data.GetData(typeof(TabPage)));
this.TabPages.Remove(tabPage);
this.TabPages.Insert(index, tabPage);
this.SelectTab(index);
}
#endregion
}
/// <summary>TabMouseClickイベントのデータ</summary>
public class TabMouseEventArgs:MouseEventArgs {
private int tabIndex_;
/// <param name="tabIndex">クリックされたタブに対応したタブのインデックス</param>
public TabMouseEventArgs(
int tabIndex,MouseButtons button,int clicks, int x, int y ,int delta):base(
button,clicks,x,y,delta) {
tabIndex_ = tabIndex;
}
/// <summary>クリックされたタブに対応したタブページ</summary>
public int TabIndex {
get {
return tabIndex_;
}
}
}
}
TabControlのMouseClickイベントでどのタブがクリックされたかが判らないのがとても不満です。.NETは面白いけど、
「なんでこんなことも出来ないの?ていうか出来るようにしてくんないの?」
と思うことが時々あります。
てことで、TabMouseClickEventArgsとかでっち上げてクリックされたタブを取得出来るようにしてみました。その名もTabMouseClickイベントです。ネーミングセンス悪くてすみません。変数とかメソッドとかクラスとか、ネーミングに非常に悩みます。
using System.Windows.Forms;
using System.Drawing;
namespace Anis.Controls {
/// <summary>TabMouseClickイベントを処理するメソッドを表します。</summary>
public delegate void TabMouseClickEventHandler(object sender, TabMouseClickEventArgs e);
/// <summary>タブ部分がクリックされた際に、
/// クリックされたタブを取得出来るTabMouseClickイベントを備えたTabControl</summary>
public class AnisTabControl: TabControl {
/// <summary>クリックされたタブが取得可能なMouseClickイベント/// </summary>
public event TabMouseClickEventHandler TabMouseClick;
/// <summary>XMLコメントが無いって警告うざい</summary>
public AnisTabControl(){
this.MouseClick += new MouseEventHandler(Class1_MouseClick);
}
void Class1_MouseClick(object sender, MouseEventArgs e) {
for(int i = 0; i <= this.TabPages.Count - 1; i++) { //
if(this.GetTabRect(i).Contains(e.X,e.Y)){ //この2行がキモでし。
TabMouseClickEventArgs E = new TabMouseClickEventArgs(
this.TabPages[i],e.Button,e.Clicks,e.X,e.Y,e.Delta);
this.TabMouseClick(sender, E);
}
}
}
}
/// <summary>TabMouseClickイベントのデータ</summary>
public class TabMouseClickEventArgs:MouseEventArgs {
private TabPage tabpage_;
/// <param name="tabPage">クリックされたタブに対応したタブページ</param>
public TabMouseClickEventArgs(
TabPage tabPage,MouseButtons button,int clicks, int x, int y ,int delta):base(
button,clicks,x,y,delta) {
tabpage_ = tabPage;
}
/// <summary>クリックされたタブに対応したタブページ</summary>
public TabPage TabPage {
get {
return tabpage_;
}
}
}
}
アップしたらXMLコメントのタグが外れてスッキリしてます。まるでただのコメントのようです。
ファイルには拡張子があって、フォルダには拡張子が無いので
if(System.IO.Path.GetExtension(“hoge”) == “”) {
//フォルダだお
} else {
//ファイルだお
}
と言うのは間違い。”hoge.moge”がフォルダ名でも”.moge”が拡張子として認識されてしまいます。フォルダ名に”.”を使えるってのは盲点でした。
if(System.IO.Directory.Exists(“hoge”)) {
//フォルダだお
} else {
//ファイルだお
}
これで上手くいきました。
if(System.IO.File.Exists(“hoge”)) {
//フォルダだお
} else {
//ファイルだお
}
は”hoge”がフォルダでもtrueが返されるのでNGでした。
以上、失敗談でした。
もっとスマートで良い方法があったら教えて下さい。
NetBeensとVisualC++2005EEをアンインストールして空いたスペースにVisualC#2005EEをインストールしました。VC#をインストールして最初に書いたのは、フォルダの階層を表示出来るツリービューのDLLです。
aniscapeのお気に入りツリーをVB.NETで作ったときにちょっと大変だったので、C#で書いてDLLとして残しておこうと思いました。
再帰処理でフォルダ階層を奥まで読んでゴリゴリとノードを追加していけば簡単なのですが、そうすると全てのノードを追加し終わるまで暫く時間が掛かります。とても実用になりません。
それなら、ノードを開くときにその下だけ読めばもっと簡単だし、最初の待ち時間もありません。でも、それにも問題があります。ノードの頭についている+-のマークが表示されないので、フォルダの下にファイルやフォルダがあるかどうかが分かりません。
それではどうするのかと言うと、ノードを開く度に、2階層下まで読み込みます。
ファイルを表示するのですから、アイコンも表示させた方がいいと思います。
Icon icon = Icon.ExtractAssociatedIcon(“FileName”);
でそのファイルのアイコンを取得出来ます。これを
TreeView.ImageList.Images.Add(“FileName”, icon);
でイメージリストに追加して
TreeNode.ImageKey = “FileName”;
TreeNode.SelectedImageKey = “FileName”;
でノードにアイコンを設定します。
ここで問題発生です。この一連の処理がとても重いのです。ノードをクリックしてから開くまでに数秒から十数秒掛かります。使い物になりません。
そこでもう少し改造します。+-マークを表示させる為には2階層下まで読む必要がありますが、2階層下のノードについてはアイコンが無くても問題ありません。そこで、ノードは2階層下まで追加するが、アイコンは1階層下のみ追加する仕様にしました。
これで、軽快とはいきませんが、使えるレベルまでレスポンスが良くなりました。後はもっとレスポンスが必要な場合の為に、ファイルごとにアイコンを取得しないようにするプロパティでも実装しておけば幅広く使える様になるでしょう。
以上、メモでした。
ソースコード(C#, .NET2.0)
バイナリ
大量にノードを開いた時のレスポンスを改善しました。
バイナリ
ソースコード(C#, .NET2.0)
どう書く?orgのベータ版が公開されました。出されたお題にそったプログラムを色んな言語で投稿するサイトです。
早速いくつかのお題に挑戦してみたのですが、自分のスキルの無さを再認識しました。
面白いのでこれからも要チェックです。
チャリタイが売ってません。