VB.net

PageLastUpdate:2010-04-14/today: - /yesterday: -
オブジェクト指向から勉強中。ヘタレた内容だけど笑わないでね。

自作クラスとか

DataGridViewEx 2007/11/19 拡張DataGridView。列位置や幅のユーザー別の保存とか
DataGridViewSynchronizer 2007/11/13 上下に並べたふたつのDataGridViewの列表示を同期させるクラス。
WorkStationLockController 2007/07/16 PCのロックをしたりロック状態を取得するクラス
DebugTimer 2007/07/23 デバッグ時に処理ごとのパフォーマンスを計測するクラス

最近やっと構造化例外処理と継承の基本が理解できた

2010/03/27
5年目にしてやっとわかったよ。片手間プログラマーはだめだなあ。
いままでのコードが恥ずかしてく、もう全部書き直したい。
公開しているコードもずっといいコードが書けるようになっているので、そのうち直す。かも。

DataGridViewのグリッド、行、列、セルのReadOnlyプロパティの相関関係

2010/03/27
1.グリッドのReadOnlyがTrueならセルのReadOnlyは実際に設定されている値とは別にReadOnlyを返します。
2.列のReadOnlyもしくは行のReadOnlyを変化させたときはTrueの時のみセルのReadOnlyが変更されます。
 →True セルのReadOnlyもTrue
 →False セルのReadOnlyは変化しない(ReadOnly=Trueのセルは書き込めず、Falseのセルは書き込めるようになる)
プロパティ部分をコードで書くとこんな感じ(雰囲気だけつかんでね)。
Public Property GridReadOnly() As Boolean
    Get
        Return _gridReadOnly
    End Get
    Set(ByVal value As Boolean)
        _gridReadOnly = value
    End Set
End Property
 
Public Property CellReadOnly() As Boolean
    Get
        If Me.Grid.ReadOnly = True Then
            Return True
        Else
            Return _cellReadOnly
        End If
    End Get
    Set(ByVal value As Boolean)
        _readOnly = value
    End Set
End Property
 
Public Property RowReadOnly() As Boolean
    Get
        Return _rowReadOnly
    End Get
    Set(ByVal value As Boolean)
        If value = True Then
            For Each cell As DataGridViewCell In Me.cells
                cell.ReadOnly = True
            Next
        End If
        _rowReadOnly = value
    End Set
End Property
 
Public Property ColumnReadOnly() As Boolean
    Get
        Return _columnReadOnly
    End Get
    Set(ByVal value As Boolean)
        If value = True Then
            For Each cell As DataGridViewCell In Me.cells
                cell.ReadOnly = True
            Next
        End If
        _columnReadOnly = value
    End Set
End Property

NotifyIconはExplorer強制終了時のトレイアイコンの再描画も勝手にやってくれる

2009/01/14
タスクトレイにアイコンを作成するアプリの作りが悪いと、エクスプローラーが強制終了したときに、プロセスだけ残ってトレイアイコンが消えてしまいます。
タスクマネージャからエクスプローラーを再起動しても、トレイアイコンは勝手には戻ってくれません。
これに対応するにはアプリケーション側でRegisterWindowMessage("TaskbarCreated")を拾ってやらないといけないわけですが、NotifyIconはこれも勝手にやってくれている模様。
偉いですね。

指定したウインドウを強制的にフォアグラウンドウィンドウに設定

2009/01/14 検索語:最前面、アクティブ、フォーム
久しぶりにプログラミング。APIを使わなければいけないにしろ、どこまでマネージドコードで書こうか悩む。
どうせ一関数内なら、全部APIにしちゃったほうが見通しがいいような気もするけど・・・
<DllImport("user32.dll")> Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As Boolean
End Function
<DllImport("user32.dll")> Private Shared Function GetForegroundWindow() As IntPtr
End Function
<DllImport("user32.dll")> Private Shared Function ShowWindowAsync(ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean
End Function
Private Const SW_RESTORE As Integer = 9 ' 画面を元の大きさに戻す
<DllImport("user32.dll")> Private Shared Function IsIconic(ByVal hWnd As IntPtr) As Boolean
End Function
<DllImport("user32.dll")> Private Shared Function GetWindowThreadProcessId(ByVal hwnd As IntPtr, ByRef lpdwProcessId As Integer) As Integer
End Function
<DllImport("user32.dll")> Private Shared Function AttachThreadInput(ByVal idAttach As Integer, ByVal idAttachTo As Integer, ByVal fAttach As Boolean) As Boolean
End Function
 
    Public Shared Sub ActivateWindow(ByVal myHandle As System.IntPtr)
        'Static myThreadProcessId As Integer = GetWindowThreadProcessId(myHandle, 0&)    'こっちでもいいけど
        Static myThreadProcessId As Integer = System.Threading.Thread.CurrentThread.ManagedThreadId
 
        If IsIconic(myHandle) Then
            ShowWindowAsync(myHandle, SW_RESTORE)
        End If
 
        Static fgHandle As System.IntPtr = GetForegroundWindow()
        If myHandle <> fgHandle Then
            Dim fgThreadProcessId As Integer = GetWindowThreadProcessId(fgHandle, 0&)
            AttachThreadInput(myThreadProcessId, fgThreadProcessId, True)
            SetForegroundWindow(myHandle)
            AttachThreadInput(myThreadProcessId, fgThreadProcessId, False)
        End If
    End Sub
 

.Net Remotingの「IPC ポートを作成できません。アクセスが拒否されました。」を解消

2009/01/05 この情報は誤りでした。環境依存っぽい。
2009/01/04 検索語:開けない
1.アプリAを起動してチャンネルAを登録。こんなカンジ。
channel = New IpcServerChannel("ChannelA")
ChannelServices.RegisterChannel(channel, False)
RemotingConfiguration.RegisterWellKnownServiceType(myServiceClass.GetType, "ServiceClass", Runtime.Remoting.WellKnownObjectMode.SingleCall)
2.アプリBからChannelAに接続してなんか(Moge)する
Public Sub Hoge
    Dim myServiceClass As ServiceClass = Activator.GetObject(GetType(ServiceClass), "ipc:/ChannelA/ServiceClass")
    myServiceClass.Moge
End Sub
3.アプリAを終了
4.アプリAを起動→「IPC ポートを作成できません。アクセスが拒否されました。」のエラー

これに2年近く悩まされていたんですよ。
ポートを解放してくれるまでの時間を計測したり、再起動時に空くのを待機させてみたり、リース期間をアレコレいじったり。
つい最近まで「Windowsがポートを捕まえてる」んだと思ってたんですが、アプリBを落としてからアプリAを起動するとエラーが出ない。
アプリBがポートを捕まえてるという前提で見直して駄目もとでNothingを叩き込んでみる。
Public Sub Hoge
    Dim myServiceClass As ServiceClass = Activator.GetObject(GetType(ServiceClass), "ipc:/ChannelA/ServiceClass")
    myServiceClass.Moge
    myServiceClass = Nothing   '←コレを追加
End Sub
なんとエラーが出なくなりました!

……お前、スコープってorz

ちょっとでも怪しいと思ったところでは、リソースの開放は意識的にやるべきだという教訓。


DataGridViewとDataGridのキーボード ショートカットの比較

2008/06/17
DataGridViewのキーボード ショートカットを探したけど見つけられないorz
とりあえずWindows フォームの DataGrid コントロール内の移動に使用できるキーボード ショートカットを元に、実際に動作検証をして比較表を作成してみた。
DataGridViewのキーボード ショートカットがまとめられているところか、この表に載っていない機能がありましたら、ぜひ教えて下さい(_o_)
印刷用にExcelファイルも用意しておきました→ダウンロード
区分 動作 DataGrid DataGridView
移動/外 タブ オーダー内の次のコントロールに移動します。 Ctrl + Tab
タブ オーダー内の 1 つ前のコントロールに移動します。 Ctrl + Shift + Tab
移動/内 現在の行にある最初のセルに移動します。 Home
現在の行にある最後のセルに移動します。 End
セルにフォーカスがある場合は、同一行の次のセルに移動します。行の最後のセルにフォーカスがある場合は次の行の最初のセルに移動します。 Tab
セルにフォーカスがある場合は、同一行の 1 つ前のセルに移動します。行の最初のセルにフォーカスがある場合は 1 つ前の行の最後のセルに移動します。 Shift + Tab
矢印の方向にある最も遠い、空白でないセルへ移動します。 Ctrl + 方向キー ×
左上のセルへ移動します。 Ctrl + Home
右下のセルへ移動します。 Ctrl + End
編集 現在のセルへの入力を終了し、次のセルへ移動します。 Enter
セル内が編集モードの場合は、セルの編集をキャンセルします。 Esc
マーキー選択の場合は、該当する行の編集をキャンセルします。 ×
セルを編集するときに、カーソル位置の前にある文字列を削除します。 BackSpace
セルを編集するときに、カーソル位置の後にある文字列を削除します。 Delete
現在のセルの文字列を強調表示し、行の最後にカーソルを位置付けます。セルをダブルクリックするのと同じ動作になります。 F2
EditMode=EditOnEnter:セルがフォーカスを受け取ったときに編集が開始されます。このモードは、Tab キーを押して行に値を入力するとき、または Enter キーを押して列に値を入力するときに便利です。 × フォーカス取得時
EditMode=EditOnF2:セルにフォーカスがあるときに F2 キーを押すと、編集が開始されます。このモードは、セルの内容の末尾を選択します。 × F2
EditMode=EditOnKeystroke:セルにフォーカスがあるときに英数字キーを押すと、編集が開始されます。 × A-Za-z0-9
EditMode=EditOnKeystrokeOrF2:セルにフォーカスがあるときに英数字キーまたは F2 キーを押すと、編集が開始されます。 × A-Za-z0-9,F2
EditMode=EditProgrammatically:BeginEdit メソッドが呼び出されたときにだけ編集が開始されます。 × BeginEdit
現在の行で EndEdit メソッドを呼び出します。 Ctrl + Enter
編集モードのときにセルに System.DBNull.Value 値を入力します。 Ctrl + 0
選択 選択範囲を矢印の方向に 1 行分拡張します (子テーブルのリンクは除外します)。 Shift + ↑
または
Shift + ↓
矢印の方向にある最も遠い、空白でない行まで選択範囲を拡張します (子テーブルのリンクは除きます)。 Ctrl + Shift + ↑
または
Ctrl + Shift + ↓ ×
一番上の行まで選択範囲を拡張します。 Ctrl + Shift + Home
一番下の行まで選択範囲を拡張します。 Ctrl + Shift + End
現在の行を選択します (子テーブルのリンクは除きます)。 Shift + Space
SelectionMode=ColumnHeaderSelectのとき現在の列を選択 Shift + Space
SelectionMode=RowHeaderSelectのとき現在の行を選択 Shift + Space
グリッド全体を選択します (子テーブルのリンクは除きます)。 Ctrl + A
選択範囲を 1 画面分下に拡張します (子テーブルのリンクは除きます)。 Shift + PageDown
選択範囲を 1 画面分上に拡張します (子テーブルのリンクは除きます)。 Shift + PageUp
フォーカスが子テーブルのリンクにある場合は、その子テーブルに移動します。 Enter
子テーブルへのリンクを展開します。Alt キーを押しながら ↓ キーを押すと、選択されているリンクだけでなく、すべてのリンクが展開されます。 Alt + ↓ または Ctrl + プラス記号 (+)
子テーブルへのリンクを折りたたみます。Alt キーを押しながら ↑ キーを押すと、選択されているリンクだけでなく、すべてのリンクが折りたたまれます。 Alt + ↑ または Ctrl + マイナス記号 (-)
子テーブル内の場合は、親テーブルの行を表示します。 Ctrl + PageDown
子テーブル内の場合は、親テーブルの行を非表示にします。 Ctrl + PageUp
フォーカスが行の最後のセルにある場合は、その行の最初の子テーブルへのリンクへ移動し、展開します。 Tab
子リンクにフォーカスがある場合は、次の子リンクに移動します。
最後の子リンクにフォーカスがある場合は、次の行の最初のセルに移動します。
行の最初のセルにフォーカスがある場合は、1 つ前の行の最後に展開された子テーブルへのリンク、または 1 つ前の行の最後のセルに移動します。 Shift + Tab
子リンクにフォーカスがある場合は、1 つ前の子リンクに移動します。
最初の子リンクにフォーカスがある場合は、1 つ前の行の最後のセルに移動します。
子テーブル内の場合は、親テーブルへ移動します。[戻る] をクリックするのと同じ動作になります。 Alt + ←

ESCキーで行の変更をキャンセルするDataGridView

2008/06/16 検索語:キーボード ショートカット エスケープ DataTable
DataGridViewはESCキーで編集のキャンセルができないので、とりあえず作ってみた。
Bindしている行がDataRowViewにDirectCastできるのが前提条件です。
Public Class DataGridViewEx
    Inherits DataGridView
    Private _rejectbyescape As RejectByEscapeType = RejectByEscapeType.None
    Public Enum RejectByEscapeType As Integer
        None = 0
        CurrentRow = 1
        SelectedRows = 2
    End Enum
 
    Public Property RejectByEscape() As RejectByEscapeType
        Get
            Return _rejectbyescape
        End Get
        Set(ByVal value As RejectByEscapeType)
            _rejectbyescape = value
        End Set
    End Property
 
    Private Sub DataGridViewEx_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
        Try
            If e.KeyCode = Keys.Escape Then
                '編集モードではなくReadOnlyでもなければRejectChanges
                '(グリッドがReadOnlyのときはCurrentRowも自動的にReadOnlyになるのでCurrentRowだけで判定してOK)
                If (IsCurrentCellInEditMode = False) And (CurrentRow.ReadOnly = False) Then
                    Select Case _rejectbyescape
                        Case RejectByEscapeType.CurrentRow
                            DirectCast(Me.CurrentRow.DataBoundItem, DataRowView).Row.RejectChanges()
                        Case RejectByEscapeType.SelectedRows
                            For Each dgvr As DataGridViewRow In SelectedRows
                                DirectCast(dgvr.DataBoundItem, DataRowView).Row.RejectChanges()
                            Next
                    End Select
                End If
            End If
        Catch ex As Exception
            MessageBox.Show(ex.ToString & ex.Message)
        End Try
    End Sub
End Class
 

Microsoft Visual Studio International Pack 1.0

East Asia Numeric Formatting Library 数値データを日本語、繁体字中国語、簡体字中国語および韓国語における漢数字の文字列に変換します。
Japanese Kana Conversion Library ひらがな、カタカナ、半角カタカナの相互変換、およびローマ字の変換をします。
Japanese Text Alignment Library 日本語固有の均等割付を用いて文字列を描画します。
Japanese Yomi Auto-Completion Library 日本語IME における読みの入力に対応したオートコンプリート機能を提供するライブラリとサンプルのTextBox コントロールを提供します。

My.Settingsの構成ファイルの場所を取得する。

2008/03/25 検索語:exe.config、user.config、ApplicationSettingsBase
アプリケーション構成ファイル
System.AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
ユーザー構成ファイル
ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath
ネタ元:http://www.atmarkit.co.jp/fdotnet/dotnettips/558appsettings/appsettings.html
ちなみに同一記事にもかかれているが、2005ではローミングユーザーであってもローカルユーザーのユーザー構成ファイルが使われてしまうようだ。せっかくローミングにも対応するように設計したつもりだったけど意味無い・・・。
別課題:過去の設定ファイル消せないと気持ち悪い。

Partial Classをメインのクラスのツリー下に配置する

2008/03/24
projファイルの中から目的の分割クラスの記述を見つけ、DependentUpon行を追加すればOK。
<Compile Include="MainForm.Menu.vb">
  <DependentUpon>MainForm.vb</DependentUpon> '←この行を追加
  <SubType>Form</SubType>
</Compile>
SubTypeは消してもVisual Stdio上で一回開いて保存すると元に戻る。

C#→VB.netへのコード変換サービス

2008/03/24 http://codeconverter.sharpdevelop.net/Convert.aspx
使ってみた中ではコレが一番だった。

Visual Studio 2005 SP1 統合 installer の作成方法

再帰的にコントロールの親をたどって、ピリオド区切りでパスを返す関数

2008/01/21
例えばForm1のPanel1に乗っているTextbox1なら Form1.Panel1.TextBox1 と帰ってきます。
Public Function ControlPath(ByVal ctl As Control) As String
    Try
        If ctl.Parent Is Nothing Then
            Return ctl.Name
        Else
            Return ControlPath(ctl.Parent) & "." & ctl.Name
        End If
    Catch ex As Exception
        MessageBox.Show(ex.ToString)
        Return ""
    End Try
End Function

VBScriptのエラーコードメモ

2007/12/25 Descriptionが定義されていないものがある。一覧が見つけられない・・・。誰か教えて。
エラーコード 内容
-2147024843 たぶんネットワークパスが見つからないとき。

Visual Studio 2008 Express Edition

2007/12/18
ついにきました。まあいきなりインストールするわけにもいかないから、遊ぶのは正月休みですね。不具合情報の様子見でw
なんと窓の杜から落とせるよ。
http://www.forest.impress.co.jp/lib/stdy/program/progdevenv/vbexedition.html
……と思ったら違いました。ダウンロード先は「作者サイト」になってるのね。

チェックボックスでスプリットコンテナのパネルの表示をOn/Offする

2007/12/06
検索語:CheckBoxでSplitContainerのPanelをOn/Off、反転、True、False

SplitContainerのパネルを片側消したかったけど、Visibleでスプリッタが動いてくれないので「なんで?」と探したらPanel1Collapsed/Panel2Collapsedというわかりにくいプロパティでした。ヘルプには「縮小または展開するかどうかを決定する値を取得または設定します。」と書いてある。表現がわかりにくいっちゅうの。

で、チェックボックスをOnにしたときに表示、Offにしたときに非表示にしたいんだけど、CheckedとCollapsedの単純バインディングだと逆になってしまうので、Bindingオブジェクトの拡張クラスをつくってみた。

Private Class BindingReverseBoolean
    Inherits Binding
 
    Public Sub New(ByVal propertyName As String, ByVal dataSource As Object, ByVal dataMember As String)
        MyBase.New(propertyName, dataSource, dataMember, False, Windows.Forms.DataSourceUpdateMode.OnPropertyChanged)
    End Sub
 
    Private Sub BindingReverseBoolean_Format(ByVal sender As Object, ByVal e As System.Windows.Forms.ConvertEventArgs) Handles Me.Format
        e.Value = Not e.Value
    End Sub
 
    Private Sub BindingReverseBoolean_Parse(ByVal sender As Object, ByVal e As System.Windows.Forms.ConvertEventArgs) Handles Me.Parse
        e.Value = Not e.Value
    End Sub
End Class
で、FormのLoadでこんな感じに使います。
myCheckBox.DataBindings.Add(New BindingReverseBoolean("Checked", mySplitContainer, "Panel2Collapsed"))
どうもバインディングオブジェクトは
[Checked]⇒True=Format=False⇒[Collapsed]⇒False=Parse=True⇒[Checked]
こういう感じに動くようだ。2回値がセットされる感じ。

今回は自分で使うだけで、絶対にBoolean以外がこないのはわかっているのでエラー処理はなし。
余裕があれば汎用的なクラスにしたいので、プロパティの型チェックとかいれる予定。

配列をリストに変換する

2007/11/18
リストを配列に変換するのはToArrayで簡単。配列をリストに変換する方法がわからない・・・3時間ぐらい調べてやっと見つけた。
http://d.hatena.ne.jp/Seasons/searchdiary?word=*%5BC%23%5D
わかってみれば簡単でリストのコンストラクタに渡せばよいだけでした・・・
Dim myArray As String() = {"A","B","C"}
Dim myList As List(Of String) = New List(Of String)(myArray)
固定値の入ったリストを作るときもこのほうがラク。
つか、ちょっとデキる人は絶対わかってるよな。「リストを配列に変換する」で検索してどうにもひっかからないっていうのは何故。

型比較でハマる

2007/11/18
オブジェクトのプロパティを列挙する処理を書いていたら、PropertyTypeの型のチェックで
エラー	5	型 'System.Type' の式を型 'String' にすることはできません。
のエラーが出て、いろいろ書き換えてみてもどうにも通らない。
原因は「型の比較はTypeOfだ」という思い込みでした。
For Each pi As PropertyInfo In target.GetType.GetProperties
    Select Case True
        Case TypeOf pi.PropertyType Is String  '←ここがダメ
		...
        Case Else
		...
    End Select
Next
For Each pi As PropertyInfo In target.GetType.GetProperties
    Select Case True
        Case pi.PropertyType Is GetType(System.Byte)  '←これでOK
		...
        Case Else
		...
    End Select
Next
TypeOfはオブジェクトと型を比較するのね。型どうしの直接比較ならIsだけでよい。
気づかなかったのが恥ずかしい・・・。

NewGUIDを文字列にするときの引数

2007/11/10
よくわからなくなるのでメモ。xは16進数なので[0-9A-F]。
GUID.NewGUID.ToString("N") xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 32桁
GUID.NewGUID.ToString("D") xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ハイフンで区切られた 32 桁
GUID.NewGUID.ToString("B") {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} 中かっこで囲まれ、ハイフンで区切られた 32 桁
GUID.NewGUID.ToString("P") (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx) 丸かっこで囲まれ、ハイフンで区切られた 32 桁

My.Settingsに連結したコントロール間でChangedイベントで値をやり取りすると値が書き戻されることがある

2007/11/08
実際に起こったのはチェックボックスのChackedChangedでテキストボックスに値を書き込んだら、チェックボックスの値が再度My.Settingから読み出されて変更する前に戻ってしまう。
検索したらMy.Settingsの挙動不審がいくつか見つかるので、バインドしたコントロール間でやり取りはしないほうが無難。
2007/11/15 Microsoftにも正式文書がありました。
http://msdn2.microsoft.com/ja-jp/library/a65txexh(VS.80).aspx
現在、Windows フォームの一部のプロパティはバインドできません。わかりやすい例は ClientSize プロパティです。
このプロパティにバインディングすると、実行時に予期できない動作が発生します。
通常、設定をプログラムで保存して読み込むことでこの問題を解決できます。

DataSet中の複数のテーブルをAccessのように連結して扱う

2007/10/26
アクセスがクエリを元にフォームをつくれるので、同じことがVB.netでもできないかなと探していたら、DataTable間にリレーションを設定し、DataColumnのExpressionを設定することで実現できました。
Private relationTest As System.Data.DataRelation
 
Me.relationTest = New System.Data.DataRelation( _
	"relationTest", 
	New System.Data.DataColumn() {Me.tableA.ShohinCDColumn}, _
	New System.Data.DataColumn() {Me.tableB.ShohinCDColumn}, _
	false)
Me.Relations.Add(Me.relationTest)
Me.tableA.ShohinNameColumn.Expression = "Parent(rerarionTest).ShohinName"
 
DataGridViewの列で処理することばかり考えていて、DataTableそのものに列を追加するというのは、ちょっと思いつかなかったな。
いままでコードに対応する名称をDataGridView上で表示するのにわざわざコンボボックスを使っていたので、これでとてもラクになりました。
DataTableはアクセスのクエリの役目も果たしてくれるのですね。

ちなみにここにはコードで載せていますが、これはDataSetのDesiner.vbから拾ってきたもので、実際にはデザイナオンリー、ノンコーディングで実現できています。

継承コントロールをデザイナで削除すると「インデックスが範囲を超えています」のエラー

2007/10/10
検索語:コンストラクタ
Newの中でAddHandlerしたテキストボックスの継承コントロールで、デザイナで削除するときに
インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
パラメータ名: index
のエラーメッセージが出るようになってしまった。いろいろ調査した結果、原因はAddHandlerだと判明。
AddHandler DataBindings.CollectionChanged, AddressOf DataBindings_CollectionChanged

最終的にはDisposeの中でRemoveHandlerを書くことで解決。
RemoveHandler DataBindings.CollectionChanged, AddressOf DataBindings_CollectionChanged

似たようなことをやっている他の継承コントロールでは起きないので、解放するリソースの種類や内部処理に依存しそう。
まあ「Disposeするときにきちんとすべてのリソースを解放しましょう」というのは当たり前のことだから、いままでAddHandlerの後始末をやっていなかったのがダメなんでしょう。たぶん。
「AddHandlerしたら必ずRemoveHandlerしましょう」とか、教えてくれる人もいなかったし、どこかに書いてあるのかなぁ。

継承したテキストボックスをフォームから削除しようとすると、エラーが出て削除されない。

2007/08/27
インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
プロジェクトを開きなおすときちんと消えている。
継承したコントロールの中でやっている処理の問題だった。詳細な内容は後でかこう。

ComboBoxに連結したDataTableが意図せずに変更される

2007/10/04 検索語:コンボボックス/DataTable/DataView/DataSource/Bind/データが変わる
DataTableにコンボボックスを連結したときに、既存データにコンボボックスに存在しない値が入っていると、レコードのCurrent時にコンボボックスの先頭の値に書き換えられてしまう。
FormattingEnabled をTrueにすることで解消できる。FormatString を設定する必要はない。

Express Edition ではセットアップ用のmsiはつくれない

2007/08/07 確実な情報が見つからないけど、つくれないっぽい。
↓こういうの見つけた。んー、個人でここまで踏み込むかどうするか。会社でやる分にはVS.net使えるからなぁ。
WiXではじめるWindows Installer作成入門

ComboBoxにはDoubleClickイベントがないのね

2007/08/24 コンボボックスでDoubleClickイベントを使おうかと思ったらありませんでした。

CSVの読み込み

日本語の露出が少ないけどXmlCsvReaderというのがよさそう。テストしてみよう。

相手先別に添付ファイルを変更するメール送信ソフトを作ってみよう

2007/07/26
VB.netでメール送信するのは簡単そう。相手のアドレスと添付ファイルのリストから、メール送信するソフトを作ってみよう。
http://www.atmarkit.co.jp/fdotnet/dotnettips/017sendmail/sendmail.html
↑このアドレスは2003で、2005からはクラスが変わっていました。
http://www.microsoft.com/japan/msdn/vbasic/migration/tips/netmail/
2007/07/28 うーん、SmtpClient はいろいろ問題がありそうな。POP before SMTPとかも自作しなきゃいかんし。
http://support.microsoft.com/default.aspx/KB/927858
2007/07/28 商用利用も含めてフリーライセンスのよさそうなライブラリを発見。
.NET用メール送受信クラスライブラリ (TKMP.DLL)
ライセンスについて http://uwa.potetihouse.com/bbs/patio.cgi?mode=view&no=139
自分で組めるようにもなりたいけど、とりあえず利用させていただいて、少しづつ力をつけよう。

コンボボックスに高速にデータをBindする

2007/07/24
DataSourceよりもValueMemberとDisplayMemeberを先に指定したほうが速いようです。
設定するたびにリクエリがかかる感じですね。
特に件数の多いテーブルをBindするときに効果的です。

DataSourceを先に設定した場合

DebugTimer.WriteLine("Testスタート")
cboSample.DataSource = New DataView(dt)          '←先に設定
DebugTimer.WriteLine("DataSourceをセット")
cboSample.ValueMember = "連結したい列名"
DebugTimer.WriteLine("ValueMemberをセット")
cboSample.DisplayMember = "表示したい列名"
DebugTimer.WriteLine("DisplayMemberをセット")
 
MEMO 00:00:000 00:00:000 Testスタート
MEMO 00:00:272 00:00:272 DataSourceをセット
MEMO 00:00:540 00:00:268 ValueMemberをセット
MEMO 00:00:808 00:00:268 DisplayMemberをセット

DataSourceを後に設定した場合

DebugTimer.WriteLine("Testスタート")
cboSample.ValueMember = "連結したい列名"
DebugTimer.WriteLine("ValueMemberをセット")
cboSample.DisplayMember = "表示したい列名"
DebugTimer.WriteLine("DisplayMemberをセット")
cboSample.DataSource = New DataView(dt)          '←後に設定
DebugTimer.WriteLine("DataSourceをセット")
 
MEMO 00:00:000 00:00:000 Testスタート
MEMO 00:00:000 00:00:000 ValueMemberをセット
MEMO 00:00:000 00:00:000 DisplayMemberをセット
MEMO 00:00:296 00:00:296 DataSourceをセット

Microsoft Win32 と Microsoft .NET Framework API との対応

2005でデザイナから自動生成されるDataTableでのDBNull

2007/07/16
XというフィールドにDBNullが来るよねと思ってIsDBNull(X)で判定しようとしたら蹴られた。
なんで?と思ってクラスを見たら、テーブルのメソッドにIsXNullっていうのが作られてた。
なるほど。Nullの可能性のあるフィールドはこれで判断しろと。

タイマーとメッセージボックス

2007/07/16
メッセージボックスが出ているあいだもタイマーは動き続けているので、処理によっては固まる。注意。

ワークステーションのロック

2007/07/16 カンタンだった。
System.Diagnostics.Process.Start("rundll32.exe", "user32.dll,LockWorkStation")
2007/07/16 ロックかけるのは簡単だけど、ロックされているかどうかの判断が難しい。つか標準ではできない。
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200612/06120018.txt
Microsoft.Win32.SystemEventsのSessionSwitchを使うことで、
ロック開始のイベントとロック終了のイベントを受け取ることができます。
との情報を発見したので、ロック状態を管理しつつ、ロックをかけてくれるクラスを作成。 → WorkStationLockController
念のためsingletonをとっておく。singletonについては → http://hccweb1.bai.ne.jp/tsune-1/VisualBasic/singleton.html
ちなみにsingletonをグローバル変数的に使うのはよくないというのは心しておく。
ワークステーションのロックについて調べていたら突き当たったサイト → http://www7a.biglobe.ne.jp/~lshen/EternalWindows/
GINAとか珍しいあたりをわかりやすく書いてくれてる。
フォアグラウンドウインドウを判定するのってAPI使うしかないのかなぁ。 → http://iseebi.half-done.net/?TechDoc%2FDetectionFullscreen

LDAPとActive Directoryの要素の比較

最大長 LDAP Active Directory
名 (LDAP CN) 256 64
ミドル・ネーム 128 64
128 64
レジストリー UID (LDAP DN) 1024 2048
ユーザー・パスワード 制限無し 256
ユーザー記述 1024 1024
グループ名 256
グループ記述 1024 1024
シングル・サインオン・リソース名 240 256
シングル・サインオン・リソース記述 1024 1024
シングル・サインオン・ユーザー ID 240 256
シングル・サインオン・パスワード 制限無し 256
シングル・サインオン・グループ名 240 256
シングル・サインオン・グループ記述 1024 1024
アクション名 1 1
アクション記述、アクション・タイプ 制限無し 制限無し
オブジェクト名、オブジェクト・スペース名、ACL 名、POP 名 制限無し 制限無し
オブジェクト記述、オブジェクト・スペース記述、ACL 記述、POP 記述 制限無し 制限無し

DirectorySearcher手ごわい

2007/07/13
http://www.microsoft.com/japan/msdn/community/gdn/ShowPost-33574.htm
グループとユーザーの階層をノード的に取得しようとしたけど、手ごわい。
なんだよMemberofプロパティとかPrimaryGroupが取れないとか。
Microsoftのヘルプじゃまったくダメで、LDAPの仕様とか理解しないといけないところがツラい・・・

System.DirectoryServices.DirectoryEntry.SchemaClassNameの一覧

2007/07/12
※とりあえず私が使ったものをメモっていきます。
ユーザー User
グループ Group
コンピュータ Computer
サービス Service
検索をかけても一覧が見つからない・・・誰か教えて。

SelectCommandでデータ書き込むストアド指定するとコミットされない・・・んー

2007/07/10
DataAdapterのSelectCommandにデータの更新ありのストアドを投げると、戻ってきた結果は正しいのにデータベースには反映されてないみたい。
んー、いちいちコミットいれなきゃダメ?
→mdfファイルが毎回コピーされてしまうためでした。
http://www.atmarkit.co.jp/fdotnet/dotnettips/532dbfilecopy/dbfilecopy.html

2005のヘルプにCrystal Reportのヘルプを追加とか

TreeView使ってみた

2007/07/04
便利。同じTreeNodeオブジェクトを別のツリーに追加することはできなかった。

アップキャストとダウンキャスト

2007/06/14
アップキャスト 派生クラス→基本クラス 常にOK
ダウンキャスト 基本クラス→派生クラス やらないほうがよい。できないこともある。
ダウンキャストについてはちょっと勉強したほうがよさそうだ。

IIFとdecimalでハマる

2007/06/12
DataTable.ColumnのExpressionを使用していて、floatだったフィールドをdecimalに変更したら何故か0除算のエラー。
IIF([分母]=0,0,[分子]/[分母])
とやって0除算をしてないはずなのに・・・・・・と半日ハマる。結論は
IIFは真も偽も計算してから値を返すから
IIFは普段は危険だから使わないんだけど、floatのときにエラーにならなかったので見落としました。
floatは0除算でエラーを返さないのね。
でもExpressionの中ってIIFしか条件式が使えない。やむをえず
[分子]/CAST([分母],'System.Double')
として回避。

GrapeCity FlexGrid for .NET 2.0J

ダメだこれ。もうイヤ。
何がダメって、ColumnオブジェクトのNameプロパティが連結先のDataTableの列名。
で、複数のColumnに同じNameが設定できる。だからIndex以外で列を特定する術がない。
なのに、列位置を移動するとIndexが変わる。
頼むからNameは固有値にしてMappingName を指定させてくれ。
誰だこんなコントロール使うことにしたのは。二度と使わない。
いや、最新は4.0Jだから、よくなってるのかもしれないけれど。

VB.Netに関する資料

2007/04/22 オブジェクト倶楽部 http://www.objectclub.jp/
ここのトレーニングテキストが死ぬほど役立つ。入門用とリファレンスのちょうど中間あたりの本になりにくいあたりが解説されている。
2007/05/13 ちょっと見ようと思ったら見つけられない。C#のページにありました。
http://www.objectclub.jp/technicaldoc/c/training.pdf
2007/04/29 .NETでの正規表現の使用法 http://japan.internet.com/column/developer/20050822/28.html
2007/05/01 コンテキストメニューまわり http://vbdotnet.fc2web.com/vbnet/control/ContextMenuMenu.htm

ArrayListとList

2007/04/22
自作クラスのコレクションを作れるに違いないと思って、ArrayListを調べて2時間。
どうしても型指定したコレクションがつくれないよー(。´Д⊂)
と、泣きそうになったところでListに気がつく。
あまりにも最初にArrayListに慣れ親しんだために、それ以外思い浮かばなかった失敗。
2007/05/24
Listって.net 2005(Framework 2.0)からなので。自宅は2005、会社は2003なので、会社で使おうとして使えなくてがっかり。

プロパティにオブジェクトを設定したときにNewのタイミング

2007/04/22
プロパティ用のローカル変数に
Private _objectname As Objecttype
と宣言していてハマる。
Private _objectname As New Objecttype
きちんとインスタンス意識しないとね。

自分自身と同じ型のコレクションをプロパティに持つ

   Private _childnodes As New List(Of LogNode)
   Public Property ChildNodes() As List(Of LogNode)
       Get
           Return _childnodes
       End Get
       Set(ByVal value As List(Of LogNode))
           _childnodes = value
       End Set
   End Property

2007/04/22 とりあえず2日間ざっくり勉強して2日間ざくざく組んだら、少し勘が働いてきた。
言語って、あるレベルまでいかないと、目の前が開けないよね。一回開けてくると調査スピードも速くなる。

DateTimeメモ

2007/04/27
DateTimeの中身は#1/1/0 00:00:00#(西暦0年1月1日)からの経過ミリ秒
javascriptと値がずれるなと思ったら、javascriptは#1970/01/01 00:00:00#からの経過ミリ秒でした。
で、それでも誤差が32400ミリ秒出るので何かと思ったら、32400/60/60=9、ということで標準時との差。

再帰型のクラスでちょっとはまったこと

クラスを通過するたびにカウントアップするような引数は参照渡しすること。

ライブラリメモ

ファイルパスの分解 System.Io.Path ディレクトリ名はディレクトリを指定すればFileNameで取得できる
.GetExtension 戻り値はピリオド付き
ファイルの検索 System.Io.Directory 戻り値はString()
ファイル情報 My.Computer.FileSystem.GetFileInfo
.Length ファイルサイズの単位はバイト
正規表現 System.Text.RegularExpressions Regex.Match(Path.GetFileNameWithoutExtension(file), "^\d{1,5}$").ToString
後方参照で置換 .Replace(対象文字列,"<a href="http://~">(.*?)</a>","$1")
ファイル名に使えない文字を置換 mystring=Regex.Replace(mystring, "[\\\/:,;*?""<>|]", "_")
文字コード System.Text.Encoding.GetEncoding("SHIFT-JIS")

LinkLabel

なんかハイパーリンクを使いたかったのでざくっと調べたらLinkLabelっていうコントロールがある。
テキストいれればクリックで勝手にブラウザ呼んでくれるのかと思ったら、呼び出しも書かなきゃいけないし、訪問済みかどうかも自分で設定しなきゃいけないみたい。不便。自分で変更できるのはありがたいとして、最初からブラウザと同期してくれてもいいと思うんだけど、なんでだろう。
まあ複数リンクも扱えるけど、もっとこう、さくっと。

ハッシュテーブル

2007/05/16
Addは使わなくても良い。
指定したキーがハッシュテーブルに存在しない場合には、新しい要素として登録される。
キーがすでに存在する場合には、インデクサではそのキーに対応する値が置き換えられるが、Addメソッドでは例外が発生する。

With Nothingを使って変数を局所化


Sub Hoge
 With Nothing
  dim i as integer
  処理  
 End With

 With Nothing
  dim i as integer
  処理  
 End With
End Sub

みたいな形で変数のスコープを短くして使いまわせるという話。

共有メンバ

2007/05/17 ヘルプより
既定では、クラスのデータはクラスの各インスタンスに固有になります。ただし、1 つのクラスから作成したすべてのオブジェクト間で、1 つのデータ項目を共有する方が都合のよい場合もあります。このような場合には、Shared 修飾子を使用して、変数の同じ値をクラス内のすべてのインスタンスで共有できるようにします (共有メンバは、他のプログラミング言語では "静的メンバ" と呼ばれる場合もあります)。共有メソッドは、事前にクラスのインスタンスを作成しなくても、クラス名を使用して直接呼び出すことができます

よくつかうリンク


comment

このページの記述で聞きたいこととか間違ってることとかありましたらコメントを。
名前:
コメント:

すべてのコメントを見る

最終更新:2010年04月14日 15:31