今回は全ソースの掲載とイベントハンドラ、メソッドの説明をしたいと思います。
特にドラッグ&ドロップの部分は他のプログラムで流用できるようにしましたので、是非ご活用下さい。
全体のソースコード
全体のソースコードは以下の通りです。
全体に軽く目をとおして頂いてから、詳細の解説をお読みいただければより分かりやすいと思います。
尚、Visual Studio 2019 のプロジェクトファイル一式は、下記からダウンロードできますので、入力が面倒という方はご利用ください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace LineFeedCodeChanger { public partial class MainFrom : Form { /// <summary> /// コンストラクタ /// </summary> public MainFrom() { InitializeComponent(); } /// <summary> /// フォームロード時の処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MainFrom_Load(object sender, EventArgs e) { //改行文字の配列 var linefeed = new string[] { "CR", "LF", "CRLF" }; //改行コード選択用コンボボックスに選択項目を登録 uxBeforeLineFeed.Items.AddRange(linefeed); uxAfterLineFeed.Items.AddRange(linefeed); //改行コード選択用コンボボックスに対して最初の項目を選択済みにしておく uxBeforeLineFeed.SelectedIndex = 0; uxAfterLineFeed.SelectedIndex = 0; //変換対象のTextBoxにドラッグ&ドロップ機能を付加する SetDragDrop(uxBeforeText); } /// <summary> /// 実行ボタンクリック時の処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void uxExecute_Click(object sender, EventArgs e) { //変換対象と変換結果の改行コードを取得し、制御コードに変換 var old_lf = ToControlChars(uxBeforeLineFeed.Text); var new_lf = ToControlChars(uxAfterLineFeed.Text); //改行コードを置換 uxAfterText.Text = uxBeforeText.Text.Replace(old_lf,new_lf); } /// <summary> /// 改行文字(CR,LF,CRLF)をエスケープシーケンスに変換 /// </summary> /// <param name="linefeed"></param> /// <returns></returns> private string ToControlChars(string linefeed) { //改行文字の内容に応じてエスケープシーケンスを返す switch (linefeed.ToUpper()) { case "CR": return "\r"; case "LF": return "\n"; case "CRLF": return Environment.NewLine; } //switchに該当しない場合は渡された値をそのまま返す return linefeed; } /// <summary> /// クリップボードへボタンクリック時の処理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void uxCopyClipboard_Click(object sender, EventArgs e) { //変換結果が空でなければクリップボードにコピーする if (uxAfterText.Text != "") { Clipboard.SetText(uxAfterText.Text); } } /// <summary> /// コントロールにドラッグ&ドロップの機能を付加する /// </summary> /// <param name="control"></param> private void SetDragDrop(Control control) { //ドラッグ&ドロップを受け付けられるようにする control.AllowDrop = true; //ドラッグが開始された時のイベント処理(マウスカーソルをドラッグ中のアイコンに変更) control.DragEnter += (s, e) => { //ファイルがドラッグされたとき、カーソルをドラッグ中のアイコンに変更し、そうでない場合は何もしない。 e.Effect = (e.Data.GetDataPresent(DataFormats.FileDrop)) ? DragDropEffects.Copy : e.Effect = DragDropEffects.None; }; //ドラッグ&ドロップが完了した時の処理(ファイル名を取得し、ファイルの中身をTextプロパティに代入) control.DragDrop += (s, e) => { //ドロップされたすべてのファイル名を取得する string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false); //ドロップされた先頭の1ファイルのみをTextプロパティに代入 control.Text = File.ReadAllText(fileName[0],Encoding.GetEncoding("shift-jis")); }; } } } |
先頭のusing 宣言
今回はファイルの読み込みが発生するため、先頭の10行目に using System.IO を手動で追加しています。
1 2 3 4 5 6 7 8 9 10 11 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; |
コンストラクタ
ファイル文字コード変換ツールと同様、今回もコンストラクタに特に何も記述していません。
自動生成された状態です。
1 2 3 4 |
public MainFrom() { InitializeComponent(); } |
Loadイベントハンドラ
ファイル文字コード変換ツールと同様、LoadイベントにComboBoxの選択項目の登録処理を記述しています。
また、TextBoxに対してドラッグ&ドロップの機能を追加する処理(SetDragDropの呼び出し)を追加しました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
private void MainFrom_Load(object sender, EventArgs e) { var linefeed = new string[] { "CR", "LF", "CRLF" }; //改行コード選択用コンボボックスに選択項目を登録 uxBeforeLineFeed.Items.AddRange(linefeed); uxAfterLineFeed.Items.AddRange(linefeed); //改行コード選択用コンボボックスに対して最初の項目を選択済みにしておく uxBeforeLineFeed.SelectedIndex = 0; uxAfterLineFeed.SelectedIndex = 0; //変換対象のTextBoxにドラッグ&ドロップ機能を付加する SetDragDrop(uxBeforeText); } |
実行ボタンクリックイベント
この処理は非常に簡単で、画面のComboBoxに選択されている改行コードを制御コードに変換し、Replaceメソッドにより文字列置換した結果を、変換結果表示用のuxAfterText.Text に代入しているだけです。
1 2 3 4 5 6 7 8 9 |
private void uxExecute_Click(object sender, EventArgs e) { //変換対象と変換結果の改行コードを取得し、制御コードに変換 var old_lf = ToControlChars(uxBeforeLineFeed.Text); var new_lf = ToControlChars(uxAfterLineFeed.Text); //改行コードを置換 uxAfterText.Text = uxBeforeText.Text.Replace(old_lf,new_lf); } |
エスケープシーケンス
改行コードを変換したい人は既にご存知のはずですが、知らない人の為に解説しておきます。
テキストデータに対して改行コードやタブコードなど、特別な意味を持つ文字がいくつか用意されており、これを制御コードとか制御文字と呼んでいます。
例えば、”ABCDEF”という文字列を表示する際、”AB”と”CDEF”の間で改行させたい場合、そこで改行してしまうとC#の構文では有り得ない記述になるため、ビルドエラーが発生してしまいます。
この時、”AB\nCDEF” と言う風に \(バックスラッシュ)+特定の文字を入れることで改行表示してくれます。
この 「バックスラッシュ+特定文字」のことをエスケープシーケンスと言い、次の様な種類が用意されています。
エスケープシーケンス | 意味 |
---|---|
\’ | シングルクォーテーション「’」 |
\” | ダブルクォーテーション「”」 |
\\ | バックスラッシュ「\」 |
\0 | null文字 |
\a | ベル(警告音) |
\b | バックスペース |
\f | フォームフィード |
\n | 改行(ラインフィード LF) |
\r | キャリッジリターン(CR) |
\t | 水平タブ |
\u | 16進表記のUnicode文字 |
\U | 16進表記のUnicode文字 |
\x | 16進表記のASCII文字 |
\v | 垂直タブ |
ちなみにこのバックスラッシュは、キーボードの¥マークのことなのですが、プログラムによって \と表示されたり ¥として表示されますが、同一のものです。
改行文字⇒エスケープシーケンス
ComboBoxから取得した改行文字列を、エスケープシーケンスに変換する処理が以下になります。
Windowsの改行コードはCRLFなので、”\r\n” と記述しても良いのですが、EnviromentクラスにNewLineプロパティがあって、OSに応じた改行コードを返してくれますので、こちらを使いました。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
private string ToControlChars(string linefeed) { //改行文字の内容に応じて制御コードを返す switch (linefeed.ToUpper()) { case "CR": return "\r"; case "LF": return "\n"; case "CRLF": return Environment.NewLine; } //switchに該当しない場合は渡された値をそのまま返す return linefeed; } |
クリップボードへコピー
クリップボードへコピーボタンがクリックされたら、変換結果のTexBox が空かどうか確認し、空でない場合のみクリップボードにコピーするようにしています。
1 2 3 4 5 6 7 8 |
private void uxCopyClipboard_Click(object sender, EventArgs e) { //変換結果が空でなければクリップボードにコピーする if (uxAfterText.Text != "") { Clipboard.SetText(uxAfterText.Text); } } |
ドラッグ&ドロップ追加処理
コントロールに対してドラッグ&ドロップを受け付けるには、次の手順が必要になります。
- ドラッグ&ドロップを受け付けるためにAllowDropにtrue を代入
- ドラッグ&ドロップが開始されるとDragEnterイベントが発生するので、ドラッグ&ドロップ用のマウスカーソルを設定
- ドラッグ&ドロップが完了したらDragDropイベントが発生するので、意図したデータがドラッグされたかを確認し、データを受け取る。
上記の事を念頭にソースコードを確認してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
private void SetDragDrop(Control control) { //ドラッグ&ドロップを受け付けられるようにする control.AllowDrop = true; //ドラッグが開始された時のイベント処理(マウスカーソルをドラッグ中のアイコンに変更) control.DragEnter += (s, e) => { //ファイルがドラッグされたとき、カーソルをドラッグ中のアイコンに変更し、そうでない場合は何もしない。 e.Effect = (e.Data.GetDataPresent(DataFormats.FileDrop)) ? DragDropEffects.Copy : e.Effect = DragDropEffects.None; }; //ドラッグ&ドロップが完了した時の処理(ファイル名を取得し、ファイルの中身をTextプロパティに代入) control.DragDrop += (s, e) => { //ドロップされたすべてのファイル名を取得する string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false); //ドロップされた先頭の1ファイルのみをTextプロパティに代入 control.Text = File.ReadAllText(fileName[0],Encoding.GetEncoding("shift-jis")); }; } |
ラムダ式によるイベントハンドラの記述
イベントハンドラを作るには、コントロールをダブルクリックするか、VisualStudioのプロパティから選択する方法が多いですが、ラムダ式を使って直接記述することも出来ます。
ラムダ式については こちら の記事中に軽く解説していますので、合わせてお読みください。
1 2 3 4 5 6 7 8 9 10 11 |
//従来の記述方法 void control_DragEnter(object sender,DragEventArgs e) { 処理; } //ラムダ式を使った記述方法 control.DragEnter += (s, e) => { 処理; }; |
この様に、わざわざイベントハンドラを生成しなくてもコードの中で定義することが可能です。
この方法の利点は、今回の様に関数化(メソッド化)して流用しやすい点です。
ドラッグ&ドロップされるファイルは複数
ドラッグ&ドロップされるとファイル名が受け取れるのですが、1つだけとは限りません。
そこで、文字列配列として受け取ることになります。
string[] fileName = (string[])e.Data.GetData(DataFormats.FileDrop, false);
しかし、今回は1つのファイルだけをドラッグ&ドロップしたいので、fileName[0] という風に最初に渡される名前だけを使って、ファイル読み込みを行い、Textプロパティに代入するようにしています。
control.Text = File.ReadAllText(fileName[0],Encoding.GetEncoding(“shift-jis”));
プログラムを配布するには
プログラムを他のPCへコピーして使う方法(配布方法)は、「CSV結合ツールを自作しよう!(最終回・プログラムの配布編)」の記事の中で、具体的な操作方法や注意点を解説しています。
フォルダ名やファイル名を読み替えて、必要なファイル3~4個をコピーして頂ければ他のWIndows10 PCで動かすことが出来ます。
まとめ
今回は改行コード変換ツールの全ソースコードの掲載と解説を行いました。
ドラッグ&ドロップ以外は非常に簡単だったのではないでしょうか。
ドラッグ&ドロップは少し複雑かもしれませんが、やっている事は単純です。
他のプログラムへの流用や改造もしやすいと思いますので、自分なりにより良い形に変更して使っていただければ幸いです。