今回は改行コード変換ツールを開発してみましょう。
画面の左に張り付けたテキストの改行コードをReplaceメソッドで置き換えるといった単純な内容ですが、それだけでは物足りないので、画面を左右に分割する設定方法と、ファイルのドラッグ&ドロップに対応しました。
全ソースコードとプロジェクトのダウンロードURLも掲載していますので、WindowsFormでプログラムを作る際の参考にしていただければと思います。
仕様を理解しよう
まず最初に、これから作る「改行コード変換ツール」の仕様を理解しておきましょう。
画面レイアウト
今回作る改行コード変換ツールの画面レイアウトは次の様になります。

左に変換対象のテキストを張り付けて「変換実行」ボタンをクリックすると、指定された改行コードで置き換えるというものです。
プログラムの機能
改行コード変換ツールの機能は以下の通りです。
- テキストボックスを左右に配置し、左右の幅の比率をマウスで変更できる
- 左のテキストボックスに変換したいテキストを張り付け、変換した結果が右のテキストボックスに表示される
- 任意のテキストファイルをドラッグ&ドロップで左のテキストボックスに張り付けられる
- 改行コードは CR,LF,CRLFの3種類に対応する
- 右のテキストボックスに表示された変換結果はクリップボードにコピーできる

処理の流れ
それでは、フローチャートで処理手順を明確にしておきましょう。
画面から変換したい文字コードと変換後の文字コードを取得し、TextBoxコントロールのTextプロパティに対して、Replace メソッドを実行するだけです。

使用するコントロール
今回は、Label、Button、ComboBox、TextBox、SplitContainer の5種類のコントロールを使います。
SplitContainer とは、画面を左右、または上下に分割するためのコントロールです。
SplitContainerの上に様々なコントロールを乗せることが出来るので、コンテナとも呼ばれています。
SplitContainerはツールボックスからドラッグ&ドロップで画面に張り付けることが出来ますが、張り付け方が少し特殊なので、詳細は こちら にてご確認下さい。

開発に取り掛かろう
ここからは、Visual Studioを使って画面レイアウトの作成とプログラムの記述を行っていきます。
プロジェクトの作成
最初にVisual Studioからプロジェクトを作成します。今回は LineFeedChanger という名前で作ります。
Visual Studio を立ち上げて、プロジェクト名にLineFeedChangerと入力し、右下の「作成」ボタンをクリックしたら完成です。

プロジェクトの作り方が分からない方は 「Visual Studio 2019 の起動と終了手順」 の記事の冒頭に詳しく記載しています。Visual Studio 2022をお使いの方も基本的には同じ手順になります。
画面レイアウトの作成
プロジェクトが出来たら、コントロールを張り付けていきましょう。今回は画面を左右に分割するため、SplitContainerというコントロールを使用します。
下記の動画を参考に、コントロールを配置して下さい。

下記の様なレイアウトになります。

Form.csの名前変更
Formのファイル名が Form1.cs になっているので、MainForm.cs に変更したいと思います。別にFormのままでも良いという方は、この部分は読み飛ばして下さい。
Visual Studio の右側にあるソリューションエクスプローラーから「Form1.cs」を右クリックし、表示されるメニューから「名前の変更」を選び、MainFormに変更します。

コントロールの命名
次はコントロールに名前を付けていきましょう。
今回新しく登場した SplitContainer については、今回の仕様ではプログラムで制御する必要がないため、特に名前は付けません。

| コントロールの役割(Labelを除く) | コントロールに付ける名前 |
|---|---|
| プロジェクトが出来上がった際、最初に自動で作成されるWindow | MainForm |
| 変換対象入力用のTextBox | uxBeforeText |
| 変換対象の文字コード選択ComboBox | uxBeforeLineFeed |
| 変換結果表示用TextBox | uxAfterText |
| 変換結果の文字コード選択ComboBox | uxAfterLineFeed |
| 変換実行Button | uxExecute |
| クリップボードへButton | uxCopyClipboard |
今回もいくつかのコントロールについて、一部のプロパティに値を設定したいと思います。
| コントロール名 | プロパティ名 | 設定する値 |
|---|---|---|
| MainForm | Font Text | Meiryo UI,9pt 改行コード変換 |
| uxBeforeText | MaxLength Multiline Anchor ScrollBars | 0 true Top, Bottom, Left, Right Both |
| uxBeforeLineFeed | Anchor | Top, Right |
| uxAfterText | MaxLength Multiline Anchor ScrollBars | 0 true Top, Bottom, Left, Right Both |
| uxAfterLineFeed | Anchor | Top, Right |
| uxExecute | Anchor Text | Top, Right 変換実行 |
| uxCopyClipboard | Anchor Text | Top, Right クリップボードへ |
| ”改行コード”のLabel | Anchor | Top, Right |
| SplitContainer | Anchor | Top, Bottom, Left, Right |
今まで作ったプログラムでは、TextBoxは1行しか入力できませんでした。
しかし、いくつかのプロパティを設定することで複数行の入力が出来る様になります。
| プロパティ名 | 解説 |
|---|---|
| MaxLength | 入力可能な文字数の設定。初期値は32767文字。 0にすると文字数制限が無くなり、メモリが許す限り入力できるようになる。 |
| MultiLine | True にすることで複数行の入力が可能になる。初期値は False。 |
| ScrollBars | スクロールバーの表示/非表示設定。None,Horizontal,Vertical,Bothから選ぶ。 Bothは縦スクロールバーが常に表示され、必要に応じて横スクロールバーが表示される。 |
| WordWrap | 行を折り返して表示するか否かの設定。初期値はTrue。 Falseにすると折り返さなくなるため、ScrollBarsプロパティに応じてScrollBarsが表示される |
にちみに、今回の改行コード変換ツールにおいては、WordWrapを設定していません。
というか、設定し忘れていました。
必要ならWordWrapをtrue に設定して下さい。
イベントハンドラの作成
レイアウトが終わったら、イベントハンドラを作成します。
今回はLoadイベント、「変換実行」ボタンと「クリップボードへ」のClickイベントの合計3個のイベントハンドラを作成します。
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;
namespace LineFeedCodeChanger
{
public partial class MainFrom : Form
{
public MainFrom()
{
InitializeComponent();
}
private void MainFrom_Load(object sender, EventArgs e)
{
}
private void uxExecute_Click(object sender, EventArgs e)
{
}
private void uxCopyClipboard_Click(object sender, EventArgs e)
{
}
}
}
動作確認
ここまで出来たら、VisualStudioの上部にある「開始」ボタンによりプログラムを実行してみて下さい。

イベントハンドラを作成しよう
ここからは、イベントハンドラの中身を記述していきます。
Loadイベントの処理
ファイル文字コード変換ツールと同様、LoadイベントにComboBoxの選択項目の登録処理を記述しています。
また、TextBoxに対してドラッグ&ドロップの機能を追加する処理(SetDragDropの呼び出し)を追加しました。
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 に代入しているだけです。
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に応じた改行コードを返してくれますので、こちらを使いました。
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 が空かどうか確認し、空でない場合のみクリップボードにコピーするようにしています。
private void uxCopyClipboard_Click(object sender, EventArgs e)
{
//変換結果が空でなければクリップボードにコピーする
if (uxAfterText.Text != "")
{
Clipboard.SetText(uxAfterText.Text);
ドラッグ&ドロップへの対応
コントロールに対してドラッグ&ドロップを受け付けるには、次の手順が必要になります。
- ドラッグ&ドロップを受け付けるためにAllowDropにtrue を代入
- ドラッグ&ドロップが開始されるとDragEnterイベントが発生するので、ドラッグ&ドロップ用のマウスカーソルを設定
- ドラッグ&ドロップが完了したらDragDropイベントが発生するので、意図したデータがドラッグされたかを確認し、データを受け取る。
上記の事を念頭にソースコードを確認してください。
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のプロパティから選択する方法が多いですが、ラムダ式を使って直接記述することも出来ます。
ラムダ式については こちら の記事中に軽く解説していますので、合わせてお読みください。
//従来の記述方法
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で動作させる(=プログラムの配布)には、次の手順を行います。
フォルダ構成と配布対象
プロジェクトが置かれているフォルダは以下のフォルダ階層になっています。

DebugとReleaseフォルダがありますが、Visual Studioの初期状態では Debug フォルダにEXEファイルが置かれています。
ここに3つのファイルが出来上がっていますので、以下の2ファイルを実行したいPCに、適当なフォルダを作ってコピーして下さい。
- LineFeedCodeChanger.exe
- LineFeedCodeChanger.exe.config
LineFeedCodeChange.pdb はデバッグ情報が含まれているだけなので特にコピーする必要はありませんが、コピーしても結構です。
コピーした LineFeedCodeChange.exe をマウスでダブルクリックすれば、プログラムが起動します。
Frameworkの確認
Visual Studio 2019 がインストールされているPCでは、今回使用した .NET Framework 4.7.2 が自動的にインストールされています。
しかし、別のPCで実行するためには、別途 .NET Frameworkのインストールが必要となります。
.NET Framework はWindows10のWindowsUpdate と共にバージョンアップされていきますので、OSバージョンが1830以上でなければエラーになる可能性があります。
厳密には、新しいバージョンで登場した機能を使わないのであれば、少し古い.NET Frameworkのバージョンでも問題はありませんので、一度ダブルクリックで動かしてみて、エラーになったらOSバージョンを確認するという手順でも良いと思います。
.NET FrameworkのバージョンとOSバージョンの関係、確認方法、.NET Frameworkのインストール方法については、こちら の記事に記載しています。
全ソースコードとプロジェクトのダウンロード
全体のソースコードは以下の通りです。
全体に軽く目をとおして頂いてから、詳細の解説をお読みいただければより分かりやすいと思います。
尚、Visual Studio 2019 のプロジェクトファイル一式は、下記からダウンロードできますので、入力が面倒という方はご利用ください。
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"));
};
}
}
}
まとめ
今回は改行コード変換ツールの仕様、Visual Studioを使ったWindowsFormプログラムの作り方、処理の解説、ソースコード一式の紹介を行いました。
ドラッグ&ドロップは汎用的な関数にしていますので、リストボックスやDataGridViewなど、他のコントロールにも応用が可能です。
また、今回新しく登場した SplitContainer は重宝するコントロールなので、是非使いこなせるようになってください。
今回の記事が皆さんのお役に立てば幸いです。
コメント