2012年10月22日月曜日

マイクロソフトのUI標準ガイドみたいなのどこだっけ

業務アプリのフォーム設計を修正するにあたって、どうも使い勝手が悪い気がしたので、マイクロソフトが推奨するUI標準の資料みたいなのがどこかにあったのを思い出して探したんですが、なんかいろんなキーワードでググったんだけど見つけるのに苦労しましたw 「マイクロソフト UI 標準」「マイクロソフト ユーザーインタフェース ガイドライン」「Windows UI 推奨」とかね……いろいろ試したんだけどw

結局、自分が前に見たことあって今回探してたのは、これでした↓

Windows ユーザー エクスペリエンス ガイドライン

UIじゃなくてUX(ユーザーエクスペリエンス)がキーワードだったのね。思いつかなかった。Windows 7 と Vista 準拠となってます。Windows 8版はどこかにあるのだろうか。
MSDN内の記事なんで、ここからツリーを下っていくと細目が見られますが、上のリンクのページからPDFファイルがダウンロードできます。せっかくだからもうちょっとわかりやすいところに置いといてくれないかなぁ……。
また探しまわらなくていいように覚え書きw しかしMSDNってちょくちょく全面改定されてページのリンクが消失するんですよねー。一応タイトルが変わってなければまたMSDN内の検索で見つかるかと思いますが。

マルチスレッドにした覚えはないのに「有効ではないスレッド間の操作」でエラー

また思い出したのでメモ。

VB.NET(VS2010)で、シリアル通信接続のカードリーダーからカードの情報を読み込んでなんやかんや、というアプリケーションを作成していました。
カードリーダーとかよくわからんので、とりあえず、読み込んだデータをフォームに表示してみることに。カードリーダーの読み書きについては出来合いのライブラリがあるので、リード成功イベントのところで、読み込んだ値(String)をフォームのテキストボックスのTextプロパティにセットして表示するようにしました。ところが、Textプロパティに値をセットするところで、

有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'txtCardData′ がアクセスされました。

と出てしまってうまくいきません。txtCardDataというのがテキストボックスで、このTextプロパティに値を代入しようとしたところでエラーになります。
例によってググるとwこのエラーは、別のスレッドからUIコントロール(この場合、フォームに貼ってるテキストボックス)にアクセスしようとしたときに出るらしいです。でも別にマルチスレッドなコードは書いてないのですが……。

さらにググってわかったのは、シリアル通信の受信イベントは別スレッドで立ち上がるとかそういう制限(?)があるようです。自分ではマルチスレッドなコードを書いてなくても、勝手にマルチスレッドになってるらしい。となると、このコードのままじゃどうしたって駄目なのか……。

結局、リード成功のイベントからというのが駄目なんだから他からならいいだろうということで、ここのイベントからはクラスのメンバ変数に値を渡すだけにして(UIコントロールの操作をしなけりゃいいので変数セットとかはできる)、タイマ回してその変数を拾ってテキストボックスに表示させるようにしました。なんか回りくどいように思ったけど、シリアル通信関係のアプリケーションではタイマ監視して処理させるというのはなんかお決まりの処理らしいので、これでいいのか。

参照のプロパティが表示されない

ちょっと思い出したのでメモ。

VB.NET(VS2010)で、.NET Framework 4 対象のアプリケーションを作成していたとき、参照のプロパティで「相互運用型の埋め込み」をTrueに変更したいということがありました。今となってはなんで変更したかったのか思い出せないというかw結局そこ関係無かったみたいなんですけどw
で、プロジェクトのプロパティで「参照」を確認してから、プロパティを変更したいdllをソリューションエクスプローラーの「参照設定」ツリーの下から選択したんだけど……プロパティウィンドウが真っ白で何も表示されない。変更できないじゃん。

結論から言いますと、プロジェクトのプロパティを表示してるときには、ソリューションエクスプローラーで参照設定の要素を選択してもプロパティは表示されないのね。フォームのデザイナとかコードエディタを表示してから参照設定を選択し直すと、プロパティが表示されるようになります。しょうもないところでハマった……しかもこれでプロパティ変更してみたけど、やりたかったこととは関係なかったようで何にもなりませんでしたw

さらに付け加えておくと、このプロパティ「相互運用の埋め込み」は .NET Framework 4 対象の場合しか表示されないようで、こないだ .NET Framework 2.0 対象に変更したので、プロパティウィンドウにその項目が表示されなくなり、結局何がしたかったのかさっぱりw

2012年10月19日金曜日

バージョン情報ダイアログに複数行の説明を表示する


VB.NET(VS2010)で作成したアプリケーションで、バージョン情報ダイアログを表示することになりました。
とりあえずデザインはどうでもいいのでw用意されているテンプレートを使います。

追加→Windowsフォーム→共通項目→Windows Forms→情報ボックス を選択
デフォルト名の AboutBox1.vb で[追加]

フォームをデザイナで開くとこんなのができてます。


マルチラインのテキストボックスのところに、

説明:
(ランタイムに、ラベルのテキストはアプリケーションのアセンブリ情報に置き換えられます。
プロジェクト デザイナーの[アプリケーション]ペインで、アプリケーションのアセンブリ情報をカスタマイズします。)

とあり、一応このフォームの説明のようです(しかし後述しますが、ここのテキストボックスに表示される項目の名前も「説明」なのでそのことを指して「説明:」と書いているのかも……よくわからないw)。
ここにある通り、特にコードを書かなくても、アセンブリ情報で設定した値を参照して表示するようになってます。
このフォームのコードをみると、フォームのLoadイベントで、アプリケーションのアセンブリ情報 My.Application.Info の各項目から、このフォームのタイトルや各ラベル・テキストボックスに値がセットされているのがわかります。

で、アセンブリ情報を見てみると、


デフォルトではこうなってます。
適当に空欄を埋めてから実行して AboutBox1 フォームを表示すると、こうなります。


アセンブリ情報にあってここには表示されていない項目もありますがそれはおいといて。
説明欄はマルチラインのテキストボックスです。せっかくなので複数行表示したいのですが、アセンブリ情報の「説明」には1行しか入力できません……。
で、またググったんですがw それらしいものがヒットせず。しかたないので自分で考えることにw

バージョン情報ダイアログに表示できさえすればいいのであれば、AboutBox1 のコードを修正し、当該テキストボックス(TextBoxDescription)のTextプロパティに固定値でもセットしてしまえばOKです。しかしなんか釈然としない……。

AboutBox1_Load のソースを見ると、テキストボックスに渡されている値は、My.Application.Info.Description であることがわかります。ということで、なんとなく "Description" で現在のプロジェクトを検索。それらしいのがヒットしました。

' アセンブリに関する一般情報は以下の属性セットをとおして制御されます。
' アセンブリに関連付けられている情報を変更するには、
' これらの属性値を変更してください。
' アセンブリ属性の値を確認します。
<Assembly: AssemblyTitle("WindowsApplication1")>
<Assembly: AssemblyDescription("説明ですよ")>
<Assembly: AssemblyCompany("会社ですよ")>
<Assembly: AssemblyProduct("WindowsApplication1")>
<Assembly: AssemblyCopyright("Copyright c  2012")>
<Assembly: AssemblyTrademark("商標ですよ")>

さっきアセンブリ情報に入力した値がここ AssemblyInfo.vb に出ています。
この AssemblyDescription の "説明ですよ" のところに複数行の内容を書けば、My.Application.Info.Description にも反映されるのでしょうか? 早速やってみます。

<Assembly: AssemblyDescription("説明ですよ" & vbCrLf & _
                                "ほげほげ" & vbCrLf & _
                                "なんやかんや" & vbCrLf & _
                                "あれやこれや")>

複数行といっても文字列としては1つなわけですが、文字列の途中に改行コード(改行定数?) vbCrLf を入れるとそこで表示のときに改行されます。
見やすいように複数行にしていますが(行末に _)、別に1行で書いてもOKです。
実行して表示してみると、こうなりました。


できたよやったー。
念のため、アセンブリ情報も見てみます。


なんかさっき AssemblyInfo.vb で書いたのが、改行コードと継続行記号(_)も含めてそのまま表示されてます。これって、最初からここに改行コード入りの1行で記入すればよかったってことなんじゃ……orz まいっかw

対象のフレームワークを変更したら環境設定が読めなくなった

VB.NET(VS2010)で作成していたプロジェクトですが、そろそろ完成という段になり、対象のフレームワークを2.0にしてくれと言われました。4で作ってたのに……。
まぁ別に .NET Framework 4 特有のクラスとか使ってないはずなのでいいか、と、2.0に変更してコンパイルは通ったのですが、実行してみたら環境設定(My.Settings)を参照するところでエラーになってます。だめじゃん。

対象のフレームワークの変更手順は次のとおり。
1.プロジェクトのプロパティの「コンパイル」タブの[詳細コンパイルオプション]ボタンをクリック
2.「対象のフレームワーク」を「.NET Framework 4 Client Profile」から「.NET Framework 2.0」に変更
3.[OK]すると、
---------------------------
ターゲット フレームワークの変更
---------------------------
ターゲット フレームワークを変更するには、現在のプロジェクトを閉じてからもう一度開く必要があります。
プロジェクト内の保存していない変更は自動的に保存されます。
ターゲット フレームワークを変更すると、ビルドのためにプロジェクト ファイルを手動で変更する必要が生じることがあります。
このプロジェクトのターゲット フレームワークを変更しますか?
---------------------------
はい(Y)   いいえ(N)   ヘルプ
---------------------------
と言われるけど他にどうしようもないので[はい]をクリック
4.ビルド

ビルドではエラーが出ないんですけどね……。
とりあえずいつものようにググるw
まずは参照設定も確認が必要とのことなので、プロジェクトのプロパティの「参照」タブを確認。
いくつかの参照で、
<システムでは、指定された参照が見つかりません。>
と表示されています。これを削除。これは Framework 4 にはあったけど 2.0 には対応するものがないもののようです。これがないとビルドも通らないようだと、2.0 にはできないことになるのかな? 他のクラスに置き換えるとか必要になるんでしょう。今回はOKだったので、削除だけしときます。

ここで一応再ビルドして実行してみるけど、やっぱり環境設定読むとこでエラー。

さらにググると、configの記法が2.0と4では違うのだみたいなことも書いてありましたが、最終的には関係なかったみたいなので割愛w
しかし環境設定のファイル(config)が読めないのはたしかなので、そのへんがあやしいとは思います。で、app.config を調べます。
なんか頭の方に、Framework 4 であることを示すらしいところがあるので、これかな?


    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
            <section name="Hogehoge.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
        </sectionGroup>
    </configSections>

試しに、新規のVBプロジェクトを作成し、ひとつ環境設定を定義して、内容をフォームに表示するだけのものを、最初から対象のフレームワークを2.0にしてビルドしてみます。そして app.config を見てみると、

    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="WindowsApplication1.My.MySettings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
    </configSections>

2.0であるっぽい記述になってます。ので、エラーになってたプロジェクトの 4.0.0.0 を 2.0.0.0 に変更してビルドして実行したら、エラーが出なくなりました。わーい。
しかしこの程度の変更ですむのなら、最初から自動的に変更してくれてもいいんジャマイカ。
ちなみに、同じく app.config の末尾の方には、

<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/></startup>

というのがあったのですが(使用するランタイムのバージョンを定義しているっぽい)、ここは勝手に

<startup><supportedRuntime version="v2.0.50727"/></startup>

こうなっていたのですよ。なんでついでにさっきのところも変えといてくれないのかw


2012年10月9日火曜日

テーブルアダプタの検索クエリにパラメータを渡すときの注意

VB.NET(VS2010)でテーブルの検索処理をするので、テーブルアダプタに検索クエリを作成、フォームで入力された値をキーにして検索するというごく普通の処理を作成。文字列の部分一致で検索させたかったので、入力値の前後にワイルドカードの % をつけてLIKE検索としました。すると完全一致のとき検索に失敗……あるはずのデータにヒットしない。よく調べてみると、検索対象のフィールド長より2文字少ない長さまでは部分一致検索できてるのが、それより長くなると失敗している。

検索対象の文字列フィールド Hogehoge の長さ:16
検索キーの入力欄(テキストボックス)のMax長さ:16

のとき、入力欄に1~14文字入力しているときはうまくヒットするんだけど、15~16文字だと失敗。
前後につけた % の2文字分というのがなんとなくあやしいとはあたりがつきましたが、さてそれってどこを直せば……。

と、先週末ハマっていたのですが、休み明けの今日、データセットのソース(~designer.vb)をゆっくり見てみると、クエリの定義のところに引数(@~)の長さ定義とかもあるのに気がつきました。ソースを直接直すのは危険なので、デザイナのどこかに設定箇所があるはず……と探して、ありました。テーブルアダプタのクエリを選択して、プロパティの Parameters のコレクションを展開すると、@引数の一覧が表示されます。当該パラメータの Size で2桁分増やしてやればOK。
例でいうと @hogehoge とかの Size が 16 になってるのを 18 にしてやる。

これってフィールド長いっぱいの検索キーを使用するときには常に起こりうる現象なんですが、そもそも入力したキーの前後に % つけてLIKE検索するというのがおかしいというか一般的でないのかな? 入力欄にワイルドカードとか含めた正規表現の記法で書いてもらえば(入力欄の文字数Maxがフィールド長と同じならば)問題ないんでしょうが、入力する人に正規表現覚えてもらわなきゃならないというのもなんかなーと思い……まぁ % (あるいは *) のワイルドカードぐらい覚えてもらってもいいかもですが。