WinForms超入門:初めての自作アプリ12選(最小機能つき)
“最初の一作目”は、短時間で完成して動く手応えが得られる題材が最適です。ここでは、レベル別におすすめアプリを並べ、各項目に学べること/最小機能/発展アイデアを添えました。記事後半には、フォーム構成の型・頻出スニペット・つまずき対策もまとめています。
目次
レベル0(30〜90分)
1) クリックカウンター
- 学べる:イベント、状態保持、プロパティ更新
- 最小機能:回数表示ラベル+「+1」「リセット」ボタン
- 発展アイデア:複数ボタンの内訳、履歴表示
2) 温度変換(℃↔︎℉)
- 学べる:TryParse による入力検証、責務分離
- 最小機能:数値入力→変換→結果表示(無効入力はメッセージ)
- 発展アイデア:双方向切替、履歴リスト、クリップボード連携
3) ストップウォッチ/カウントダウン
- 学べる:System.Windows.Forms.Timer、UIスレッド更新
- 最小機能:開始/停止/リセット、mm:ss.ff 表示
- 発展アイデア:ラップ記録、ホットキー、終了音
Timer最小サンプル(Form1)
public partial class Form1 : Form
{
private readonly Timer _timer = new() { Interval = 10 }; // 10ms
private int _elapsedMs;
public Form1()
{
InitializeComponent();
labelTime.Text = "00:00.00";
_timer.Tick += Timer_Tick; // ← シンプル
}
private void Timer_Tick(object? sender, EventArgs e)
{
_elapsedMs += _timer.Interval;
labelTime.Text = TimeSpan.FromMilliseconds(_elapsedMs).ToString(@"mm\:ss\.ff");
}
private void btnStart_Click(object s, EventArgs e) => _timer.Start();
private void btnStop_Click(object s, EventArgs e) => _timer.Stop();
private void btnReset_Click(object s, EventArgs e)
{
_elapsedMs = 0;
labelTime.Text = "00:00.00";
}
}
レベル1(半日〜1日)
4) じゃんけん/サイコロ
- 学べる:Random、enum、switch
- 最小機能:プレイヤー入力→CPU→勝敗表示
- 発展アイデア:連勝数、グラフ風ラベル、効果音
5) 単位変換ツール(長さ・重さ・面積)
- 学べる:ComboBox、モデルクラス設計
- 最小機能:カテゴリと単位選択→変換
- 発展アイデア:履歴CSV、ショートカット操作
6) クリップボード整形
- 学べる:Clipboard API、文字列操作
- 最小機能:貼り付け→整形→コピー(全角/半角・トリム)
- 発展アイデア:履歴、正規表現プリセット
レベル2(1〜2日)
7) メモ帳(簡易Notepad)
- 学べる:MenuStrip、OpenFileDialog/SaveFileDialog、文字コード
- 最小機能:新規/開く/保存、変更フラグ、終了時の確認
- 発展アイデア:最近使ったファイル(MRU)、検索/置換、UTF-8/Shift_JIS切替
- 注意:using var でファイルを確実に閉じる
8) 画像ビューア
- 学べる:PictureBox、D&D、TrackBarズーム
- 最小機能:フォルダ選択→前後移動→フィット表示
- 発展アイデア:回転/反転、サムネイル、スライドショー
- 注意:pictureBox.Image?.Dispose() を忘れるとファイルがロックされる
9) 単語帳クイズ(CSV)
- 学べる:ファイルI/O、List<T>、ランダム出題、スコア管理
- 最小機能:問題→選択肢→正誤→スコア
- 発展アイデア:タイムアタック、タグ出題、成績JSON保存
レベル3(2〜3日)
10) ToDoリスト(永続化)
- 学べる:DataGridView / BindingList<T>、データバインディング、JSON保存
- 最小機能:追加/編集/完了/削除、終了時保存→起動時復元
- 発展アイデア:未完フィルタ、締切アラート、ドラッグで並べ替え
11) 家計簿ミニ
- 学べる:LINQ集計、decimal(金額計算)、CSV入出力
- 最小機能:収支入力→月次合計
- 発展アイデア:カテゴリ別円グラフ、期間フィルタ、バックアップ
12) タイピングゲーム
- 学べる:キーボードイベント、Timer、難易度調整
- 最小機能:単語提示→タイプ→スコア
- 発展アイデア:連続モード、ランキング、辞書入替
最初の一作:進め方テンプレート
ここでは「温度変換」を例に設計→実装→検証の型を示します。どの題材にも流用できます。
1. 仕様を1行で言語化
- 「数値(℃)を入力し、ボタンで℉へ変換して表示。無効入力は警告する。」
2. フォーム構成(命名まで先に決める)
- TextBox(txtCelsius)
- Button(btnToFahrenheit)
- Label(lblResult)
- (任意)ErrorProvider(errorProvider1)
3. ロジックをFormから分離(テストしやすく)
public static class TemperatureConverter
{
public static double CelsiusToFahrenheit(double c) => c * 9.0 / 5.0 + 32;
}
4. UIコードは薄く・入力検証は TryParse
private void btnToFahrenheit_Click(object sender, EventArgs e)
{
errorProvider1.SetError(txtCelsius, "");
if (!double.TryParse(txtCelsius.Text, out var c))
{
errorProvider1.SetError(txtCelsius, "数値を入力してください。");
return;
}
var f = TemperatureConverter.CelsiusToFahrenheit(c);
lblResult.Text = $"{f:F1} ℉";
}
5. 動作確認チェック
- 無効入力時に落ちない(例外なし)
- 小数入力もOK
- 連打しても表示が崩れない
フォーム設計の「型」
命名規則(例)
- Button: btnStart, btnSave
- Label: lblStatus, lblCount
- TextBox: txtInput, txtPath
- Timer: timerMain
- PictureBox: picPreview
イベントの基本
- イベントは1アクション=1メソッドを原則に短く保つ
- 長くなる処理は別クラスやメソッドへ切り出す
- 匿名ラムダでの購読は解除が難しいので、基本は名前付きハンドラ
頻出スニペット集
1) TryParse パターン
if (!int.TryParse(txtCount.Text, out var count))
{
MessageBox.Show("整数を入力してください。");
return;
}
2) ファイルを確実に閉じる
using var sw = new StreamWriter(path, append: false, Encoding.UTF8);
sw.WriteLine("hello");
3) 実行ファイル横のデータを読む(学習用)
- CSVや画像を「出力ディレクトリにコピー」して、以下で参照
string dataPath = Path.Combine(AppContext.BaseDirectory, "questions.csv");
var lines = File.ReadAllLines(dataPath, Encoding.UTF8);
実運用では AppData 等に保存するのが一般的。学習初期は「コピーして読む」で十分です。
4) 画像のロックを避ける
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var img = Image.FromStream(fs);
pictureBox.Image?.Dispose();
pictureBox.Image = new Bitmap(img);
5) Timer は UI用を使う
- やってはいけない:Thread.Sleep(…)(UIが固まる)
- やるべき:System.Windows.Forms.Timer で Tick 内だけ更新
つまずき対策(よくある5項)
- UIが固まる
- 原因:Thread.Sleep や重い処理の直書き
- 対策:Timer・非同期処理へ分離、重い処理は別スレッド
- ファイルが保存/読み込みできない
- 原因:パスの勘違い/ファイルを閉じていない
- 対策:AppContext.BaseDirectory で確認、using で確実にDispose
- 画像が編集できない/上書きできない
- 原因:Image のDispose漏れ
- 対策:差し替え前に pictureBox.Image?.Dispose()
- イベントが解除できない
- 原因:匿名ラムダで += して -= できない
- 対策:名前付きハンドラ、またはラムダを変数に保持して解除
- テストが難しい
- 原因:ロジックをFormに直書き
- 対策:モデルクラスへ分離(例:TemperatureConverter)
学習課題(自力で伸ばすためのチェックリスト)
- どの題材でも仕様を1行で言語化できたか
- 最小機能を先に完成 → 後から発展アイデアを1つだけ足す
- UI名前は意味のあるものに(button1卒業)
- 例外を出さずに無効入力を扱えるか(TryParse/ErrorProvider)
- 画像/ファイルは必ず閉じる(Dispose)
まとめ:まずは1時間で「動く」を掴む
- 初作は ストップウォッチ か 温度変換 が特におすすめ。
- できあがったら、命名の見直しと入力検証だけでもう一段きれいになります。
- ロジックを別クラスに分ける癖を、この段階から身につけましょう。
訪問数 5 回, 今日の訪問数 5回
ディスカッション
コメント一覧
まだ、コメントがありません