2006年09月29日

DataGridViewの行ヘッダに行番号を表示させるには

以前のTips「DataGridViewの行ヘッダ(列ヘッダ)にContextMenuStripを関連付ける」のサンプル画面に行番号の実例がさりげなく写っていた。
これをご覧になった方からその方法が知りたいという要望があったので今回はこれを紹介する。(コードだけの紹介なのでイメージは上記を参照してください)

注:この方法はサイトを調べてC#のサンプルを見つけ、そこからVB用に直しただけの代物です。但し、Tipsとして公開するにあたり理解しやすいように個々のプロパティを直接引数に配置せず、一旦変数に置き換えてあります。また、行番号の右揃えの方法も追加しました。

その仕組みをみると簡単ではあるが泥臭い(APIで無理やり描画させているような感じの)もので、この程度の機能なら標準プロパティ等で指定できるようにすべきだと思う。

'///// 行ヘッダに行番号を描画 /////
Private Sub dataGridView_RowPostPaint(ByVal sender As Object, _
ByVal e As DataGridViewRowPostPaintEventArgs) _
Handles Me.RowPostPaint
' - 行番号と行の境界(枠)の左上のPOINT(X,Y)を取得
Dim RowNo As Integer = e.RowIndex + 1 '行番号を取得
Dim X as Integer = e.RowBounds.Location.X '行(Row)の境界の左上X座標
Dim Y as Integer = e.RowBounds.Location.Y ' 同上 Y座標

'塗り潰し用ブラシを作成
Using bs As SolidBrush = New SolidBrush(Me.RowHeadersDefaultCellStyle.ForeColor)
'文字列を描画
e.Graphics.DrawString(RowNo.ToString(), _ '行番号文字列
Me.DefaultCellStyle.Font, _ 'フォントを指定
bs, _ 'ブラシを指定
X + 15, Y + 4) '文字出力座標
End Using
End Sub
 
説明すると、DataGridViewの一行分が描画し終わったタイミング(RowPostPaintイベント)で、行ヘッダに直接文字を描画させている。このコードだけで全ての行に行番号を表示することができる。
行削除、行追加を行っても自動で更新(再描画)されるので便利である。

ここで使われる描画メソッド(Graphics.DrawString)はフォームやコントロールに文字列を描画するときに使うものだ。(ヘルプにはフォームに文字を出力するサンプルがいろいろある)
描画位置は文字列の左上を指定するので、文字が行ヘッダの適当な位置に収まるように調整する。(この例では右に15ピクセル、下に4ピクセル移動している)
左上が開始位置なので何もしないと左揃えになる、右揃えや中央揃えにするには文字列の長さを取得して位置を調整する必要がある。
右揃えにする簡単な方法は、DrawStringのオーバーロードでStringFormatを引数に渡すタイプを使う。

'///// 行番号を右揃えで表示させる方法 /////
Private Sub dataGridView_RowPostPaint(ByVal sender As Object, _
ByVal e As DataGridViewRowPostPaintEventArgs) _
Handles Me.RowPostPaint
Dim RowNo As Integer = e.RowIndex + 1
Dim X As Integer = e.RowBounds.Location.X
Dim Y As Integer = e.RowBounds.Location.Y
Dim drawPoint As New Point(X + 35, Y + 4) '右揃え用に位置をずらす
Dim drawFormat As New StringFormat
'このフラグで右から左に出力される。
drawFormat.FormatFlags = StringFormatFlags.DirectionRightToLeft

Using bs As SolidBrush = New SolidBrush(Me.RowHeadersDefaultCellStyle.ForeColor)
e.Graphics.DrawString(RowNo.ToString(), _
Me.DefaultCellStyle.Font, _
bs, _
drawPoint, _
drawFormat)
End Using
End Sub

posted by なっちゃん at 11:36| 静岡 ☀| Comment(6) | TrackBack(1) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年09月22日

DataGridViewの行ヘッダ(列ヘッダ)にContextMenuStripを関連付ける

VB6で使っていたメニューの仕様が.NETになってから大きく変わった。
メニューのデザインが直感的にわかるようになり、右クリックでポップアップするメニュー(ショートカットメニューとかコンテキストメニュー(ContextMenu)と呼ばれる)はフォームやコントロール毎にプロパティーに指定することで簡単に表示できるようになった。

DataGridViewのContextMenuStripプロパティに、作成したContextMenuStripコントロールを関連付けるとすべてのセル・ヘッダ上でショートカットメニューが表示されてしまう。
行ヘッダや列ヘッダで、それぞれの別のショートカットメニューを表示させるには実行時に以下の処理を追加する。

Private Sub AddContextMenu()
'-- 行ヘッダにContextMenuStrip1を関連付け
For Each row As DataGridViewRow In DataGridView1.Rows
row.HeaderCell.ContextMenuStrip = ContextMenuStrip1
Next
'-- 列ヘッダにContextMenuStrip2を関連付け
For Each column As DataGridViewColumn In DataGridView1.Columns
column.HeaderCell.ContextMenuStrip = ContextMenuStrip2
Next
End Sub

画面は合成イメージ
行ヘッダ・列ヘッダにショートカットメニューを関連付け
posted by なっちゃん at 10:30| 静岡 ☁| Comment(3) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年09月21日

DataGridViewの列毎に数字のみ入力許可を与える方法

前回、列毎にIMEを制御する方法を紹介したので、今度はIMEをOFFにした上で数値(0〜9)だけを許可する方法を紹介する。

この方法では前回のソースを再利用している。それというのも現在の列番号を取得するのに必要だからである。

普通のTextBoxコントロールであれば、通常のKeyPressイベント内で制御すれば良いのだが、DataGridViewでそれをやってもCell内のKeyPressイベントを拾ってはくれない。これはDataGridViewのセルにはTextBox・ComboBoxなどいくつものスタイルがあって、それぞれのタイプ別にイベントを持っているからである。

Private colNo, rowNo As Integer
'DataGridViewのTextBoxセルを宣言
Private TextEditCtrl As DataGridViewTextBoxEditingControl
 
'//// 列毎にIMEを制御 ///////
Private Sub DataGridView1_CellEnter(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
Handles DataGridView1.CellEnter
colNo = e.ColumnIndex '現在の列番号
rowNo = e.RowIndex '現在の行番号
Select Case e.ColumnIndex
Case 0, 4, 11
'この列は日本語入力ON
DataGridView1.ImeMode = Windows.Forms.ImeMode.Hiragana
Case 1 To 3, 5 To 10
'この列はIME無効(半角英数のみ)
DataGridView1.ImeMode = Windows.Forms.ImeMode.Disable
End Select
End Sub
 
'///// DataGridViewの編集コントロールが表示された時に //////
'///// KeyPressイベントを関連付け //////
Private Sub DataGridView1_EditingControlShowing( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
Handles DataGridView1.EditingControlShowing
TextEditCtrl = CType(e.Control, DataGridViewTextBoxEditingControl)
AddHandler TextEditCtrl.KeyPress, AddressOf TextEditCtrl_KeyPress
End Sub
 
'///// TextBoxセル内でのKeyPressイベント //////
Private Sub TextEditCtrl_KeyPress(ByVal sender As Object, _
ByVal e As KeyPressEventArgs)
Select Case colNo '現在の列番号
Case 2, 3, 6 '数値のみ許可
Select Case e.KeyChar
Case Chr(Keys.Back) 'BackSpace
Case Chr(Keys.D0) To Chr(Keys.D9) '数値キー
'テンキー用は不要(コメント参照)
'Case Chr(Keys.NumPad0) To Chr(Keys.NumPad9)
'小数点(.)を許可したい場合は
'Case Chr(Keys.Decimal) を追加
Case Else
'上記キー以外は処理しないようにする
'(Delete,Enter,Tabなどは有効)
e.Handled = True
End Select
End Select
End Sub
 
'////// 編集が終わったタイミングでKeyPressイベントの関連付けを解除 /////
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
Handles DataGridView1.CellEndEdit
RemoveHandler TextEditCtrl.KeyPress, AddressOf TextEditCtrl_KeyPress
End Sub
posted by なっちゃん at 16:44| 静岡 ☁| Comment(10) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

Parameters の使用上の注意(ADO.NET)

SQLステートメントでパラメータを使用する場合にParametersプロパティに値をセットするが、連続してSQLを実行する場合、事前にパラメータの内容を消しておかないと同じ内容で処理されてしまうので注意する。
最初これに気が付かず、何故エラーするのか大いに迷ったことがある。

(Dim cmd As New OleDbCommand)
 
For i = 0 To 2
With Item(i)
cmd.CommandText = "insert into hoge_tb values(?,?,?)"
cmd.Parameters.Clear() 'これが無いとItem(0)の内容が3回登録されてしまう。
cmd.Parameters.Add("id", OleDbType.Integer).Value = .id
cmd.Parameters.Add("no", OleDbType.SmallInt).Value = i
cmd.Parameters.Add("namae", OleDbType.VarWChar).Value = .Name
cmd.ExecuteNonQuery()
End With
Next i

posted by なっちゃん at 14:44| 静岡 ☁| Comment(19) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年09月12日

DataGridViewで列毎にIMEを制御するには

CellEnterイベントで列毎にImeModeを指定する

Private Sub DataGridView1_CellEnter(ByVal sender As Object, _
ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
Handles DataGridView1.CellEnter
'---- 列番号を調べて制御 ------
Select Case e.ColumnIndex
Case 0, 4, 11
'この列は日本語入力ON
DataGridView1.ImeMode = Windows.Forms.ImeMode.Hiragana
Case 1 To 3, 5 To 10
'この列はIME無効(半角英数のみ)
DataGridView1.ImeMode = Windows.Forms.ImeMode.Disable
End Select
End Sub

CellEnterイベント・・・現在のセルが変更されたとき、またはこのコントロールが入力フォーカスを受け取ったときに発生
posted by なっちゃん at 20:12| 静岡 ☔| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年09月04日

VB2005でMainプロシージャから起動させるには

VB.NETではプロジェクトのプロパティで選択できたのに(図1)、VB2005では「Sub Main」が出てこない(図2)。何がいけないのかとあちこち調べたがどこにも出てない。
あちこちいじっているうち、「アプリケーションフレームワークを有効にする」を解除したら現われた(図3)。
分ってしまえば何でもないことだが、こういったことが一番やっかいである。やれやれ(- -;

図1:VB.NET2003のプロパティ
VB.NET2003のプロパティ


図2:VB2005のプロパティ(既定値)
VB2005のプロパティ(既定値)


図3:VB2005のプロパティ(修正)
VB2005のプロパティ(修正)
posted by なっちゃん at 18:29| 静岡 ☀| Comment(4) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年08月31日

VS2005のDataGridViewは感動もの

最近VB2005でちょっとしたシステムを作り始めた。もちろん仕事でだが、VB.NETと比べて確かに使い勝手が良くなったと思う。
いろんな点で洗練されてきたのを感じる。ちょっとビックリしてしかも感動的なのがコントロールの配置の際に補助線(?)がでてくるところだ。
隣り合うコントロールと位置関係が一目瞭然でバランスよく配置する手助けになる。(下図)

補助線が現われる

レイアウトに関して新しいコンテナコントロールがあり、これまで面倒だったサイズや位置の変更に強力に支援してくれる。ほとんど考える(作り込む)必要がなくなる。

そして今のところ一番感動したのがDataGridViewコントロール。これは従来のDataGridコントロールの進化したものだが、これを使ったサンプルをHPで見つけ試したところあまりの見事さに感動、近くにいた同僚に「見て見て!凄い凄い!」と思わず興奮してもう一度手順を解説してしまったくらいである(^^;。

「特集:.NET Framework 2.0のWindowsフォーム新機能(後編)」
新グリッド・コントロールの豊富な機能と高い表現力


このサンプルはコーディングレスでここまで出来るかという良い見本である。

ただ、ちょっと説明不足のため、どうしても見本の通りできないところがあり、かなり悩んだのでそこを補足してみたい。
下左図が正しい完成画面である。その右の図は最初にHPの手順通りに作ったときのものでDataGridViewの上部が隠れてしまっている。

正しいサンプル 表示がおかしい

これは次のようにして解決した。

ツールバーがDataGridViewの上に被さってしまっているのは、これがToolStripContainerのTopToolStripPanel内に配置されておらずFormに直接配置されていたためである。そのため、一旦ToolStripContainerのDockプロパティをFillからNoneに変更しツールバーから離しておく。次にツールバーのStretchプロパティをFalseにし、Anchorプロパティを全て解除すると移動可能な状態になるのでドラッグ&ドロップでTopToolStripPanelに配置する。(下図)

直しているところ

最後にToolStripContanierのDockプロパティをFillに戻せば修正完了だ。

良い事ばかりではないということも一言書いておく。
開発が便利になった分、統合環境での操作、デザイナーの操作時にバックグラウンドでいろいろ動いているようでやたらと待たされることが多くなった。マシン性能(CPU,メモリ)が一段と要求されるので覚悟してほしい。
posted by なっちゃん at 21:19| 静岡 ☔| Comment(1) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年07月25日

VS2005を入れるとアイコンでバージョンが判る

VB2005をインストールしたときは気付かなかったのだが、よくみるとソリューションファイルのアイコンのデザインが変わっていて、「7」という数字がアイコンに付いていた。
これをVB.NET2003で開くと、確認ダイアログがでて「このソリューションとすべてのプロジェクトを変換しますか?」と聞いてくる。これはVB.NET2002から2003へ変換するためのものだが、変換すると「7.1」という数字にアイコンが変わる。
さらにこれをVB2005で開くと変換ウィザードが現われVB2005のプロジェクトファイルに変わる。このときには「8」の数字がソリューションアイコンに付いている。

バージョン毎のアイコンの違い

これはなかなか便利だ(^^)
もちろん、アイコンをダブルクリックすれば対応する開発環境が自動的に認識されて起動する。ついでにVisualStudioの∞アイコンもバージョン毎に変えてくれるとなお便利だと思うのだが。

posted by なっちゃん at 09:42| 静岡 🌁| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年07月19日

VS2005とVS.NET2003の共存の注意

先日取り上げた「VB2005はASP.NET(VB.NET2003)と相性が悪い?」の原因が判った。
そして、VisualStudio2005とVisualStudio.NET2003の共存は問題ないことが判明した。
注意すべきなのはWebアプリ(ASP.NET)である。IIS(InternetInformationService)の設定項目に、VS2005の環境つまり「.NET Framework2.0」をインストールするとASP.NETタブが追加され、ここの設定を誤ると動作しなくなる。だからここさえ注意すれば何も問題ない。
(図はいずれもWindows2000ServerのIISのもの)

VB2005をインストールする前のIISのプロパティ(タブの数に注目)
iistab.gif

VB2005をインストールした後のIISのプロパティ(ASP.NETタブが追加されている)
ここでFrameworkのバージョンを指定できるのでアプリ毎に切替可能になる。
iistab-2.gif

実は、今日再インストールしたら今度は何の問題も無く動いたので合点が行かなかった。前回と特にインストール方法に違いがあるとは思えないのに。ただ、IISに「ASP.NET」のタブが追加されることをインターネットで調べて知ったので、今度はここを確認してみたところ、最初から既存のWebアプリはASP.NET1.1の仕様になっていた。前回動かなかったということはこれが2.0を指していたためだと思うのだが、何故何もしなくても1.1になっていたのか・・・・インストール後再起動しなかったために2.0になっていたのかも知れないが。

posted by なっちゃん at 19:32| 静岡 ☁| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年07月11日

XML Webサービス 開発上の注意(参照URLとアプリケーション構成ファイル)

「基になる接続が閉じられました。リモートサーバーに接続できません。」

例によって、開発環境で問題なく動いていたのに、ユーザーの環境へ移した途端にこのエラーが出た。
スマートクライアントでWebサービスを利用しているのだが、つくづくこのスマートクライアントというのはやっかいなシステムだと思う。やたらと制限や条件が付く。ASP.NETの方がずっと楽である。
しかしWebアプリでは入力バリバリの業務システムは難しい。(VS2005はもうちょっと改善されているようなことを聞いたが...)

さてエラーの原因は、Webサービスの参照URLが「http://localhost/....」になっていたためだった。
開発環境では自分自身のことなのでlocalhost(初期値)で問題ないのだが、他のクライアントから見たらサービスを提供するPCはlocalhostには決してならない。そこで初期値のURLを動的に変更できるようにアプリケーション構成ファイル(App.Config)に記述しておき、起動時にそれを読み込み、サービスのインスタンス時のURLに適用させるのである。

※アプリケーション構成ファイルの使い方は 下を参考に
-> http://support.microsoft.com/default.aspx?scid=kb;ja;313405

何のことはない、これは既に解決済みの処理でうっかりサービス呼出時にURLを変更するのを忘れていただけのミスだった。
ただ、このことでサービス呼出時に毎回URL変更手続きを書くのは今回のようなミスを引き起こしやすい。もっと楽に一回でできる方法が必要だと考え、調べてみることにした。

VisualStudioのソリューションエクスプローラーでWeb Referencesを開き、サービスを選択するとプロパティーウィンドウに「URLの動作」として初期値がスタティックになっている。これをダイナミックにするだけでよい。(下図参照)
20060711.gif

構成ファイルからの取得も以下のように自動で行ってくれる。
Reference.vb を見ると以下の行ができているのがわかる。ダイナミックにすることでアプリケーション構成ファイルから値を自動で取得するようになる。

Public Sub New()
MyBase.New
Dim urlSetting As String = _
System.Configuration.ConfigurationSettings.AppSettings(
"hoge.ws_hoge.Service1")
If (Not (urlSetting) Is Nothing) Then
Me.Url = String.Concat(urlSetting, "")

Else
Me.Url = "http://localhost/websvhoge/ServiceHoge.asmx"
End If
End Sub

構成ファイルのkeyも自動的に追加作成される。配布後、ここのValueを配布先のPCのURLに変更するだけでよい。(下図参照)

20060711-2.gif


補足Tips:
構成ファイル(.Config)はWindowsアプリでは App.Configがプロジェクトに追加され、WebアプリではWeb.Configが追加される。App.Configはコンパイル後に(ApplicationName).(Application Type).config という形式の名前に変更される。
例えば hoge.exe.config とかいう感じで。
posted by なっちゃん at 22:18| 静岡 ☁| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年07月07日

DataGridに書式を指定して表示

DataGridはデータの一覧表示に便利なコントロールでよく使う。
その際、列の書式設定には通常ColumnStyleコレクションエディタを使うが、問題はあらかじめ決まったテーブルを表示するとき以外には全く利用価値がないことだ。
マスター参照用にマスターの数だけフォームを用意するのは、2・3個ならまだしも、それ以上はうんざりする。一つで汎用的に作るのが賢いプログラマである。
今回、その方法はSELECT文の書き方だけでできるのでとても簡単である。

サンプルはOracel(10g)のデータを使った。
書式の効果がわかりやすいように、日付・時刻はNUMBER型になっている。

1.普通の書き方とその表示画面はこうなる。

20060707-1.gif

sSql = "SELECT " & _
"inputymd ""入力日""," & _
"inputhms ""時刻""," & _
"denpyono ""伝票No.""," & _
"jyucyuymd ""受注日付""," & _
"case denkbn when 0 then '売上' when 5 then '現金売上' else 'その他' end ""伝区"" ," & _
"tokuinm ""得意先""," & _
"gokei ""合計金額"" " & _
"FROM t_jyutyub_h " & _
"WHERE tantocd like '%" & para & "%' " & _
"AND jyucyuymd >= " & para2 & " " & _
"ORDER BY jyucyuymd DESC"

2.書式指定付きの書き方とその表示はこうなる。

20060707-2.gif

sSql = "SELECT " & _
"TO_CHAR(TO_DATE(inputymd,'YYYYMMDD'),'YYYY/MM/DD') ""入力日"", " & _
"TO_CHAR(TO_DATE(TO_CHAR(inputhms,'FM000000'),'HH24MISS'),'HH24:MI:SS') ""時刻"", " & _
"denpyono ""伝票No.""," & _
"TO_CHAR(TO_DATE(jyucyuymd,'YYYYMMDD'),'YYYY/MM/DD') ""受注日付""," & _
"case denkbn when 0 then '売上' when 5 then '現金売上' else 'その他' end ""伝区"" ," & _
"tokuinm ""得意先""," & _
"TO_CHAR(gokei,'9,999,999,990') ""合計金額"" " & _
"FROM t_jyutyub_h " & _
"WHERE tantocd like '%" & para & "%' " & _
"AND jyucyuymd >= " & para2 & " " & _
"ORDER BY jyucyuymd DESC"


数値型の日付(年月日)の書式指定は、日付型に変換(TO_DATE)後、さらに文字型(TO_CHAR)に変換している。
時刻の場合だと、5桁(90130=9時1分30秒)と6桁(101545=10時15分45秒)が混じるので、事前に文字型(FM修飾子付)に変換し、6桁に統一してから日付型に変換している。
合計金額の場合、最大桁数分のFormat書式を指定する。これが少ないと、Excelのように#で表示されてしまう。桁の無いところは[9]を指定すると空白が出力され、[0]を指定すると0が出力される。


posted by なっちゃん at 21:20| 静岡 🌁| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年07月04日

VB2005はASP.NET(VB.NET2003)と相性が悪い?

これは、たまたま自分の環境だけの問題なのかよくは判らないが、VisualBasic2005Expressを現在の開発環境(VS.NET 2003)にインストールしたところASP.NET(2003)でこれまで動いていたWebアプリが急にmachine.configに不正があるという意味のエラーで起動できなくなってしまった。但しWindowsアプリ(VB.NET)は問題なく動く。原因が特定できず仕方なくVB2005を.NET Framework2.0を含め全てアンインストールしたところ、何事も無かったように正常に起動した。
一体何が悪さをしていたのか。今のところ仕事でVS2005は使うことは無いので支障は無いが、追々調べて見るつもりである。

追加補足:
VB2005Expressと.NET Framework2.0をアンインストールした後、Webアプリは正常に起動したが、その後データベースへの登録のとき「サーバーは要求を処理できませんでした。 MTS オブジェクト コンテキストがありません」のエラーが発生するようになった。他にもVS.NET関連のファイルの関連付けが解除されsln(ソリューション)ファイルのアイコンも不明なアイコンに変わってしまった。
そこで、VS.NET2003の修復セットアップをおこなってようやく元通り動くようになった。VS.NETとVS2005は同居させない方が良いのかな・・・・。


続きを読む...
posted by なっちゃん at 10:47| 静岡 ☁| Comment(2) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年06月08日

スマートクライアントにはVB6互換性ライブラリは使わないこと

テスト環境(開発環境)では問題なく動いていたスマートクライアントがデモ機で実行させたとき次のようなエラーを起こして起動できない。

IEExec.exe - 共通言語ランタイム デバッグ サービス

「アプリケーションで、ハンドルできない例外が発生しました。

処理 ID=0x4bc (1212)、スレッド ID=0x758 (1880)

アプリケーションを終了するには[OK]をクリックしてください。
アプリケーションをデバッグするには、[キャンセル]をクリックしてください。」


最初は原因が判らなかった。いろいろ調査するとVS.NET開発環境のPCでは問題なく動作する。エラーが起きるのは.NET FrameworkランタイムだけのPCであることが判った。
簡単なサンプルを作るとそれは問題なく動いたので、エラーをするプログラムに原因があり、それは開発環境では問題にならないことで、使用するランタイムに特殊なものが利用されているのではと考えた。

その結果、VB6プロジェクトをアップグレードウィザードでVB.NETへコンバートする際に利用されるVisualBasic6.0互換性ライブラリ(Microsoft.VisualBasic.Compatibility.dll)が原因と判明した。
たまたま、問題のプログラムでは一部の機能にVB6プロジェクトからアップグレードさせたルーチンを含んでいたせいでこのランタイムが使われていたのだった。

一般のPCにインストールされる.NET Frameworkのランタイムには
Microsoft.VisualBasic.dll(VisualBasicランタイムライブラリ)は含まれるが、
Micorosoft.VisualBasic.Compatibility.dll (VisualBasic6.0互換性ライブラリ) は含まれないことが判った。

アプリケーションサーバー上に必要なランタイムがあれば動くASP.NETとは違い、クライアント側にもランタイムが必要とされるスマートクライアントはこの点を注意する必要がある。
またクライアントPCに余計なセットアップをさせないためにもVB6アップグレードに頼らずVB.NET本来のコード設計を心がけるべきだろう。
posted by なっちゃん at 10:06| 静岡 ☀| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年06月02日

VB.NET開発者の最良の参考書

私の手元にはVB.NET(ASP.NET含)関連の参考書が約20冊程ある。それなりに重宝して活用してるが、現在一番苦心している問題「フォームやユーザーコントロールの継承に伴うイベントの継承」についてどこにも詳しい解説がない。インターネットで調べてフォームの継承に関する記事を唯一載せていたのが以下の書籍であった。これは全2巻合わせて1,600頁を越す大著で値段も合わせて15,330円と高価だ。しかし、それだけの値打ちがあった。内容は初代VB.NET(2002)によるものだが.NET Frameworkの本質(※)的な解説なので問題なく使える。
※VB6から.NET Frameworkへの転換は非常に大きく.NET Framework1.0(2002)->1.1(2003)->2.0(2005)の違いの比ではない。

この本はVB6経験者でVB.NETに取り組むベテラン開発者にとっては最高の参考書となる。基礎編・活用編2冊一緒に買うべきである。もともと原著は1冊であり、引用箇所が日本語版では分かれてしまった箇所が少なくないからだ。また付録CD-ROMには掲載サンプルソースが付いており詳細に解析するのに大いに役立つ。(VB.NET2003環境でも自動変換してそのまま動く)
文章は平易でユーモアもあり(著者はイタリア人らしい)読み易い。

プログラミングMicrosoft Visual Basic .NET〈Vol.1〉基礎編
プログラミングMicrosoft Visual Basic .NET〈Vol.1〉基礎編Francesco Balena ドキュメントシステム


おすすめ平均 star
starすべての.NETプログラマー必読の本
star基本です
star現時点では、VB.NETのベストの解説書

Amazonで詳しく見る
by G-Tools

プログラミングMicrosoft Visual Basic .NET〈Vol.2〉活用編プログラミングMicrosoft Visual Basic .NET〈Vol.2〉活用編
Francesco Balena ドキュメントシステム


Amazonで詳しく見る
by G-Tools


追記:2006.10.26
同じ著者によるVB2005の書籍の日本語版が発売された。
「言語編」(上・下)とあるので、上記の書籍とはまたタイプが異なるのだろうか?まだ現物を見たことがないので(^^;確認できていません。

プログラミング Microsoft Visual Basic 2005 言語編〈上〉
プログラミング Microsoft Visual Basic 2005 言語編〈上〉フランチェスコ バレナ Francesco Balena クイープ


おすすめ平均 star
star言語仕様の詳細を知るなら!

Amazonで詳しく見る
by G-Tools


プログラミングMicrosoft Visual Basic 2005 (言語編下)プログラミングMicrosoft Visual Basic 2005 (言語編下)
Francesco Balena


Amazonで詳しく見る
by G-Tools

posted by なっちゃん at 15:46| 静岡 ☁| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年05月19日

VB.NETではForm1(最初に起動させるフォーム)を非表示で起動できない?

タスクトレイに常駐させるプログラムの場合、VB6ではForm_Loadイベント内で、Me.Visible = False と記述するだけで、フォームを全く表示することなく起動することができた。
ところが、VB.NETではMe.Visible = False とやっているにも関わらずなぜか表示してしまう。
Me.RefreshやApplication.DoEventsを付けても全くだめ。Activatedイベント内で非表示にさせようとしても駄目だった。
一度フォームが表示した後でなら、いくらでも非表示にさせられるのに、起動時に非表示にできないのである。
仕方が無いのでTimerコントロールを使いTimerイベント内でMe.Visible=Falseを実行させたところ、一瞬表示された後フォームは消えた。
スマートではないがとりあえず非表示にはなった。だが、やはり納得がいかずもう少し調べてみた。

いろいろ試すうちにフォームデザイン時にShowInTaskbarをFalseにして、WindowStateをMinimized(最小化)にすると表示しないことが判明
大事なのは実行時に指定しても無駄で、必ずデザイン時にこうしておかないと表示してしまうことである。

これで万事OKかと思いきや問題はまだあった。
タスクトレイに常駐させるプログラムは、フォームを表示してまた閉じる、この繰り返しが必要なのだが、2回目にフォームを表示させたとき、フォームが元のサイズに復元されない。ちょうど子フォームのようにタイトルバーだけのサイズになって左下に表示されるのである。
この原因はよくわからないのだが、WindowStateプロパティを最小化状態から標準(Normal)状態に変更する前にVisibleをTrueにしておくことで解決した。本当は後にもってきて最小化している状態を見せないようにしたかったのだが。

以下にこのサンプル画面デザインとソースを紹介する。
なお、この問題で調べた中でDOBON.NET「フォームを表示させずにトレイアイコンを表示する」に同じ問題について論じられている。ここで紹介されている「フォームのCreateParamsプロパティをオーバーライドする」では非表示に起動できても、その後2度と表示することができないものなので採用しなかった。

20060519.gif

'--- 起動 ---
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
'NotifyIconの初期化
With NotifyIcon1
.Text = Me.Text
.Icon = Me.Icon
.ContextMenu = ContextMenu1
.Visible = True
End With
End Sub
 
'--- ContextMenu(表示) ---
Private Sub MenuItem1_Click(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles MenuItem1.Click
Me.Visible = True
Me.WindowState = FormWindowState.Normal

End Sub
 
'--- アイコンをダブルクリックは表示 ---
Private Sub NotifyIcon1_DoubleClick( _
ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles NotifyIcon1.DoubleClick
Me.Visible = True
Me.WindowState = FormWindowState.Normal

End Sub
 
'--- ContextMenu(終了) ---
Private Sub MenuItem3_Click( _
ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles MenuItem3.Click
NotifyIcon1.Visible = False 'トレイからアイコンを削除
Application.Exit() 'プログラムの終了
End Sub
 
'--- 「画面を閉じる」ボタン ---
Private Sub Button1_Click( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Me.Visible = False
Me.WindowState = FormWindowState.Minimized

End Sub
 
'--- 「最小化」ボタンを押したときの処理 ---
Private Sub Form1_Resize(ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Resize
Select Case Me.WindowState
Case FormWindowState.Minimized
If Me.Visible = True Then Me.Visible = False

End Select
End Sub
 
'--- Context(終了)以外からは終了しない ---
Private Sub Form1_Closing(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) _
Handles MyBase.Closing
Select Case e.CloseReason
Case CloseReason.UserClosing
e.Cancel = True '終了をキャンセル
Me.WindowState = FormWindowState.Minimized
End Select
End Sub

2012年になってVB2010で開発した際、このTipsを使ったのだがどうしたことかフォームが小さく残ってしまうことが判明、そこで新たな方法を編み出した。
http://natchan-develop.seesaa.net/article/290752211.html
posted by なっちゃん at 15:47| 静岡 ☔| Comment(0) | TrackBack(1) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年05月18日

VB.NETのコントロールの一括処理(コントロール配列−その3)

以前、VB6のようにコントロール配列が使えないため、沢山あるテキストボックスにデータを代入するのに便利な方法を取り上げたが、これはWebアプリ(ASP.NET)でしか使えない方法だった。
「コントロール配列−その2」

Windowアプリ(VB.NET)ではどうやって実現するか調べてみた。
そして、@ITの「Windowsフォーム上のすべてのコントロールを列挙するには?」を使うことで実現できることがわかった。

サンプルとして取り上げたのは、起動時に全てのTextBoxのTextプロパティを初期化し、Labelコントロールの中でもBorderStyleがFixed3Dのものだけを初期化するというものである。

まず、@ITのサンプルにある「すべてのコントロールを再帰的に取得するメソッド」を汎用モジュールとする。これはForm上の全てコントロールを一つの配列に取り込むものである。

Public Function GetAllControls(ByVal top As Control) As Control()
Dim buf As ArrayList = New ArrayList
For Each c As Control In top.Controls
buf.Add(c)
buf.AddRange(GetAllControls(c))
Next
Return CType(buf.ToArray(GetType(Control)), Control())
End Function

次にTextプロパティの初期化ルーチン[ControlInit]を次のようにする。
ここでは、取得した全てのコントロールから目的のTextBoxとLabelをTypeOf ... Is 式を使って判定している。もし、コントロール名を知りたければ、nameプロパティを使うとTextBoxやLabelの個別名がわかる。

Private Sub ControlInit()
Dim AllCtrl As Control() = GetAllControls(Me)
For Each c As Control In AllCtrl
If TypeOf c Is TextBox Then
'TextBoxだったら
c.Text = "" 'TextBoxの初期化
ElseIf TypeOf c Is Label Then
'Labelだったら
Dim lb As Label
'(注) c のままではBorderStyleにアクセスできない
lb = CType(c, Label)

If lb.BorderStyle = BorderStyle.Fixed3D Then
'BordeStyleがFixed3Dだったら
lb.Text = "" 'Labelの初期化
End If
End If
Next
End Sub

後はこれをForm_Loadイベントで実行すればよい。
posted by なっちゃん at 10:49| 静岡 ☔| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年05月12日

他のフォームのコントロールを参照するには

VB6の時は簡単だった。(フォーム名).(コントロール名).(プロパティ)で参照できた。たとえばForm1.Text1.Textのような感じで。
VB.NETで別のフォームからForm1.TextBox1.Textを参照しようとしてもそのままではTextBox1が見えない。
ガリバー著「VisualBasic.NET基礎300の技」のTips261「他のフォームのコントロールを参照する」をみると、コントロールをSharedキーワードと共に宣言すると出ている。ところがこの通りやってみると、参照は確かにするのだが、フォームデザイン画面からコントロールが消えてしまう。Sharedを外すと復活する。これではたとえ参照できても画面の編集ができないから使いようがない。この本はVB.NET2002を元に書かれたものだからVB.NET2003の仕様が変わったためなのかもしれない。

仕方が無いので自分で調べることにした。そして試行錯誤の上、以下のような方法で実現することができた。

1.クラスモジュールにForm1をPublic Shared で定義
2.上記クラスモジュールのMainプロシージャからForm1を起動。
3.Form2に上記クラスモジュールをimportsで参照
4.Form1から開いたForm2でForm1のコントロールを参照。

サンプルソース(SharedForm.lzh)を用意したので詳しくはそちらを見てもらうとして、サンプルでは、Form1のTextBox1の内容をForm2から参照し、さらにForm2のTextBox1の値をForm1のTextBox2へ直接代入するようになっている。なおスタートアップをMainプロシージャでなくForm1にした場合では参照することはできなかった。


'=== プロジェクト名:SharedForm ===
'--- Class1.vb ---
Public Class Class1
Public Shared f1 As New Form1
Shared Sub Main()
Application.Run(f1)
End Sub
End Class
 
'--- Form1.vb ---
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
Dim f2 As New Form2
If f2.ShowDialog(Me) = DialogResult.OK Then
'f2側から変更しているので不要
'TextBox1.Text = f2.TextBox2.Text
'TextBox1.BackColor = System.Drawing.Color.Red
End If
f2.Dispose()
End Sub
 
'--- Form2.vb ---
Imports SharedForm.Class1
Public Class Form2
(中略)
Private Sub Form2_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
Me.Left = f1.Left + f1.Width
Me.Top = f1.Top
TextBox1.Text = f1.TextBox2.Text
End Sub
 
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles Button1.Click
f1.TextBox1.Text = TextBox2.Text
f1.TextBox1.BackColor = System.Drawing.Color.Red
Me.Close()
End Sub
End Class

20060512.gif サンプル画面

Visual Basic.NET基礎300の技Visual Basic.NET基礎300の技
ガリバー

Visual Basic .NET逆引き大全 500の極意―WindowsXP/2000/NT対応 Visual Basic .NET ネットワーク+データベース300の技 ひと目でわかるMicrosoft Visual Basic .NET データベース開発入門 Visual Basic.NETプログラミングマニュアル ステップバイステップで学ぶMicrosoft Visual Basic .NET実践講座〈Vol.1〉基礎編

by G-Tools

posted by なっちゃん at 17:26| 静岡 ☔| Comment(5) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年05月02日

VB.NET:通常起動とスマートクライアントでのコマンドライン取得結果の違い

スマートクライアントで引数をどう渡すのかと疑問に思ったところからはじまる。
通常のWindowsアプリならプログラム名と引数の間に半角スペースを置けば良い。
(例) hoge.exe para1 para2
スマートクライアントはURLで記述するから
http://localhost/webapp1/hoge.exe para1 para2 とは書けないので
ASP(ASP.NET)やJava,CGI等の一般的な書き方にすると
http://localhost/webapp1/hoge.exe?para1&para2 となるだろう。

さて、問題はこの引数をどうやって取得するかである。
VB6の場合Command関数で引数を取得できるが、プログラム名と引数の間はスペースが必要だ。そこで、VB.NETの場合に同様の関数があるかを調べてみると3つの方法があることがわかった。

1.VB6互換関数
2.Mainプロシージャからの取得
3.EnvironmentクラスのGetCommandLineArgsメソッド

このうち、Mainプロシージャはクラスモジュール(xxxx.vb)に記述し、プロジェクトのスタートアップに指定する必要があるが、他の2つはFormのLoadイベントでも利用可能である。

テストは手っ取くMainプロシージャ内に3つの方式を利用するコードを書いて行った。

Shared Sub Main(ByVal CmdArgs() As String)
Dim i As Integer
'--- CmdArgs() から取得 ---
For i = 0 To UBound(CmdArgs)
Console.WriteLine(CmdArgs(i))
MsgBox(CStr(i) & " : " & CmdArgs(i), _
MsgBoxStyle.OKOnly, "CmdArgs")
Next
'--- VB6互換Command関数から取得 ---
Dim sepa As String = " "
Dim commands As String = _
Microsoft.VisualBasic.Command()
Dim args() As String = _
commands.Split(sepa.ToCharArray)
For i = 0 To UBound(args)
Console.WriteLine(args(i))
MsgBox(CStr(i) & " : " & args(i), _
MsgBoxStyle.OKOnly, "VB6:Command")
Next i
'--- Environmentクラスから取得 ---
Dim args2() As String = _
Environment.GetCommandLineArgs
For i = 0 To UBound(args2)
Console.WriteLine(args2(i))
MsgBox(CStr(i) & " : " & args2(i), _
MsgBoxStyle.OKOnly, "Environment")
Next i
'--- フォームの起動 ---
Application.Run(New Form1)
End Sub

これを以下のように実行させた。

Windowsアプリ
hoge.exe abc 123

Webアプリ(スマートクライアント)
http://localhost/hoge.exe?abc&123

結果はこちらの表
20060502.gif

これにより、スマートクライアントでパラメータを取得するにはVB6互換Command関数が手っ取り早い。
ここからプログラム名と#以降の文字データを取り除きSplit関数を使ってパラメータを分解する方法である。
posted by なっちゃん at 17:48| 静岡 ☁| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年04月25日

DateTimePickerで和暦表示を行う

前回のTipsではDateTimePickerで和暦表示を行うにはコントロールパネルの地域オプションのカレンダー表示を和暦にする必要があると書いたが、いろいろ調べてみたところVB6風にプログラム上で和暦表示させる方法が見つかった。VB6の場合と比べると年を直接変更できない問題はあるが(一度カレンダーを表示させて西暦を変更することで可能)、現状ではこれ以上の解決方法はなさそうである。以下にサンプルを記す。

※DateTimePicker1.Format = DateTimePickerFormat.Custom をロード時またはデザイン時のプロパティに指定しておく。
 
Imports System.Globalization
 
'--- 汎用モジュールに記述して再利用可能にする ----
Public Function FormatJPCalendar( _
ByVal tday As DateTime) As String
Dim cal As JapaneseCalendar = New JapaneseCalendar
Dim era As Integer = cal.GetEra(tday)
Dim nengo() As String = {"明治", "大正", "昭和", "平成"}
Select Case era
Case 1 To 4
Return String.Format("{0}{1:00}年MM月dd日", _
nengo(era - 1),
cal.GetYear(tday))
Case Else
Return "yyyy/MM/dd"
End Select
End Function
 
'--- フォームロードイベントの初期設定 ---
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles MyBase.Load
DateTimePicker1.Format = DateTimePickerFormat.Custom
DateTimePicker1.Value = Today
DateTimePicker1.CustomFormat = _
FormatJPCalendar(DateTimePicker1.Value)

End Sub
 
'--- フォームモジュールのDateTimePickerのイベント ---
Private Sub DateTimePicker1_ValueChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles DateTimePicker1.ValueChanged
DateTimePicker1.CustomFormat = _
FormatJPCalendar(DateTimePicker1.Value)
End Sub
 
Private Sub DateTimePicker1_VisibleChanged( _
ByVal sender As Object, _
ByVal e As System.EventArgs) _
Handles DateTimePicker1.VisibleChanged
DateTimePicker1.CustomFormat = _
FormatJPCalendar(DateTimePicker1.Value)
End Sub

20060427.gif
posted by なっちゃん at 17:50| 静岡 ☀| Comment(10) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする

2006年03月02日

実用的な.NET学習用サンプルを見つけた

@ITのサイトの「.NETでWindowsアプリを作ろう」に見事なサンプルを見つけた。
VB.NETとC#の両方のソースが付いている。
サンプルとは言っても、十分実用的で便利なものだ。
Googleのイメージ検索で表示される画像だけを一覧で表示してくれる。
試しに「荒川静香」で検索するとあれよあれよいうまに755件の画像が表示された。

このサンプルの凄いところは、サムネイルの画像がスライドバーで自動的に拡大縮小することだ。これをVB6で作ろうとしてもサードパーティのツールを使わなければ無理だろう。
20060302-2.jpg 20060302.jpg

その後、
posted by なっちゃん at 19:54| 静岡 ☀| Comment(0) | TrackBack(0) | VB.NET Tips | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。