1 // ================================================================================================
3 // フォーム処理に関するユーティリティクラスソース。</summary>
5 // <copyright file="FormUtils.cs" company="honeplusのメモ帳">
6 // Copyright (C) 2012 Honeplus. All rights reserved.</copyright>
9 // ================================================================================================
11 namespace Honememo.Wptscs.Utilities
14 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Windows.Forms;
18 using Honememo.Models;
20 // ※ プロパティを含むので、そのまま他のプロジェクトに流用することはできない
21 using Honememo.Wptscs.Properties;
24 /// フォーム処理に関するユーティリティクラスです。
26 public static class FormUtils
31 /// バージョン情報を含んだアプリケーション名を返す。
33 /// <returns>アプリケーション名</returns>
34 public static string ApplicationName()
36 // アセンブリからバージョン情報を取得し、書式化して返す
38 // ※例外なし。もし万が一発生する場合はそのまま投げる
39 Version ver = Assembly.GetExecutingAssembly().GetName().Version;
40 return String.Format(Resources.ApplicationName, ver.Major, ver.Minor);
44 /// 指定されたファイルを UserAppDataPath
45 /// → 旧バージョンのUserAppDataPath
46 /// → StartupPath の順に探索し、その際のパスを返す。
48 /// <param name="fileName">ファイル名。</param>
49 /// <param name="compatible">探索する旧バージョンの最大。</param>
50 /// <returns>ファイルが存在したパス、どこにも存在しない場合は<c>null</c>。</returns>
51 /// <remarks>アセンブリ名が変わっている場合、旧バージョンは探索不可。</remarks>
52 public static string SearchUserAppData(string fileName, string compatible)
54 // ※ 以下GetFilesAtUserAppDataと共通化してもよいが、性能に影響あるかと考え自前で処理
55 // 現在の UserAppDataPath を探索
56 string path = Path.Combine(Application.UserAppDataPath, fileName);
57 if (File.Exists(path))
62 // 可能であれば、旧バージョンの UserAppDataPath を探索
63 if (!String.IsNullOrEmpty(compatible))
66 foreach (string dir in FormUtils.GetCompatibleUserAppDataPaths(compatible))
68 path = Path.Combine(dir, fileName);
69 if (File.Exists(path))
76 // どこにも無い場合は、exeと同じフォルダを探索
77 path = Path.Combine(Application.StartupPath, fileName);
78 if (File.Exists(path))
87 /// 指定されたファイルを UserAppDataPath
88 /// → StartupPath の順に探索し、その際のパスを返す。
90 /// <param name="fileName">ファイル名。</param>
91 /// <returns>ファイルが存在したパス、どこにも存在しない場合は<c>null</c>。</returns>
92 public static string SearchUserAppData(string fileName)
95 return FormUtils.SearchUserAppData(fileName, null);
100 /// → 旧バージョンのUserAppDataPath
101 /// → StartupPath から、指定した検索パターンに一致するファイル名を返す。
103 /// <param name="searchPattern">ファイル名と対応させる検索文字列。</param>
104 /// <param name="compatible">探索する旧バージョンの最大。</param>
106 /// 指定した検索パターンに一致するファイル名を格納するString配列。ファイル名には完全パスを含む。
107 /// 同名のファイルが複数のパスに存在する場合、最初に発見したもののみを返す。
109 /// <exception cref="ArgumentException"><paramref name="searchPattern"/>に有効なパターンが含まれていない場合。</exception>
110 /// <exception cref="ArgumentNullException"><paramref name="searchPattern"/>が<c>null</c>の場合。</exception>
111 /// <exception cref="UnauthorizedAccessException">呼び出し元に、必要なアクセス許可がない場合。</exception>
112 /// <remarks>アセンブリ名が変わっている場合、旧バージョンは探索不可。</remarks>
113 public static string[] GetFilesAtUserAppData(string searchPattern, string compatible)
115 // 現在の UserAppDataPath を探索
116 List<string> files = new List<string>();
117 IgnoreCaseSet names = new IgnoreCaseSet();
118 if (Directory.Exists(Application.UserAppDataPath))
120 FormUtils.MergeFiles(files, names, Directory.GetFiles(Application.UserAppDataPath, searchPattern));
123 // 可能であれば、旧バージョンの UserAppDataPath を探索
124 if (!String.IsNullOrEmpty(compatible))
127 foreach (string dir in FormUtils.GetCompatibleUserAppDataPaths(compatible))
129 FormUtils.MergeFiles(files, names, Directory.GetFiles(dir, searchPattern));
134 FormUtils.MergeFiles(files, names, Directory.GetFiles(Application.StartupPath, searchPattern));
135 return files.ToArray();
140 /// → StartupPath から、指定した検索パターンに一致するファイル名を返す。
142 /// <param name="searchPattern">ファイル名と対応させる検索文字列。</param>
144 /// 指定した検索パターンに一致するファイル名を格納するString配列。ファイル名には完全パスを含む。
145 /// 同名のファイルが複数のパスに存在する場合、最初に発見したもののみを返す。
147 /// <exception cref="ArgumentException"><paramref name="searchPattern"/>に有効なパターンが含まれていない場合。</exception>
148 /// <exception cref="ArgumentNullException"><paramref name="searchPattern"/>が<c>null</c>の場合。</exception>
149 /// <exception cref="UnauthorizedAccessException">呼び出し元に、必要なアクセス許可がない場合。</exception>
150 public static string[] GetFilesAtUserAppData(string searchPattern)
153 return FormUtils.GetFilesAtUserAppData(searchPattern, null);
157 /// UserAppDataPath → StartupPath から、全ファイル名を返す。
160 /// フォルダ内の全ファイル名を格納するString配列。ファイル名には完全パスを含む。
161 /// 同名のファイルが複数のパスに存在する場合、最初に発見したもののみを返す。
163 /// <exception cref="UnauthorizedAccessException">呼び出し元に、必要なアクセス許可がない場合。</exception>
164 public static string[] GetFilesAtUserAppData()
167 return FormUtils.GetFilesAtUserAppData("*", null);
171 /// 文字列中のファイル名に使用できない文字を「_」に置換。
172 /// また、&nbsp;由来の半角スペース (u00a0) も普通の半角スペース (u0020) に置換する。
174 /// <param name="fileName">ファイル名。</param>
175 /// <returns>置換後のファイル名。</returns>
176 public static string ReplaceInvalidFileNameChars(string fileName)
178 // 渡された文字列にファイル名に使えない文字が含まれている場合、_ に置き換える
179 string result = fileName;
180 foreach (char c in Path.GetInvalidFileNameChars())
182 result = result.Replace(c, '_');
185 // 由来の半角スペース (u00a0) も普通の半角スペース (u0020) に置き換える
186 result = result.Replace(' ', ' ');
195 /// <see cref="DataGridViewCell"/>が<c>null</c>の場合に空の文字列を返す<see cref="Object.ToString"/>。
197 /// <param name="obj">値を<see cref="Object.ToString"/>するセル。<c>null</c>も可。</param>
198 /// <returns>渡されたセルの<see cref="DataGridViewCell.Value"/>を<see cref="Object.ToString"/>した結果。<c>null</c>の場合には空の文字列。</returns>
199 public static string ToString(DataGridViewCell obj)
201 return FormUtils.ToString(obj, String.Empty);
205 /// <see cref="DataGridViewCell"/>が<c>null</c>の場合に指定された文字列を返す<see cref="Object.ToString"/>。
207 /// <param name="obj">値を<see cref="Object.ToString"/>するセル。<c>null</c>も可。</param>
208 /// <param name="nullStr">渡されたセルが<c>null</c>の場合に返される文字列。<c>null</c>も可。</param>
209 /// <returns>渡されたセルの<see cref="DataGridViewCell.Value"/>を<see cref="Object.ToString"/>した結果。<c>null</c>の場合には指定された文字列。</returns>
210 public static string ToString(DataGridViewCell obj, string nullStr)
216 else if (obj.Value == null)
221 return obj.Value.ToString();
229 /// 単純デザインの通知ダイアログ(入力された文字列を表示)。
231 /// <param name="msg">メッセージ。</param>
232 public static void InformationDialog(string msg)
234 // 渡された文字列で通知ダイアログを表示
237 Resources.InformationTitle,
238 MessageBoxButtons.OK,
239 MessageBoxIcon.Information);
243 /// 単純デザインの通知ダイアログ(入力された文字列を書式化して表示)。
245 /// <param name="format">書式項目を含んだメッセージ。</param>
246 /// <param name="args">書式設定対象オブジェクト配列。</param>
247 public static void InformationDialog(string format, params object[] args)
250 FormUtils.InformationDialog(String.Format(format, args));
254 /// 単純デザインの警告ダイアログ(入力された文字列を表示)。
256 /// <param name="msg">メッセージ。</param>
257 public static void WarningDialog(string msg)
259 // 渡された文字列で警告ダイアログを表示
262 Resources.WarningTitle,
263 MessageBoxButtons.OK,
264 MessageBoxIcon.Warning);
268 /// 単純デザインの警告ダイアログ(入力された文字列を書式化して表示)。
270 /// <param name="format">書式項目を含んだメッセージ。</param>
271 /// <param name="args">書式設定対象オブジェクト配列。</param>
272 public static void WarningDialog(string format, params object[] args)
275 FormUtils.WarningDialog(String.Format(format, args));
279 /// 単純デザインのエラーダイアログ(入力された文字列を表示)。
281 /// <param name="msg">メッセージ。</param>
282 public static void ErrorDialog(string msg)
284 // 渡された文字列でエラーダイアログを表示
287 Resources.ErrorTitle,
288 MessageBoxButtons.OK,
289 MessageBoxIcon.Error);
293 /// 単純デザインのエラーダイアログ(入力された文字列を書式化して表示)。
295 /// <param name="format">書式項目を含んだメッセージ。</param>
296 /// <param name="args">書式設定対象オブジェクト配列。</param>
297 public static void ErrorDialog(string format, params object[] args)
300 FormUtils.ErrorDialog(String.Format(format, args));
308 /// <see cref="DataGridViewRow"/>が空行かを判定する。
310 /// <param name="row">1行。</param>
311 /// <returns>空行の場合<c>true</c>。</returns>
312 public static bool IsEmptyRow(DataGridViewRow row)
314 foreach (DataGridViewCell cell in row.Cells)
316 if (!String.IsNullOrEmpty(FormUtils.ToString(cell)))
330 /// 指定されたバージョン以上の旧バージョンのUserAppDataPathを取得する。
332 /// <param name="compatible">探索する旧バージョンの最大。</param>
333 /// <returns>旧バージョンと自バージョンの間のフォルダ名を格納するString配列。フォルダ名には完全パスを含む。</returns>
335 /// フォルダが異なる同じファイル名のパスが存在する場合、登録しない。
336 /// アセンブリ名が変わっている場合、旧バージョンは探索不可。
338 private static string[] GetCompatibleUserAppDataPaths(string compatible)
341 // <ベースパス>\<CompanyName>\<ProductName>\<ProductVersion>
342 // という構成のはずなので、一つ上のフォルダから自分より前のフォルダを探索
343 List<string> paths = new List<string>();
344 string parent = Path.GetDirectoryName(Application.UserAppDataPath);
345 if (!String.IsNullOrEmpty(parent))
348 string now = Path.GetFileName(Application.UserAppDataPath);
350 // 同じ階層のフォルダをすべて取得し、降順にソート
351 string[] directories = Directory.GetDirectories(parent);
352 Array.Sort(directories);
353 Array.Reverse(directories);
355 // 指定された互換バージョンと自バージョンの間のパスのみを取得
356 foreach (string dir in directories)
358 string ver = Path.GetFileName(dir);
359 if (compatible.CompareTo(ver) <= 0 && ver.CompareTo(now) < 0)
366 return paths.ToArray();
370 /// <see cref="GetFilesAtUserAppData(string, string)"/>用のファイル名リストのマージを行う。
372 /// <param name="mergeto">マージ先ファイル名リスト。</param>
373 /// <param name="names">比較高速化用のパスを含まないファイル名セット。</param>
374 /// <param name="mergefrom">マージ元ファイル名リスト。</param>
375 /// <remarks>フォルダが異なる同じファイル名のパスが存在する場合、登録しない。</remarks>
376 private static void MergeFiles(IList<string> mergeto, IgnoreCaseSet names, IList<string> mergefrom)
378 foreach (string file in mergefrom)
380 string name = Path.GetFileName(file);
381 if (!names.Contains(name))