エントリー

Top > Programmingとか > VB / VB.NET > 泥Tips

2006年11月14日

(35) VB6:ErrorLevel

Declare Sub ExitProcess Lib "kernel32" (ByVal uExitCode As Long)
で一発。知らなかったよ…orz

元ネタはDevX.comReturn a Dos error code on exit

2006年10月19日

(34) VB2005:0除算例外が発生しない

先日のこと。

VBを使ったプログラミングの説明をしてまして、「0で除算するとオーバーフロー例外が発生して」と説明したら、「0除算例外ではないんですかい?」とツッコみが入りました。

言われてみればその通りだ。

でも実際問題として、VBで0除算すると発生するのは「System.OverflowException」であって「System.DivideByZeroException」ではないんだよなぁ。なんでだ?

0001.png
(クリックで拡大します)

VB2005のExpress EditionでやってもTeam SuiteでやってもVB.NET2003でやってもオーバーフロー例外。

むー?とか悩んでいたら、msdnLibraryの/ 演算子 (Visual Basic)のページに、

除算を実行する前に、整数の数式は必ず Double 型に拡大変換されます。

ってええっ

で、DivideByZeroException クラスの説明では、

浮動小数点値を 0 で除算すると、IEEE 754 の算術規則に従って、結果の値は、正の無限大、負の無限大、または非数 (NaN) のいずれかになります。浮動小数点演算では、例外はスローされません。

ってあらー

ついでに、Double.PositiveInfinity フィールドの説明では、

正の無限大を表します。このフィールドは定数です。
この定数の値は、正数を 0 で除算した結果です。

つことは、

  1. 整数型の値同士で除算を行おうとすると、計算前にそれぞれの値がDouble型に変換される。

  2. 浮動小数点型で0除算した場合には例外はスローされず、割られる数の符号に応じて正または負の無限大が計算結果となる。

  3. 演算結果である±∞を左辺の整数型変数に代入しようとしてオーバーフロー例外が発生する。

ってことですかい。
ならば、左辺の受け側変数をDouble型ににしちまえばオーバーフロー例外も発生しなくなるってことですかい?

Private Sub Button1_Click(...) Handles Button1.Click

Dim a As Integer = 10
Dim b As Integer = 0
Dim c As Double = 0

c = a / b

End Sub

うわぁほんとに発生しねぇ。スルーで通っちまいましたよお客さん。

ちなみに、Decimal型の場合は事前のDouble型変換が行われないので、0除算例外が発生します。

0003.png
(クリックで拡大します)

上でお見せしたVBのリリースEXE(MSIL)がどうなってるかってぇと、

0004.png
(クリックで拡大します)

わー確かにIL_0008とIL_000aでDouble型に変換(conv.r8)してからdivかけてはるー。


VB6までは0除算エラーは型にかかわらず発生していたんですよ。
浮動小数点型の0除算がIEEE754に則って±∞または非数(NaN)を返すようになったのはVB.NETからってゅうか.NET Framework1.0からですね。
例外が発生しないのは浮動小数点型での0除算のみで、整数型・固定小数点型での0除算は旧来通り0除算例外が発生します。

このへん、VB5:Single型・Double型の変数で計算すると微妙に数値が狂うで型ごとのデータの内部格納形式を調べた時にブツカって、「あーVBってIEEEに準拠しない独自仕様なのねー」とちょっとしょんぼりした覚えがあるのでなんか懐かしいす。

かといって小数の演算結果になり得る演算を整数型のままでやるわけにもいかないので、

Dim a As Integer = 10
Dim b As Integer = 0
Dim c As Double = 0

c = a / b
って記述した時は、意味的には
Dim a As Integer = 10
Dim b As Integer = 0
Dim c As Double = 0

c = CInt(CDbl(a) / CDbl(b))
とせざるを得ないわけです。

C#だと「c = a / b;」でも0除算例外が発生するんですけど、これ、整数型のまま除算しているんですよ。これと同じ演算結果を得ようと思ったら、VBでは「/」ではなく「\」を使うことになります。いわゆる整数除算。
この場合であればVBでもちゃんと0除算例外が発生しますね。

0006.png
(クリックで拡大します)

以上より今回の結論。

  • VBではDecimal型以外0除算例外は発生しない。

  • 0除算例外を発生させたい演算はDecimal型で行う。

  • 受け側変数が整数型の場合はオーバーフロー例外が発生するのでそれを拾う。

  • 受け側変数が浮動小数点型の場合は例外が一切発生しないので、演算結果を無限大定数(Double.PositiveInfinityとか)と比較して0除算を検出する。
ってところでひとつ。

うーん、意図は納得できるけどめんどくさいなぁ。

2006年06月27日

(33) VB5,6:エラーをイベントビューアで参照したい

App.LogEvent。

でいいんです。いいんですけど。

試しにログ文章用にTextBox1つ、イベントタイプ指定用にOption3つ用意して、実行用のCommandに

Private Sub cmdExec_Click()
Dim logBuffer As String
Dim eventType As Long
logBuffer = Trim$(txtBuffer.Text)
Select Case True
Case optError.Value
eventType = vbLogEventTypeError
Case optWarning.Value
eventType = vbLogEventTypeWarning
Case optInfo.Value
eventType = vbLogEventTypeInformation
End Select
Call App.LogEvent(logBuffer, eventType)
End Sub
ってやってみたらさくっとイベントビューアに反映されたんですけども。

ハマったのは、

イベント ログは、アプリケーションがコンパイル済み .EXE として実行されているときにのみ更新されます。IDE から実行した場合は、イベントはイベント ログに書き込まれません。これは、デバッグ中にイベント ログに書き込まれるデータが過剰になるのを防ぐためです。

がわからなかったんですよ!
そんなことMSDN Libraryのどこにも書いてないんですよ!

Visual Basic から Windows NT イベント ログへの書き込み方法までたどり着いてようやく事の次第を理解した次第で。思いきりむかりとした次第で。

VB5の頃からの仕様なんだからMSDN Libraryに書いといてくれよ!

とかやつ当たってみたりもする次第で。とほほ。

2006年06月23日

(32) VB2005:ListViewに非表示列を持たせたい

検証環境 Dell PRECISION340(Pen4-2.0GHz/512MB)
Win5.1(Build 2600.xpsp_sp2_gdr.050301-1519)/VS.NET2005(8.0.50727.42(RTM.050727-4200)) & .NET Framework2.0(2.0.50727)

ソーシャルネットワーキングサイト(SNS)のmixiってところがありまして。
そこの日記で「ListViewに非表示列を持たせたいよー」とか愚痴ったら、意外にいろんな方からご意見をいただいておもしろいディスカッション(つか一方的に教えてもらいまくったというか)になりましたので、ちょっとまとめてみることにしました。



ことの発端はListViewコントロール。

簡単に表形式でデータを表示したい時に、これを .View = Details にしてよく使うんですが。
今回、主な項目だけを表示しておき、行を選択するとその明細を横に表示するような機能を作ってみたくなったんですね。

しかし表示する項目は重複要素が多く、ユニークなキーにはならないんです。
ってことは、せっかくHashTableで明細情報を保持しても、選択行からHashTableの特定のItemへひもづける方法がない、ということになります。

そこでキー引きできるようなユニークなキーをListViewの非表示列に保持しておきたいなーと思ったんですよ。

ところがどう調べても列を非表示にするプロパティもメソッドも見つからないよどーしよーと。
したっけ知恵者な方々からのナイスアイデアやらアドバイスやらが続々と。

てことで、以下サンプルを交えてのまとめです。



その1 (初級者向け)

「非表示にできないなら列幅を0にして見えなくしちゃえ」という発想ですね。
正直これが一番簡単だと思います。

実際に作ってみるとこんな感じで。

mud32-01.png

列タイトルが「1列目」「2列目」「4列目」になっているのがミソで、3列目の列幅を0にしているんですね。

mud32-02.png

表の初期値は、めんどくさいのでForm_Loadイベントの中でアルファベット大文字をキャラクタコードとループで突っ込んであります。3列目だけは区別をつけるために小文字にしてあります。

Private Sub Form1_Load( _
ByVal sender As System.Object _
, ByVal e As System.EventArgs _
) Handles MyBase.Load

'*** 初期化
ListView1.Items.Clear()
For i As Integer = &H41 To &H47
ListView1.Items.Add( _
New ListViewItem(New String() {New String(Chr(i), 3) _
, New String(Chr(i), 11) _
, New String(Chr(i + &H20), 11) _
, New String(Chr(i), 5)}))
Next

End Sub
で、好きな行をクリックすると、隠れている3列目の内容が下のLabelに表示されると。
Private Sub ListView1_SelectedIndexChanged( _
ByVal sender As System.Object _
, ByVal e As System.EventArgs _
) Handles ListView1.SelectedIndexChanged

If ListView1.SelectedItems.Count > 0 Then
Label1.Text = ListView1.SelectedItems(0).SubItems(2).Text
End If

End Sub
mud32-03.png

おお、いい感じだ。

いい感じなんですけど、これ、列見出しの2列目と4列目の間をドラッグすると、隠れた3列目が見えてきちゃうんですよ。

mud32-04.png

ああっ、なんともかっこ悪い。
見せたくないからこそ非表示にしたのであって、なんかの拍子にぞろりと隠しデータが表示されたらびっくりします。
この操作は2列目の列幅を広げたい時によくやりますので、実際に充分ありえる操作ですよね。



その2 (初級者向け改)

てことで、 .Width = 0 で非表示化した次は見出しドラッグによる列幅の変更を禁止したいということになります。

これは、ColumnWidthChangingイベントで列幅の変更を検出し、むりやりもう一度列幅を0にしてやればいい、ということがわかりました。

Private Sub ListView2_ColumnWidthChanging( _
ByVal sender As Object _
, ByVal e As System.Windows.Forms.ColumnWidthChangingEventArgs _
) Handles ListView2.ColumnWidthChanging

If e.ColumnIndex = 2 Then
e.NewWidth = 0
e.Cancel = True
End If

End Sub
実際に操作していただくとわかりますが、イベント発生ごとに抑え込んでいるなんてまったくわからないくらいにびくともしなくなります。

mud32-05.png

実用上はこれで十分ですね。

…わざわざ「実用上は」と言ったのは、実はマウスカーソルの挙動がちょっと変だからです。

2列目と4列目の見出しの間、ドラッグで2列目の幅を増減できる位置までマウスカーソルを持っていくと、カーソルが左右の矢印(左右へのスライドが可能、との意味を持つ)になります。

mud32-06.png

この場合は、2列目の幅を増減できるわけです。

で、ここから少しだけ右へマウスカーソルを移動させると、列幅0で非表示になっている列の幅の増減ができるマークに変わってしまうんですよ。

mud32-07.png

びみょーな違いですが、2列目増減の場合は左右矢印を貫く縦線が1本、3列目増減の場合は2本になります。
しかし2本線左右矢印のマウスカーソルに変わっても、列幅の変更はコードで抑え込んでいますので、実際にドラッグしても何も起こりません。

つまり、画面に表示される補助情報と実際の動作が食い違うという状態になってしまうわけです。

これはユーザにとまどいを感じさせますし、なによりここに隠し列があるのがバレバレで、これはこれでかっこ悪いす。



その3 (ちょっと中級者向け)

以上のような推敲の末、ゆっきさん(荒野の喫茶店)に教えていただいたベストリザルト。

ListViewの行に、表示させない変数を追加しちゃえ。

ListViewの行はListViewItemってクラスですので、これに表示と関係ない変数を追加した派生クラスを作ってそっちを使っちゃえばいいんだと。

Public Class ListViewItemEX
Inherits System.Windows.Forms.ListViewItem

Dim KeyData As String

Public Property Key() As String
Get
Return KeyData
End Get
Set(ByVal value As String)
KeyData = value
End Set
End Property

Public Sub New(ByVal subItems As String(), ByVal Key As String)

MyBase.New(subItems)
KeyData = Key

End Sub
End Class
こんな感じで。

InheritsでListViewItemからの派生を指定して、Newの中にMyBase.NewでListViewItemオリジナルの構造を引き継いで、ついでにString変数Keyも追加して。
Keyは内部的には変数KeyDataで保持しておいて、プロパティでGet/Setできるような出入り口を用意して。

ListViewItemの派生クラスですので、これはこのままふつーにListViewに突っ込めます。

Private Sub Form1_Load( _
ByVal sender As System.Object _
, ByVal e As System.EventArgs _
) Handles MyBase.Load

'*** 初期化
ListView1.Items.Clear()
For i As Integer = &H41 To &H47
ListView1.Items.Add( _
New ListViewItem(New String() {New String(Chr(i), 3) _
, New String(Chr(i), 11) _
, New String(Chr(i + &H20), 11) _
, New String(Chr(i), 5)}))
Next

ListView2.Items.Clear()
For i As Integer = &H41 To &H47
ListView2.Items.Add( _
New ListViewItem(New String() {New String(Chr(i), 3) _
, New String(Chr(i), 11) _
, New String(Chr(i + &H20), 11) _
, New String(Chr(i), 5)}))
Next

ListView3.Items.Clear()
For i As Integer = &H41 To &H47
Dim ItemEx As New ListViewItemEX( _
New String() {New String(Chr(i), 3) _
, New String(Chr(i), 11) _
, New String(Chr(i), 5)} _
, New String(Chr(i + &H20), 11))
ListView3.Items.Add(ItemEx)
Next

End Sub
参照する時はListView.SelectedItems(0)でいいんですけど、これはListViewItemクラスですのでいったんListViewItemEXに型変換してやってからKeyプロパティを見てやればいいということになります。
Private Sub ListView3_SelectedIndexChanged( _
ByVal sender As System.Object _
, ByVal e As System.EventArgs _
) Handles ListView3.SelectedIndexChanged

If ListView3.SelectedItems.Count > 0 Then
Label3.Text = CType(ListView3.SelectedItems(0), ListViewItemEX).Key
End If

End Sub
非表示列がそもそもなく、でも行選択すると表の中にはないデータがLabelに表示される機能が、実にすっきり実装できます。

mud32-08.png

わーい。



VBは、2005になってかなりお気楽プログラミングができるようになってきていて、オブジェクト指向プログラミングとかの理解なしに済む簡単ルールでそこそこイケるのではないかと、そっち方面をいろいろ模索していたわけですが。
.NET Frameworkから提供されるコントロールは他言語と共通で、ほしい機能は自分でクラス拡張してこなしていくのがスタンダードな手法であるなら、「簡単ルール」なんて無理だよなぁと実感しました。
出来合いのコントロールの組み合わせと裏でのチョロっとコーディングで楽しいことができるよーと言いたかったんですけどね。やはり素直に動くものを作ろうとするなら、クラスの理解と応用は避けられそうにありません。

やはり.NETになって、RADツールは死んだのかもしれません。くそぉ。



元ネタの日記ディスカッションでは、羅樹さん、ゆっきさん、[弁士]さん、Kok.Wishさん(スレッド参加順)に大変お世話になりました。どうもありがとうございました。
[弁士]さんご提供の手法は、まだちょい自分の中で整理がついていないので、今回はペンディングにさせてください。いずれきちんと応用できるようになったら、本エントリ末に追記したいと思います。

2006年05月23日

(31) VS2005:サテライトDLLを使ったVSアドインコマンドでの独自ビットマップの表示

Huizhong Long's WebLogDisplaying custom bitmap for VS add-in command button from satellite DLL

ちょっとややこしいかも…翻訳しておきたいところだなぁ。

ちなみにサテライトDLLってなぁMSDNチュートリアル : マネージ サテライト DLL の作成で詳しく。

2006年05月22日

(30) VS2005:ExtBrowser.dllの組み込み方

英語版ですが、Visual Studio 2005 Automation Samplesって奴が米国MSから提供されておりまして。

この中のUnSupportedToolで、ExtBrowser.dllってのがあるんですね。
どぅもDTE.Properties回りのAdd-Inらしいんですが。
どんなもんかイジってみたくて、さっそくダウンロードしてみました。

入手したmsiを実行すると、「(マイドキュメントフォルダ)\Microsoft Visual Studio 2005 Automation Samples」ってフォルダに25種類のサンプルが展開されます。で、目指すExtBrowser.dllは「(マイドキュメントフォルダ)\Microsoft Visual Studio 2005 Automation Samples\unsupptools\x86」にありましたありました。

unsupptoolsフォルダのreadme.txtには

To use it, run regsvr32 on the dll, ~
とありますので、レジストリ登録もしました。って、

ExtBrowser01.gif

えーだめじゃんさすがアンサポートツール(T-T)。

でも一度も実行できずにあきらめるのはくやしいので、目玉飛び出させそうになりながらあちこち検索かけてみると、米国MSDN ForumsDTE.GetObjectスレッドに解決策がありました。

  1. TOM_MUERegister ExtBrowser.dll
  2. から、ExtBrowser.zipを入手する。
  3. ExtBrowser.zipを展開して取り出したExtBrowser.AddInを「(マイドキュメントフォルダ)\Visual Studio 2005\AddIns」に置く。AddInsフォルダがなければ作る。

  4. ExtBrowser.AddInの中のタグに、ExtBrowser.dllへのフルパスを記述する。
以上。readme.txtにある「regsvr32を使ってのレジストリ登録」なんか要りません。
もうこれだけで、VS2005IDEを起動すると[ツール]メニューのトップに[ExtBrowser]がかわいく微笑んでいたりします。

実行結果はこちら。

ExtBrowser02.gif

なんか初回はフリーズ?ってくらいに時間がかかるのでお気をつけ。

(29) VS2005:DTE.Propertiesのプロパティ項目名のありか

MSDN Libraryの「ツールのオプション設定の制御(ローカルオンライン)」以下。

ついで。IDE回りでツールウィンドウなどを作成するには、「環境ウィンドウの作成と制御(ローカルオンライン)」。「オプション」ダイアログに独自のページを追加することなんかもできたりします。

プロパティ項目は「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\8.0\AutomationProperties」に格納されており、一覧することが可能です。Itemはこのキーに含まれるGUIDで指定されるパッケージ(dll)の中で実装されているので、レジストリから参照することはできません。
元ネタであるMZ-ToolsHOWTO: Getting properties from the DTE.Properties collection of Visual Studio .NET. によると、自分なりに拡張することも可能らしいです。

あと、参照。
Craig Skibo's WebLogProperties: How they work, why they exist

(28) VS2005:MSDN Library June 2006がインストールできない

VS2005がMicrosoft Visual Studio 2005 ドキュメント(MSDN Library for Visual Studio 2005)込みで提供開始されたのが2005.12.15。VS2005だけに限っていえば2005.12.14には提供開始されていたわけですが。

なんですけれども、その後2006.01.12に単体で提供されたMSDN LibraryはJanuary 2006

このEditionはVS.NET2003に自動的に組み込まれる最後のEdition、VS.NET2003・.NET Framework1.1に関する記述が含まれる最後のEditionです
なんて注釈がついておりまして、VS2005のための資料ではなかったんです。

VS2005用の更新版MSDN LibraryJune 2006は、2006.05.01によぅやっと出ました。
English版はMay 2006として2006.03.17(なぜ3月?^^;)に既に出ていましたので、お待たせしました日本の皆さんというかお待たせされましたよえぇもぅほんとにというかなんかそんな感じで。

わくわくしながらMSDNサブスクライバからダウンロードしましたよ、2,236,194,816バイトなどといぅADSL野郎にはかなり過負荷なサイズでしたけれども。
血沸き肉躍らせながらインストールしましたよ、またとんでもないインストール時間というかヘルプ結合時間がかかることを覚悟しながらも。

したっけ、「ファイルのコピー」フェイズが始まったとたんに

次のディスクを挿入してください Visual Studio 2005 DVD
ダイアログが表示されて、にっちもさっちも行かなくなってしまいました。いぇー。

もーVS2005TS、Exp、MSDN LibraryのどのDVDを入れても認識してくれない→∴(だから)そこから先に進まない(T-T)。

TSとExpを混在させていたので、あるいはMSDN Express Libraryが悪さしているのかとも思いそっちをアンインストもしてみましたけれども状況は一向に改善されず。

とりあえず困っちゃってたのは自宅マシンなんですが、仕事場のマシンでならどーよ?ってことで同じことをやってみたんですけど同じ現象が(T-T)。

どーにもお手上げで、ついにマイクロソフトサポート(有償)に「なんでですかね?」と連絡とってみました。

返ってきた答えは、「"MSDN Subscriptions Library June 2006 Edition" のインストールが正常に完了する手順に関してご案内いたします。」との前置き付きで、「この手順なら正常にインストールできるのではないか?」との提案がいくつか。
その中に、「既存のMSDN LibraryをアンインストしてJune 2006を新規インスト」ってのがありまして。

え。
June 2006って更新モジュールじゃなかったの?だって起動した時に

MSDN Library for Visual Studio 2005 - 日本語版の更新のセットアップウィザードへようこそ
って出るじゃないすか。

でもまぁ他に手もないことだし、ってVS2005回りのすべてのMSDN LibraryをアンインストしてからJune 2006を起動すると。

MSDN Library for Visual Studio 2005 - 日本語版のセットアップウィザードへようこそ
って新規インストール可能だったのかよ!

おかげさまで職場マシンには無事インストール完了ってなんか納得いきませんけれども。
自宅マシンで同じ作業をやってみて、同様に正常にインストールできることを確認しました。
以上、マイクロソフトサポートに「おかげさまでうまくいきました」と完了報告上げて一件落着としたいと思います。



MSDN Express Libraryが悪さしていたのであれば、June 2006が正常にインストールできている環境で一度アンインスト、オリジナルMSDN Libraryをインストした上で更新インストができるかどうか試す手もあります。
また、VB2005Expのisoイメージから作ったDVDでは認識してもらえませんでしたが、別途配布のmsdnixp.exeからDVD作って試してみるという手もありますね。

さすがにこれ検証1つに数時間かかるので、June 2006が正常にインストールできている環境でわざわざ試す気には今さらなれませんけれども、やるとしたらそんな感じということで。



あと、自宅のMSDN Library for VS2005からだと、どーやってもVisual Studio 連結ヘルプ コレクションのページを探し出すことができなかったんですよ。検索かけても出てこない。

が、職場のマシンで[スタート]メニューから[すべてのプログラム]-[Microsoft Visual Studio 2005]-[Microsoft Visual Studio 2005 ドキュメント]で起動すると、さくっと起動ページとして表示されるじゃありませんか。
もちろん検索かけると、トップでヒットするわけで。あれぇ?

June 2006がどうのという前に、自宅のマシンでも試してみました。

  1. 「Visual Studio 連結ヘルプ コレクション」で検索かけてヒットするかどうか確認。
    →しません。

  2. [スタート]メニューから[すべてのプログラム]-[Microsoft Visual Studio 2005]-[Microsoft Visual Studio 2005 ドキュメント]で起動して起動ページ表示されるか確認。
    →あっ、ちゃんと起動ページが「Visual Studio 連結ヘルプ コレクション 」になる!

  3. 2.の手順後、再度「Visual Studio 連結ヘルプ コレクション」で検索かけてヒットするかどうか確認。
    →だめだ、やっぱり抽出されません。
うーん。なんべんやっても、同じ結果。

ショートカットのプロパティを見比べてみると、「Microsoft Visual Studio 2005 ドキュメント」の方は

"C:\Program Files\Common Files\Microsoft Shared\Help 8\dexplore.exe" /helpcol ms-help://ms.vscc.v80 /LaunchNamedUrlTopic DefaultPage /usehelpsettings VisualStudio.8.0
「Visual Studio 2005 MSDN ライブラリ」の方は
"C:\Program Files\Common Files\Microsoft Shared\Help 8\dexplore.exe" /helpcol ms-help://MS.MSDNQTR.v80.ja /LaunchNamedUrlTopic DefaultPage
でした。

まぁ引数がそもそもms.vscc.v80とMS.MSDNQTR.v80.jaで大違いなので、動作が違ったって不思議はないんですが。なんでこんな2通りの動作を用意したのかなーと、そっちの方が不思議だったりします。



ついでの愚痴。

今回提供されたJune 2006、

インストール後に「June 2006」だと確認できる方法がありません。

とりあえず無理無理調べるなら、「C:\Program Files\MSDN\MSDN8.0\1041\eula.txt」の作成日時が「2006.02.24 3:52:53」だとか「C:\Program Files\MSDN\MSDN8.0\1041\readme.htm」の作成日時が「2006.03.18 12:11:33」だとかならJune 2006版だ、みたいな感じで確認するしかないっぽいです。

VS2005添付のMSDN Library for VS2005だと、「C:\Program Files\MSDN\MSDN8.0\1041\eula.txt」の作成日時が「2005.11.24 0:16:37」、「C:\Program Files\MSDN\MSDN8.0\1041\readme.htm」の作成日時が「2005.11.30 0:00:43」ですので、まぁとりあえず明確に違いますと。なんとかこれで確認できますと。

嫌な確認方法だなぁ。

どのページを更新したのかの情報もないので、「このページの記述がこうなっているからJune 2006版だ」とかの確認もできませんしね。

アップデートしたのかどうなのか確認しにくい、ってのはかなり不便なんですけどねぇ…なんとかならんもんでしょうかこのへん。

(27) VS2005:IDEのショートカット情報はどのように管理されているか

検証環境 Dell PRECISION340(Pen4-2.0GHz/512MB)
Win5.1(Build 2600.xpsp_sp2_gdr.050301-1519)/VS.NET2005(8.0.50727.42(RTM.050727-4200)) & .NET Framework2.0(2.0.50727)

えー、ちょっと気になったので、VS2005 IDEのショートカット情報の仕組みについて調査結果メモ。



まず、[ツール]-[オプション]で表示される「オプション」ダイアログ-[環境]-[キーボード]ページの[次の追加キーボードマップスキームを適用:]に表示される選択肢。

「(既定)」以外の選択肢は、「(VSフォルダ*1)\Common7\IDE」直下に格納されている.vskファイルの「拡張子抜きファイル名」がそのまま表示される。
.vskファイルは、それぞれのキーボードマップスキーム情報の実体。
「(既定)」はデータファイルとしては用意されておらず、システム内に埋め込まれているようだ。

どのスキームが選択されているかは、「HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Keyboard」キーの「SchemeName」値にフルパスで格納される(例:「C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\Brief.vsk」)。
ただし「(既定)」の場合は「SchemeName」値はそのままで、値のデータが空文字列となる。

この選択スキームをDTE側から確認する場合は、

Dim props As EnvDTE.Properties = DTE.Properties("Environment", "Keyboard")
Dim prop As EnvDTE.Property = props.Item("SchemeName")
とした時の prop.Value で取得できる。

逆にスキームを設定したい場合は、

prop.Value = "Brief"
prop.Let_Value("Brief")
の2種類の書き方がある。
なんとなく2種類あるってのがキモチ悪いが、実際にやってみるとホントにどちらからでも設定可能。使い分けか経緯がわからないと素直に納得しにくいところではある。

この手法はMSDN Library for VS2005の「方法 : コマンドの既存のショートカット キーを保持する(ローカルオンライン)」および「Command.Bindings プロパティ(ローカルオンライン)」で確認できる。
ただし「Command.Bindings プロパティ」の方のサンプルプログラムではスキーム名を引っ張り出すアイテム名を「Scheme」としているが、そんなアイテム名はない。「方法 : コマンドの既存のショートカット キーを保持する」で説明されているアイテム名「SchemeName」が正解。

とはいうものの、「方法 : コマンドの既存のショートカット キーを保持する」の記述がすべて正しいわけでもない。prop.Valueを「<FileName.vsk>」と、いかにも拡張子まで込みでファイル名を保持しているように書かれているが、実際に保持されるのは拡張子抜き。
「Brief.vsk」であれば「Brief」と保持されている。

では、実データファイルの存在しない「(既定)」の場合はどう保持されるのか?と調べてみると、「(既定)」と保持されていた。まんまじゃん。
というよりはむしろ、日本語版の表記そのもので内部保持しているところに問題がある。この点でVSマクロはローカル言語版でしか動作しなくなってしまうからだ。
確認は取っていないがオリジナルの英語版で「(既定)」になっていることはあり得ないだろう。「(Default)」かなんかになっているはずで、VSマクロをどのローカル言語版なのかに依存せずに動作させたいなら、そのVSのローカル言語を取得してその値によって振り分けてやらなければならないことになる。って、ローカル言語の取得ってどうやるんだろう。



さて、今度はショートカットのキーカスタマイズについて。
インストール時に提供される出来合いのスキームは上記の通りだが、独自にキー割り当てを変更した場合はどう保持されるのか。

VS2005はWin2000以降での動作を前提としているので、ログインするユーザごとに異なる環境を保持する。キー割り当ても例外ではなく、ログインするユーザごとにカスタマイズの状態を保持することとなる。

これは、「C:\Documents and Settings\(UserName)\Application Data\Microsoft\VisualStudio\8.0」直下の「Current.vsk」に保持される。

もう少し具体的に言うと。

  1. まず、「オプション」ダイアログ-[環境]-[キーボード]ページの[次の追加キーボードマップスキームを適用:]で選択されたスキームを下敷きとする。

  2. 次に、独自のキー割り当てが、「Current.vsk」と同じく「C:\Documents and Settings\(UserName)\Application Data\Microsoft\VisualStudio\8.0」直下に作成される「User.vsk」に格納される(のではないかと推測している)。

  3. で、下敷きのスキームに「User.vsk」のデータを混ぜ合わせて「Current.vsk」を作成する。実際に使用されるキー割り当ては、この「Current.vsk」だということになる。
独自のキー割り当てを「User.vsk」に保持させた後下敷きスキームを変更した場合、バッティングする部分がどちら優先になるのかは未確認。
下敷きスキームに割り当たっているキーを取り消して別のコマンドに独自に割り当てた場合、「User.vsk」には取り消し情報と割り当て情報の両方を持たなければならず、これは別の下敷きスキームでは取り消し情報が合致しないので、「User.vsk」を丸ごと無視しなければならないのではないかと推測はしているのだが。

ちなみに、「User.vsk」を削除してもVS IDEの動作に影響はない。
また、「Default.dsk」というファイルも「Current.vsk」「User.vsk」と同時に生成されるが、何に使用しているのかよくわからない。
これら3つのファイルはインストール時ではなく、ログインしているユーザー単位にVS IDEの初回起動時に生成される。ので、VS2005インストール後に作成したユーザーからでも、そのマシンにインストールされているVS2005を使用可能。もちろんショートカット回りだけではなくさまざまな初期値が用意されるのだろうが、現時点ではそちらの方までは未検証。

というわけで「Current.vsk」は原稿のショートカットキー割り当て情報のフルセットということになるのだが、では、これはインストール時に格納されるスキームファイルとどう違うのか。

実は何も変わらない。
実際、「Current.vsk」を「(VSフォルダ)\Common7\IDE」にコピーして「Salvage.vsk」に変更してみると、きちんと[次の追加キーボードマップスキームを適用:]リストボックスに「Salvage」の選択肢が追加される。「Salvage」を選択してみると、「Current.vsk」作成時に埋め込んでおいた独自のキー割り当てまでが再現できる。

VS2005には独自のキーボードマップスキームを新規スキームセットとして保存する機能はないが、「Current.vsk」に独自のファイル名(選択肢名)をつけて「(VSフォルダ)\Common7\IDE」にコピーする機能を作れば、独自スキームの選択肢作成機能になる。



独自のキー割り当てから独自のスキーム選択肢までの作成機能を考えた時に、気をつけなければならないこと。

[次の追加キーボードマップスキームを適用:]が「(既定)」に設定されていると、VSマクロやアドインから独自のキー割り当てをしようとしてもなぜかエラーになってしまう。.vskファイルとして用意されているいずれかの選択肢を設定してから独自のキー割り当て機能に移行する必要がある。

しかし現実には、「(既定)」を下敷きにしてキー割り当てを拡張する人が圧倒的多数だろうと推測できるので、やはり「(既定)」と同じキー割り当て情報を持つスキームファイルが必要だろう。
となると、一度「(既定)」の状態で作成された「Current.vsk」を別名でコピーして下敷きにするしかない。

となると、

  1. 現行の「Current.vsk」とprops.Item("SchemeName")を待避。

  2. props.Item("SchemeName")を「(既定)」に変更。

  3. 2.の結果できあがった「Current.vsk」を、「(既定)」と同内容のスキームファイルとして待避。

  4. 1.で待避した「Current.vsk」とprops.Item("SchemeName")を元に戻す。

  5. これから新しく作るスキーム名を入力させる。

  6. 3.で待避した「Current.vsk」を5.で入力させたスキーム名に変更し、「(VSフォルダ)\Common7\IDE」にコピー。

  7. props.Item("SchemeName")を5.で入力させたスキーム名に変更。

  8. 独自のキー割り当ての設定。

  9. 8.の結果できあがった「Current.vsk」を、もう一度5.で入力させたスキーム名に変更し、「(VSフォルダ)\Common7\IDE」に上書きコピー。

  10. props.Item("SchemeName")をもう一度5.で入力させたスキーム名に変更。
のような手順が必要か。

実装すべき事柄が決まれば、あとは演出の問題だけ。
とはいうものの、キー割り当て回りはセットしたとたんにファイルにまで書き出しているようなので、どのタイミングで掃き出されたという前提で次の動作をしていいのか、ファイルがクローズされていると当て込んでリネームやコピーを行っていいかはちょっとびみょー。

このへんのからくり自体明確に説明されている資料が存在していないので、当然タイムチャートも存在しないし保証もされない。
タイミングの可否状態をあぶり出す検証作業を細かいレベルでやっておかないと、マシンによって動作する/しないなんて事態にもなり得る。

ここまででも私の頭にとっては相当ややこしい(;-;)。



*1VSフォルダ:VS IDE関係のファイルが格納されているフォルダ。VS IDEの実体(devenv.exe)が格納されているのが目印。標準では「C:\Program Files\Microsoft Visual Studio 8」。

2006年05月19日

(26) VS2005:マクロ実行バルーンを表示させない方法

VSマクロを実行させると、システムトレイにカセットテープアイコンが表示され、実行中ずっとぐるぐる回るんですね。
VS IDE側(マクロエクスプローラなど)から実行させると、VS IDEのステータスバー右隅でも同じアイコンがぐるぐる回るわけです。

それだけならなかなか愛らしいような気もするんですが、ときどきシステムトレイのカセットテープから、「このマクロを止めたい場合にはここをクリックしてください」ってバルーンヘルプが出ることがあるんです。

私のところでは、2台ある作業用マシンのうち1台では出、1台では出なかったりするんですが。で、出ると出ないの違いが、Windowsのタスクバーを固定にするか自動的に隠すかの設定の違いのような気もするんですが、別に検証したわけではないので断言は避けておきます。

つかそこが本題ではなく。

このマクロバルーン、どーいうわけだかマクロ愛好家の皆さんの間ではあまり評判がよろしくないようで。
まぁマクロそのもののデバッグならともかく、それを拡張機能として組み込んだ状態のVS IDEを使ってなんらかの開発作業をしている時に、いちいちIDE内部の動作についての報告なんか受けたくないという気持ちはわかります。集中がそがれちゃいますし、間違ってクリックしちゃうととんでもないところでマクロが止まったりしますので、不便っちゃ不便ですよね。

てことで、そのへんお怒りの方々がバルーン表示をさせない方法を探し出してます。

HKEY_CURRENT_USER\Software\Microsoft\VisualStudio
\8.0\DontShowMacrosBalloon ← 「6」
ってことでひとつ。

私自身は試していないので、メモレベルの情報です。ご注意ください。

元ネタはCraig Skibo's WebLogStopping the “Click here balloon”から。

2006年04月30日

(25) VS2005:マクロサンプルが存在しない

Visual Studio 2005に搭載されているVisual Studioマクロ。
こいつでしばらく遊んでみようと、マクロエクスプローラから"Samples"ノードを開いてみようとしたわけです。

したっけ、

以下の理由により、マクロ プロジェクト '' を読み込めません :

'(マイドキュメントのPath)\Visual Studio 2005\Projects\VSMacros80\Samples\Samples.vsmacros' は無効か、またはアクセス不可能なマクロ プロジェクト ファイルです。
ってえええええ(T-T)。

えーと、どぅも私の環境では、VSマクロのサンプルがうまくコピーされないようです。

VSのバグなのかなぁという気もしますが、VB/C#のExpress Editionも一緒にインストールしている環境ですので、あるいはそちらと混在させたが故の現象なのかもしれません。

ですからことさら「不具合だバグだ」と騒ぎ立てるつもりはありませんが、だからといってSamples抜きの環境のままで調査や学習をしていくのもムダに大変です。

ここは一発、手作業でSamplesを参照できる環境を作ってみましょう。



さて、Samplesは「いつ」作成されるのか。
実は、インストール時に用意されるわけではないようです。

上記のエラーメッセージでは「(マイドキュメントのPath)\Visual Studio 2005\Projects\」フォルダの下層にある「VSMacros80\Samples\」から読み取ろうとしていますが、VSのインストール直後にエクスプローラで見てみると、そんなフォルダは存在していません。
マクロエクスプローラを初めて表示した際に作成されるようなんですね。

つことは、本来このタイミングでSamplesフォルダにサンプルファイルがコピーされるはず。
またマイドキュメントフォルダ以降に生成されるということは、ログオンするユーザーごとに別々のタイミングで生成されるはず。
つことは、コピーされる元ネタは別の位置に保存されているはず。

という推測が成り立ちますというか推測してみました。

もひとつ。

コピーされるファイルは、具体的になんなのか。

私の環境にはVS2003も併せてインストールしてあり、こちらのマクロエクスプローラからはサンプルのノードが正常に表示されていますので、これを手がかりにしてみましょう。

VS2003の個人データは「(マイドキュメントのPath)\Visual Studio Projects」以下にできます。で、目指すSamplesフォルダは「(マイドキュメントのPath)\Visual Studio Projects\VSMacros71\Samples」と、ほぼVS2005と同じ階層構造になっています。このへんの管理のしかたはあまり変わっていないようですので、中のファイル群も参考にできる可能性大です。

…実際に「(マイドキュメントのPath)\Visual Studio Projects\VSMacros71\Samples」に格納されているファイルはSamples.vsmacrosひとつだけでした。

「コメントを追加→保存」などして試してみると、Samples.vsmacrosそのものの内容が変化しますので、どうもこれ自体が実体のようですね。
VSのソリューション/プロジェクトとは異なり、VSマクロはまとめてひとつの.vsmacrosファイルにバイナリで保存されるようです。

ふむ。では、VS2003のSamples.vsmacrosをVS2005用のフォルダにコピーしてしまえば。

っていやいや、上記の推測では「どこかにVS2005用Samples.vsmacrosのコピー元ネタが存在しているのではないか?」ですので、そいつを探してみるのが先でしょう。
第一VS2003と2005でVSマクロがバイナリレベルで完全互換があるとは限らないので、安易なバージョン間移行は危なくってしょうがありません。



探すこと自体はそんなに手間ではありません。VS2005のインストールフォルダ以下をざっくり検索してしまえばいいんですね。

もっともふつーにVS2005をインストールすると、そのファイル群はデフォルト指定で

  • (Program FilesのPath)\Common Files\Microsoft Shared

  • (Program FilesのPath)\Microsoft Visual Studio 8

  • (Program FilesのPath)\Microsoft Visual Studio .NET 2005

  • (Program FilesのPath)\MSDN\MSDN8.0

  • (Program FilesのPath)\Microsoft SQL Server
あたりにツッコまれます。
探し漏れがあるとムダな推論を重ねることになりそうですので、ここはひとつ時間はかかりますが「C:\Program Files\」以下を全部対象にしてしまいます。
検索に使用するファイル名は「*.vsmacros」、拡張子だけ指定してやればいいです。別拡張子で雛形として用意とか.cabファイルに圧縮格納されている可能性もあるんですが、まぁそれは「*.vsmacros」で見つからなかった時に考えてみようかと。
少なくとも「.vsmacros」なんて拡張子、他の用途のファイルとカブることはまずないでしょうから、誤ヒットの可能性が少ないのは探しやすくてありがたいですね。

探してみました。
えーと、2つ見つかったんですけど。デフォルト指定で

  1. (Program FilesのPath)\Microsoft Visual Studio .NET 2005\Common7\IDE

  2. (Program FilesのPath)\Microsoft Visual Studio .NET 2005\Common7\IDE\1041
1.の方がファイルサイズがでかいんですけど、2.の方が日付が新しく、1041フォルダに入っているってことは日本語対応版?とも思えますので、今回は2.にあるsamples.vsmacrosを(マイドキュメントのPath)\Visual Studio 2005\Projects\VSMacros80\Samplesにコピーしてみました。

でVS2005起動→マクロエクスプローラ表示→Samplesノード展開。

おおっ、なんかいろいろサンプルが表示されているぜソースもエディタで表示されるぜ!

自動でSamplesフォルダにコピーされないのがいまいち気にくわないところではありますが、まぁこれで十分実用になりますので今回はよしとしましょうか。

2006年04月29日

(24) VS2005:インストーラで「無効なディスクが挿入されました」

VS2005セットアップのメンテナンスモードで「修復/再インストール」を実行すると、Disc1の挿入を促す「ディスクの挿入」ダイアログが表示される。

msdnDVDなどからインストールする場合の指定パスは「(ドライブレター):\vs\」だが、ここでうっかり「(ドライブレター):\」などとすると、「無効なディスクが挿入されました。Microsoft Visual Studio 2005 Team Suite - JPN Disc 1 を挿入してください。」メッセージボックスの無限ループになってしまう。

この無限ループから脱出するには、誤って指定してしまったドライブからDVDを抜いて[OK]。

HDDドライブを指定した時などはメッセージボックスは表示されず、無反応。
CD/DVDドライブの時にのみ発生。試してはいないが、それ以外のリムーバブルメディアの場合も同様か?

気づけばなんということはないが、気づかないともータスクマネージャから強制終了するしかないというカメイワTipsといぅことでひとつ。

※カメイワ:
「ゼルダの伝説/神々のトライフォース」プレイ時に、3本の杭を順番に叩くだけの簡単な亀岩のイベントで私が3日もハマったことに由来。
以来個人的に「気づけば簡単なのに、気づかないために猛烈にドツボにハマる状態」を「カメイワ」と呼ぶことに決定。
個人的な表現には、他に「ナガサキ」、「トレロカモミロ」などがある。

(23) Oralce:PL/SQLの改行コードはVBLf

Procedure/FunctionのVBからの生成は、素直にCREATE/UPDATE - PROCEDURE/FUNCTIONをDbExecuteSQL(VB6 & OO4O)でブン投げればOK。
ただしPL/SQLコードはVBCrLfではなくVBLfで改行しないとコンパイルエラー発生。OracleではCRを処理できないらしい。

2005年06月20日

(22) VB6:FlexGrid.NET2.0Jの表示専用行選択

たぶん標準のDataGridでは効かせにくい融通なんかもあるので、中規模以上の基幹系受注生産タイプ旧来型開発では、やはりActiveReportsやFlexGridを組み込むケースが多いと思うんです。

ちなみに私の知る限りもっとも融通の利くGridコントロールはSpreadなんですが、たぶんこれを使わないと満たせないような仕様は、エンドユーザにひきずられて機能設計の時点ですでに泥沼になっている可能性が高いので、「使ってる」とわかった時点でそのプロジェクトからは逃げ腰になったりします。

UIのレスポンスまで考えるとSpreadは必ずしもベストの選択肢ではないので、あえてSpreadにしている場合はなんらかのマイナスファクターがある場合が経験上多かったもので…。

それはさておき、むちゃくちゃ守備範囲が狭いんだけれども、自分としてはちょいちょい思い出す必要に迫られるので、ここにメモ。

  • FlexGrid.NET2.0Jで

  • 表示専用で使用し

  • 行選択の必要があり

  • マウスクリックで行選択してもクリックセルにフォーカスを当てないようにするには
FocusRect = None

いゃ実際にはフォーカス当たってんですけども、見えなきゃわかんないべといぅポリシーの元に。

いつも「フォーカスを当てない方法ってどぅすんだっけー」と慌てるんですが、この考えだと次に「じゃあフォーカスをどこに置くんだ」といぅことを考えねばならず、さらに「フォーカスをよそに持ってった状態でカーソルキーで選択行を移動させたい場合はどぅ制御すんだ」といぅことを考えねばならず、やってできないことはないんでしょぅけれどもやたら力技でフォーカスやらキー押下やらを制御しまくるといぅ本筋と全然関係ない部分にマニアックな対応を行わなければならず。

だったらフォーカスを見せなきゃいいじゃんといぅことで。

2005年05月02日

(21) VB2003:プロジェクトを実行しようとしているときにエラーが発生しました

検証環境 自作ATX(PenIII1.2GHz/GA-6VTXE/512MB)
WinXPPro(2002)SP2/VS.NET2003(7.1.3091) & .NET Framework1.1(1.1.4322SP1)/MSDN-Lib Oct,2004
プロジェクトを実行しようとしているときにエラーが発生しました
デバッグを開始できません.

上記はIDE環境からデバッグ実行しようとした時のエラーメッセージの前半。
EXEを直接実行した場合はそのEXEファイルのフルパスが表示された上で、

このアプリケーションの構成が正しくないため、アプリケーションを開始できませんでした。
アプリケーションを再度インストールすることにより問題が解決する場合があります。

で、どぅすりゃいいかってぇと、

App.configのencodingプロパティを「Unicode(UTF-8)」にする。

この現象が発生するのは、「プロジェクトにApp.configがUTF-8以外の文字コードで存在」しており、「実行するEXE用にLunaインターフェイスを適用するmanifestファイルがUTF-8の文字コードで存在」している場合です。 manifestファイルがなかったりApp.configがなかったりする場合にはこの現象は発生しません。

最初、原因がわからなくてかなりあせりました。
自宅のメインマシンで発生したんですが、どうしてApp.configがShift-JISで生成されたのかがいまいちわかっていません。
会社のマシンで検証したら、デフォルトUTF-8の文字コードでApp.configが生成されたので、わざわざ手動でShift-JISにエンコード切り替えないとこの現象は発生しませんでしたし。

まぁ、「こんなエラーが出たら原因としてそのへんも疑ってみよう」ってことでひとつ。



05.05.06付記

単純に、App.configの中に文法エラーがあってもこのエラーは出ます。
どぅも、構成ファイルを正常に読み込めなかった時全般で発生するエラーみたいですね。
心当たりを片っ端から当たってみるしかない、対象範囲の広いちょっととほほなエラーといぅことでひとつ。

2005年03月08日

(20) VS2003:IDEの操作性あれこれ

検証環境 自作ATX(PenIII1.2GHz/GA-6VTXE/512MB)
WinXPPro(2002)SP2/VS.NET2003(7.1.3091) & .NET Framework1.1(1.1.4322SP1)/MSDN-Lib Oct,2004

コードエディタ上ブレークポイント(F9)はコマンド単位で背景色が変わるのに対し、ブックマーク(Ctrl+K,Ctrl+K)は行の左側に水色の四角が付きます。

もちろん使用者の好みの問題なんですが、私としてはブックマークも行単位の背景色変更で表示されたいわけです。

が、[オプション]-[環境]-[フォントおよび色]では特に行/マージンの表示振り分け設定は見当たりません。
ブックマークもブレークポイントと同じように、背景色-文字色の組み合わせでサンプル表示されます。

そーいぇば、旧VBの時には行/マージンの表示振り分け設定みたいな項目があったが、行単位で表示と設定しても、マージンを非表示にしないと有効にならなかったなー、などと思い出し。

.NET IDEでも同様かと推測、[オプション]-[テキストエディタ]-[全般]-[表示]で「マージン」のチェックをはずしてましみた。

…アウトラインの[+][-]が非表示になったよorz。

正解は、同じダイアログの「インジケータマージン」のチェックをOffでした。



ちなみに。

現在の私の仕事の一部に「中国の協力会社へソースレベルで指示を出したり」ってのがあるので、コードエディタに行番号も表示しています。
どぅしても、「****.vbのxxx行目からのSQL文を見直してくださーい」とか言わなきゃならない場合があるので。

これは、[オプション]-[テキストエディタ]-[すべての言語]-[全般]-[表示]から「行番号」にチェック。

さらにちなみに。

2ストロークデフォルトになったのがちょっと痛いけど、やはりショートカットキーは楽ちんなので多用しているんですが。

ウチの若い者の中には、カット&ペーストまでマウスでこなすつわものがいますが、ユーザならともかく開発者としてはいかがなものか。
が、実際それでも私がキーボードから操作するのと同等以上のスピードだったり。
Oracleのインストール時など、ダイアログが表示される前に、ボタンが表示されるはずの場所を先にクリックして待つ(表示された途端にクリックされた動作が始まる)ほどのマウス捌きを見ていると、すでに私は旧世代なのか!?とたまげてみたりもするんですよね。

それはともかく、マイフェイバレットショートカットキー。

Ctrl+ASZXCVP基本過ぎなので省略
F1ダイナミックヘルプ
F5プログラムの開始
F9ブレークポイントのOn/Off
Shift+Ctrl+F9ブレークポイント全Off
F10コマンド1つ実行(実行中のプロシージャかその親)
F11コマンド1つ実行(子プロシージャ突入)
Shift+F11親プロシージャまで一気に実行
Ctrl+「-」直前のカーソル位置へ戻る
Shift+Ctrl+「-」戻ったカーソル位置へもう一度進む
Ctrl+L行削除
Ctrl+K,Ctrl+KブックマークのOn/Off
Ctrl+K,Ctrl+Lブックマークの全Off
Ctrl+K,Ctrl+C選択行のコメント化
Ctrl+K,Ctrl+U選択行のコメント解除
Ctrl+M,Ctrl+MアウトラインのOn/Off
Ctrl+M,Ctrl+H選択行のアウトライン化
Ctrl+M,Ctrl+U選択行のアウトライン解除
Shift+Ctrl+Enter全画面表示のOn/Off
Shift+Ctrl+Bソリューションのビルド
Ctrl+↑↓カーソル位置を変えずにスクロール
Ctrl+RollUp/Down表示画面をスクロールせずにカーソルを最上行/最下行へ
Alt+↑↓プロシージャの先頭/最後へ(MZ)
Shift+Ctrl+Hプロシージャのヘッダコメント挿入(MZ)

こんなところかなー。

「(MZ)」とあるのは、IDE標準ではなくMZ-TOOLSで提供されていて、自力でショートカットキーに割り当てて使っている機能。
特に「Alt+↑↓」は旧VBにあって重宝していた操作だったので私にとっては必須だったり。

「Ctrl+M,Ctrl+M」は、カーソルがどこにあるかきちんと把握していないととんでもない深さでたたまれるので、実はちょっとつらい。
プロシージャとプロシージャの間にカーソルがある時にうっかりたたむと、Class/Module/Regionのレベルでたたまれてしまい、あわててもう一度開いてもカーソルはその先頭行へ。
数千行あるソースでこれをやっちゃうと、元の場所へたどり着くまでが一苦労なんですよね。

コンテキスト(右クリック)メニューの[定義へ移動]で子プロシージャへよく飛ぶんですが、これの「元の場所へ戻る」がありません。旧VBにはあったし、.NET IDEでもツールバーにはあるんですが(ちょっと飛び位置が違いますが)。
って、コンテキストメニューのカスタマイズの方法がわかりません(T-T)。できないのかなぁ…

とか嘆いていたら、The Code ProjectGo Back Add-in for VS.NET 2003ってのを発見。
コンテキストメニュー(→クリックメニュー)に[Previos Location]ってのが追加されて、[定義へ移動]とセットの操作で自由に参照元と参照先を行ったり来たり。
[Choose Location]って項目もあって、こちらは飛び元のスタックを一覧表示・好きな位置を選択できるナイスっぷり。
Formのコード上で操作した場合にFormエディタウィンドウへ切り替わってしまぅのがちょっとあれですが、まぁそこらへんは今後の改善を祈って。

そいえば、私はヘルプを「外部ヘルプ」にしています。
F1でカーソル/フォーカス位置状況に合わせてなかなかいいヒット率で知りたい情報へ飛ぶので重宝しているんですが、IDE側に出てくるダイナミックヘルプツールウィンドウは邪魔なので要らないんですよ。
自宅の環境では出てこないようにできているので何らかの設定方法があったはずなんですが、どこだったかどーしても思い出せません。
仕事場の環境では、このウィンドウが何かと出てきて、もーいやだーって感じです。
Office Assistant以来のいらいらさせられっぷりなんだよなー。

2005年02月10日

(19) VB2003:Button.PerformClick

検証環境 自作ATX(PenIII1.2GHz/GA-6VTXE/512MB)
WinXPPro(2002)SP2/VS.NET2003(7.1.3091) & .NET Framework1.1(1.1.4322SP1)/MSDN-Lib Oct,2004

旧VBの時。

デスマーチになってやっつけ仕事になると、とりあえずButtonのClickイベントに実コード書いて、後から同じ機能を別のトリガで(たとえばキー操作から)使いたい場合に、Clickイベントを直接Callしちゃうなんてのはよくある話だったんですが。

VB.NETになったらClickイベントの引数が妙にめんどくさくなった(てゅうか.NET標準に合わせたてゅうか)ので、この手法は使えないなぁとあきらめていたんです。

PerformClickメソッドなんてのがあったのね。

知りませんでした…orz

2005年02月09日

(18) VB2003:Tabキーを拾えるTextBoxコントロールその後

検証環境 自作ATX(PenIII1.2GHz/GA-6VTXE/512MB)
WinXPPro(2002)SP2/VS.NET2003(7.1.3091) & .NET Framework1.1(1.1.4322SP1)/MSDN-Lib Oct,2004

泥Tips(6)の手法でおっけー、とか思っていたら、IMessageFilter.PreFilterMessageでWM_KEYDOWNメッセージを拾ってる人を発見しました。

Message.WParamでキーコードを取得して、Tabキー(&H09)だったらモジュールレベルのスコープを持つフラグ変数を立てておいて、TextBoxのLeaveイベントの中でそのフラグを参照してTab押下によるフォーカス移動かどぅかを判断してんですわ。

その手があったかー、と思うより先に、Formに来るメッセージを味噌もくそも一緒くたに処理しよぅとするPreFilterMessageの存在にものすごく疑問が。

確かにmsdnLibraryでは「このメソッドを使用すると、メッセージがディスパッチされる前に行う必要のあるコード作業も実行できます。」とか記述されてて、ButtonのClickコマンドを横取りするような例を挙げちゃっているわけで。
これを鵜呑みにすると、確かにTextBoxのキー押下も横取りできる、って発想はアリだよなぁ。

でも、コード間の脈絡がまったくなくなってしまぅので、フラグ変数名でコード内を検索するかデバッグトレースでもしない限り、操作から発生するイベント及びそこからCallされるプロシージャの流れと無関係なところで動作が制御されていることがわからなくなるんですよね。

これはデバッグ/メンテナンス時にかなりなツラさだと思ぅわけですよ。

C++で考えれば、ふつーコントロールへ流れてくるメッセージはコントロールの中でつかまえて処理するよなぁ。
Formで一律してメッセージをつかまえるってのはよっぽどのこと、てゅうか客先のわがまま要求に負けて泣く泣くへんてこな動作を作りこんだ時くらいしか覚えがありません。

まぁmsdnLibraryの例はわかりやすく説明したいがためにあんまり適切ではない例をつい出しちゃった、くらいに解釈しておいたとしても。
そもそPreFilterMessageって、何を想定して用意されたメソッドなんでしょぅ。

むちゃくちゃ泥臭い使い方しか思いつきませんよ?

2005年01月22日

(17) VB2003:Tabキーを拾えるTextBoxコントロールを作ってみる

検証環境 自作ATX(PenIII1.2GHz/GA-6VTXE/512MB)
WinXPPro(2002)SP2/VS.NET2003(7.1.3091) & .NET Framework1.1(1.1.4322SP1)/MSDN-Lib Oct,2004

前提として。

  • TextBoxコントロールのデフォルトでは、Tabキーは次のTabIndexを持つコントロールへのフォーカスの移動。

  • 旧VBではKeyDownイベントプロシージャが優先して評価され、これを抜けてからデフォルトの動作となっていました。
    つまりデフォルトの動作をツブして独自の動作をさせることができたわけです。

  • VB.NETではTabキーや矢印キーの押下ではKeyDownイベントが発生しません。
    コントロール内部でフックされて、こちらでコーディングしたプロシージャまでメッセージが届かないんですね。
って状況下で、Tabキー押下時のアクションを自前で用意したい場合。

ふつーに考えれば、TextBoxから、Tabキー押下時のイベントをこっち側に持ってくるような派生クラス作ってしまえばいいんですけれども。

クラスってWindows Formデザイナの管理の対象外なもんで、せっかく作っても[ツールボックス]-[マイユーザーコントロール]に表示されないんですよね。
コードでインスタンス作ってFormに割り当てて表示位置とか属性とか決めて、ってやらなきゃならないんですよ。つまり、Windows Formエディタの管理外となりますので、大変作りにくい状況になってしまぅわけです。

かといってユーザーコントロールとして作るとツールボックスには表示されるものの、Control型のオブジェクトになってしまぅので、TextBox特有のプロパティなんかを明示的に公開するよぅに作り込まなければならないのも手間ですし、デザイン時にそこだけすでに実行されているのも個人的には大変気に食いません。

もちろん高度に特殊なコントロールを作るのなら上記の手間やら動作やらもわかった上で積極的に使っていくつもりはありますが、たかがTextBoxにTabをスルーさせるためだけにユーザーコントロール、ってのもちょっとおもしろくないよぅな気がします。

てことで、[ツールボックス]に表示される派生クラスの作り方。

  1. 「新しい項目の追加」で「ユーザーコントロール」を追加します。

    いゃいいから。「ユーザーコントロール」でいいから。
    ファイル名は「U_Test.vb」とでもしてみます。
    この時点で、[マイユーザーコントロール]には「U_Test」コントロールが表示されます。

  2. U_Test.vbのコードエディタを表示させます。

  3. 「Inherits System.Windows.Forms.UserControl」の「UserControl」を「TextBox」に書き換えます。

    書き換えたとたんに、ソリューションエクスプローラに表示されている「U_Test.vb」のアイコンがユーザーコントロールのではなくコンポーネントクラスのになります。

    でも[ツールボックス]-[マイユーザーコントロール]の中ではユーザーコントロールアイコンのまま表示されてます。

    で、この時点で「U_Test.vb」の[デザイン]ウィンドウを開いていたら、フチなしFormのようなデザイン領域の表示が消えて「クラスにコンポーネント追加するには、~」といぅまか不思議な文章が表示されますが気にしないでけっこぅです。

  4. 今回はTabキーをKeyDownイベントで取り扱えるよぅにしたいわけですから、IsInputKeyメソッドをオーバーライドするコードを書いてしまいます。

    書く位置はU_Testクラスの内側、「Windowsフォームデザイナで生成されたコード」の下。
    Protected Overrides Function IsInputKey( _
    ByVal keyData As System.Windows.Forms.Keys) As Boolean
    If (keyData = Keys.Tab + Keys.Shift) _
    Or (keyData = Keys.Tab) Then
    Return True
    Else
    Return MyBase.IsInputKey(keyData)
    End If
    End Function
    こんな感じで。

  5. 一度ビルドします。

    ビルドしないと、作成したユーザーコントロールは使えないので。
    [マイユーザーコントロール]には表示されているんだからってドラッグとかしてみると、「ユーザーコントロール'*****.U_Test'を読み込めませんでした。~」って赤バッテンMessegeBoxが表示されます。
以上で、ユーザーコントロールと同様に[ツールボックス]からドラッグできる派生クラスのできあがりです。

ちなみに、こーやって作った派生クラスファイルを他のプロジェクトで使用しようとして「既存項目の追加」で読み込んでも、[ツールボックス]には表示されません。

この場合は、読み込んだU_Test.vbをコードエディタで開き、上記(3)で書き換えた 「Inherits System.Windows.Forms.TextBox」の「TextBox」を「UserControl」に書き戻して、デザイナでも開きます。

これで[ツールボックス]に表示されますので、再度「UserControl」を「TextBox」に書き戻します。

なんだか単にデザイナをだましているだけのよぅな気もしますし、2005とかで通用する手段かどぅかはわからないわけなんですが。
今んとこは割と重宝しています。

(16) VS.NETのHelpにサードパーティのHelpを組み込む。現実として。

検証環境 自作ATX(PenIII1.2GHz/GA-6VTXE/512MB)
WinXPPro(2002)SP2/VS.NET2003(7.1.3091) & .NET Framework1.1(1.1.4322SP1)/MSDN-Lib Oct,2004

私は今VS.NET2003にOracle9.1とCrystalReports10を組み込んでプログラムを作ったりする仕事をしているわけなんですが。

OracleとCRのHelpが.NETのHelpと連動しなくてもーどーにもなりません。
どちらも.HxS(MS HTML HELP 2.0のデータファイル)とかは提供されているわけですから、連動できてしかるべきとかやはり考えるわけで。
いーかげんいらいらしてきたのでちょっと調べてみました。やみくもに。



で、わかったこと。

VS.NETのヘルププログラムの実体は「Microsoft Document Explorer」って奴で、C:\Program Files\Common Files\Microsoft Shared\Helpとかに格納されているdexplore.exeがそれです。

で、これを単体で立ち上げると、デフォルトで表示されるトピックは「Visual Studio .NET 連結ヘルプ コレクション」。
このページから「Visual Studio .NET 連結ヘルプ コレクション マネージャ」のリンクをクリック→移動、「VSCC に含めることのできるコレクション」の項目に、うわぁあるよ。「Oracle Data Provider for .NET Help」(ODP.NET)も「Crystal Reports 10」もチェックできる選択肢として。
「Crystal Reports 10」にはチェック付いてるんですが、なんでだか現状私のマシンでは表示も