びったんびったん

ユーザビリティ・プログラミングについて。

Form.Close() メソッドの CloseReason は UserClosing

Form アプリケーションがどのように終了する(した)のかは CloseReason で知ることができる。
CloseReason 列挙体 (System.Windows.Forms)

これの注意点として CloseReason が UserClosing になるのはウィンドウの閉じるボタンや Alt + F4 で終了するときだけではなく、 Form.Close() メソッドを呼んだときもである。

ShowWindow(hWnd, SW_RESTORE) は Visible プロパティを更新しない

やりたいこと

最小化されていてかつ非表示なフォームがある。これを表示し元のサイズに戻したい。

バグ

状況を再現する最小のコードを書いた。元のサイズに戻すことは .NET ではできないので Win32 の ShowWindow(hWnd, SW_RESTORE) 関数を使う。

class C {

    [DllImport("user32")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    private const int SW_RESTORE = 9;

    private void F() {
        var f = new Form {
            WindowState = FormWindowState.Minimized
        };
        ShowWindow(f.Handle, SW_RESTORE);

        Console.WriteLine(f.Visible); // フォームは表示されているのになぜか Visible は false
    }
}

フォームは表示されているのになぜか Visible は false になる。イミワカンナイ

なにがまずいのか

.NET がフォームをごにょごにょするときに Visible を参照して表示か非表示かを判断していることがありそこがバグる

具体的にはフォームに関連付けられたコンテキストメニューは、フォームが表示されているときにしか表示できないらしい。先のバグでフォームが表示されているにもかかわらずコンテキストメニューが表示できなかった。

じゃあどうすんの

ShowWindow(f.Handle, SW_RESTORE);
f.Show();
// f.Visible = true;

ShowWindow 関数の直後に Show メソッドを呼ぶか Visible プロパティに true をセットする。かなり気持ち悪いが、今のところ不具合は起きていない。もっとよい方法があれば教えてください。

まとめ

.NET と Win32 が混在するときには最新の注意を払いましょう。

次バージョンを決めた

自作ソフトの現バージョンは 0.3 なのだけれど次バージョンは 1.1 に決めた。

メジャーバージョンを 0.X から 1.X に上げているのは大きな機能がたくさん増えるため。

なぜ 1.0 ではなく 1.1 なのかというと 1.0 だとユーザに初公開と勘違いされるかもしれないから。初公開ではなくバージョンアップですよーというのがユーザに伝わるメリットは3つ。

  • メンテナンスしてるよーというのが伝わる
  • ユーザがたくさんいるからバージョンアップしたと思ってくれるかもしれない
  • 個人的に更新履歴を見るのって楽しい(私だけ?

Firefox 32.0 リリースノート
まったく関係ないけどブラウザって結構な速度で JavaScriptCSS の標準規格への準拠を進めてるなーと思った。

バージョン番号に最終更新日を含めるべきか?

自作ソフトの現バージョンは 0.3 と 0.3.20140712 の2つともを正式なバージョンとしている。

他のサイト様に紹介いただいてソフト一覧に並ぶことがあると思いますが、このとき紹介いただくサイト様ごとにデザインが違い最終更新日があるサイトもないサイトもありますよね。そんなときにこんな感じで適切に使い分けてくれたらなーという思いをこめたからです。

最終更新日の記載があるサイト

ソフト名 バージョン 最終更新日
ソフト v1.0 2014/xx/xx
私のソフト v0.3 2014/07/12
ソフト v1.0 2014/xx/xx

最終更新日の記載がないサイト

ソフト名 バージョン
ソフト v1.0
私のソフト v0.3.20140712
ソフト v1.0

・・・なのですがコノザマダヨ

f:id:hakomof:20140922192134p:plain

動作環境をわかりやすくするためのバージョン番号

最近では OS に限らずブラウザや IDE などにサードパーティ製のソフトウェアやアドオン、プラグインなどが増えてきました。

しかしソフトウェアの動作元のバージョンアップでソフトウェアが動かなくなることもあるので動作環境を明らかにすることは重要です。そのとき動作元が(あまり頻繁に数字が増えないような)メジャーバージョン番号をユーザにわかりやすく周知させているとよいです。

なぜかというと Windows OS のようにバージョンごとに異なる名前が振られていると動作環境の記述が冗長になるからです。以下の例は同じ動作環境の2種類の書き方です。

わかりやすいが冗長
動作環境: Windows Vista, Windows 7, Windows 8 以上

簡潔だが例えば Windows 8 ユーザには動作するかどうかが知識がないとわからない
動作環境: Windows Vista 以上

バージョンアップごとに無機質な数字ではなく名前を振りたくなる気持ちもわかりますが、メジャーバージョン番号を周知させてください。

エンドユーザがソフトウェアをインストールするときに DLL の依存関係を解消してくれたらいいな

ひとつの言語にひとつのパッケージ管理システムが当たり前になりつつある昨今、エンドユーザがソフトウェアをインストールするときにもパッケージ管理システムが普及して欲しいな。

たとえ複数のソフトウェアで同じサードパーティー製 DLL が使われていたとしても、実行ファイルに同梱されることがほとんどで重複してしまうためダウンロード・ストレージの無駄である。

開発者が依存する DLL を指定することでエンドユーザがインストールするときに未インストールな DLL だけ個別にインストールされて欲しい。これで実行ファイルのあるディレクトリが DLL でうじゃうじゃするのも防げるしね。

インライン SVG がうまく表示されない

インライン SVG というのは HTML に直接記述できる SVG です。こんな感じ。

<body>
    <svg>
        <path />
    </svg>
</body>

そのインライン SVG が HTML 圧縮ツールのせいでうまく表示されませんでした。というのも input タグのような閉じタグのないタグは HTML ではスラッシュがいりません(あってもよい)。そのため HTML 圧縮ツールは文字数を減らすためスラッシュを消していました。

しかし SVGXML であり XML はスラッシュが必須です。 HTML 圧縮ツールSVG のスラッシュを消していてうまく表示されなかったのです。

対応策

  • HTML 圧縮ツールを使わない。
  • HTML 圧縮ツールにスラッシュを消させないようオプションを設定する。
  • SVG を外部ファイルにして読み込む。
  • CSSSVG を記述する。

プリミティブ型や構造体の FirstOrDefault

とてもよい本でした。
C#ショートコードプログラミング第2版 【▲→川俣晶の縁側→技術関連執筆情報】

この本に null 許容型を使えばプリミティブ型のデフォルトと区別をつけられるよーって書いてありました。

var v = (new int?[] { 1, 2, 3 }).FirstOrDefault(p => p == 0);
if(v == null) {
} else {
    // v にごにょ
}

そんな都合よく null 許容型に変えられるわけないでしょ(笑
どちらも一長一短ありますが私ならこうします。

var v = (new int[] { 1, 2, 3 }).Where(p => p == 0);
if(v.Count() == 0) {
} else {
    // v.First() にごにょ
}

LINQ というか関数型大好きマンになってしまった。もう少し純粋度の高い関数型で大きなプログラム書きたい。