コミュニティでの活動の履歴として、自身(Orator/魔界の仮面弁士)が掲示板・Mailing List・Newsgroup等へ発言した内容の中で、再利用できそうな物を拾い出して、掲載しています。

« blog | Main | Jet/Access »
[.NET]イベント付きCOMオブジェクトの解放 / 2009年07月28日(火)

VB.NET から イベント付き COM オブジェクトを扱う場合の注意点として覚書。

KB317109KB306682 などでは、使用した COM オブジェクトの後始末として、Marshal.ReleaseComObject( object ) の呼び出しと、Nothing の代入コードが紹介されています。

それ自体は間違いでは無いのですが、その変数がイベントを受け取るコードであった場合には要注意です。

たとえば下記を実行すると、フォーム終了時の Nothing 代入の時点で、[TargetInvocationException]が発生します。


Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices
Public Class Form1
  Private WithEvents xlApp As Excel.Application

  Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
    If xlApp IsNot Nothing Then
      'xlApp.Quit()
      If Marshal.IsComObject(xlApp) Then
        Marshal.ReleaseComObject(xlApp)
      End If
      xlApp = Nothing    '★
    End If
  End Sub

  Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    xlApp = New Excel.ApplicationClass()
    xlApp.Visible = True
  End Sub

  Private Sub xlApp_NewWorkbook(Wb As Excel.Workbook) Handles xlApp.NewWorkbook
    MsgBox("新しいブック")
  End Sub
End Class

このエラーは、Handles xlApp.NewWorkbok の部分が原因で引き起こされています。COM オブジェクトに対する Handles 句を削ってしまえば、Nothing を代入してもエラーは発生しません。

Private Sub xlApp_NewWorkbook(Wb As Excel.Workbook)  'Handles xlApp.NewWorkbook
  MsgBox("新しいブック")
End Sub

しかし、そのままだとイベントが使えません。そのため、AddHandler を使う方法に切り替えます。

このようにしておけば、Marshal.ReleaseComObject 後の Nothing 代入がエラーになる事もありません。

'Private WithEvents xlApp As Excel.Application
Private xlApp As Excel.Application
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    xlApp = New Excel.ApplicationClass()
    AddHandler xlApp.NewWorkbook, AddressOf xlApp_NewWorkbook    
    xlApp.Visible = True
End Sub

 
Posted at 00:42 / .NET / この記事のURL
コメント(0)
[VB2005]WebBrowser上のスクリプト ダイアログを制御する / 2008年10月05日(日)

HTMLページ上に表示される、メッセージボックスを制御するサンプルです。

JavaScript 等から alert、confirm、prompt を呼び出していたり、あるいは VBScript で MsgBox を呼び出しているサイト等が対象となります。


[10/05/2008]VBレスキュー(VB.NET用掲示板)

ソースは、下記からダウンロードして下さい。

http://www.vb-user.net/junk/replySamples/2008.10.05.13.35/8274.zip


メッセージの表示をカスタマイズするには、WebBrowser コントロールのホストが、IDocHostShowUI::ShowMessageを実装してやる必要があります。

そして今回のサンプルでは、IDocHostShowUI インターフェイスを実装した独自クラス WebBrowserController を作成しています。

これは、メッセージが表示されるタイミングで ShowMessage というイベントが発生するよう実装させてあり、下記のようにして利用することができます。

Private Sub WebBrowerCtrl_ShowMessage(ByVal sender As Object, ByVal e As WebBrowserController.ShowMessageEventArgs) Handles WebBrowerCtrl.ShowMessage
	' 任意のメッセージに差し替えたり、メッセージそのものを非表示にしても OK。
	Dim ret As MsgBoxResult = MsgBox(e.Text, e.Type, e.Caption)

	' メッセージボックスで押されたボタンを返す。
	e.Result = ret

	' 標準のダイアログを表示させないなら True、表示させるなら False
	e.Handled = True
End Sub

 
Posted at 18:05 / .NET / この記事のURL
コメント(0)
[.NET]AxMSHFlexGridでMouseWheelイベントを実装 / 2008年02月18日(月)

「AxMshFlexGridでホイールが効かない」という質問を受けて作ったものです。VB2005を前提としたコードになっています。


[02/18/2008]VBレスキュー(VB.NET掲示板)

Partial Public Class Form1
	Public Class SampleGrid
		Inherits AxMSHierarchicalFlexGridLib.AxMSHFlexGrid
		Public Shadows Event MouseWheel As MouseEventHandler
		Protected Overrides Sub OnMouseWheel(ByVal e As MouseEventArgs)
			RaiseEvent MouseWheel(Me, e)
			MyBase.OnMouseWheel(e)
		End Sub
	End Class

	Private WithEvents AxMSHFlexGrid1 As SampleGrid
	Private Sub Form1_Load(ByVal sender As System.Object, _
	  ByVal e As System.EventArgs) Handles MyBase.Load
		AxMSHFlexGrid1 = New SampleGrid()
		AxMSHFlexGrid1.Dock = DockStyle.Fill
		Controls.Add(AxMSHFlexGrid1)

		FillSampleData(AxMSHFlexGrid1)
	End Sub

	Private Sub AxMSHFlexGrid1_MouseWheel(ByVal sender As Object, _
	  ByVal e As MouseEventArgs) Handles AxMSHFlexGrid1.MouseWheel
		Dim row As Integer = AxMSHFlexGrid1.TopRow - _
			(e.Delta \ SystemInformation.MouseWheelScrollDelta)
		If row < AxMSHFlexGrid1.FixedRows Then
			row = AxMSHFlexGrid1.FixedRows
		ElseIf row > AxMSHFlexGrid1.Rows - 1 Then
			row = AxMSHFlexGrid1.Rows - 1
		End If
		AxMSHFlexGrid1.TopRow = row
	End Sub

	Private Shared Sub FillSampleData( _
	  ByVal grid As AxMSHierarchicalFlexGridLib.AxMSHFlexGrid)
		With grid
			.Rows = 200
			'.Cols = 20
			.set_Cols(20)
			Dim Cells As New System.Text.StringBuilder()
			For row As Integer = 0 To 199
				For col As Integer = 0 To 19
					Cells.Append(String.Format("{0,3}-{1,3}", row, col))
					Cells.Append(vbTab)
				Next
				Cells.AppendLine()
			Next
			.Row = 0
			.Col = 0
			.RowSel = 199
			.ColSel = 19
			.Clip = Cells.ToString()
			.RowSel = 0
			.ColSel = 0
		End With
	End Sub
End Class

 
Posted at 22:02 / .NET / この記事のURL
コメント(0)
[.NET]CodeDOMで多次元配列の作成 / 2008年02月06日(水)

CodeDOM で『Dim Test(3, 2) As Integer』のような宣言を行おうにも、CodeArrayCreateExpression クラスは 1 次元配列しか作成できない…という話があったので、Array.CreateInstance を使った回避コードを作ってみました。


[02/06/2008]Programming Library(VB初心者掲示板)

Dim ArrayName As String = "Test"
Dim ArrayMaxIndex1 As Integer = 3
Dim ArrayMaxIndex2 As Integer = 2

Dim arrayInstance As New CodeMethodInvokeExpression( _
	New CodeTypeReferenceExpression(GetType(Array)), "CreateInstance", _
	New CodeTypeOfExpression(New CodeTypeReference(GetType(Integer))), _
	New CodePrimitiveExpression(ArrayMaxIndex1 + 1), _
	New CodePrimitiveExpression(ArrayMaxIndex2 + 1))

Dim variable As New CodeVariableDeclarationStatement( _
	GetType(Integer(,)), ArrayName, _
	New CodeCastExpression(GetType(Integer(,)), arrayInstance))

Dim statements As New CodeStatementCollection()
statements.Add(New CodeCommentStatement(String.Format("配列{0}の宣言", ArrayName)))
statements.Add(variable)

Using sw As New StringWriter()
	For Each language As String In "C#,VisualBasic,JScript,VJ#,C++".Split(",")
		Dim provider As CodeDomProvider = Nothing
		Try
			provider = CodeDomProvider.CreateProvider(language)
			If Not provider.Supports(GeneratorSupport.MultidimensionalArrays) Then
				sw.WriteLine("★{0} は多次元配列をサポートしていません。", language)
			End If
			sw.WriteLine("☆{0} として生成されたコード", language)
		Catch ex As Exception
			sw.WriteLine("★{0} のコードは生成できません。", language)
			sw.WriteLine()
			Continue For
		End Try
		For Each s As CodeStatement In statements
			provider.GenerateCodeFromStatement(s, sw, Nothing)
		Next
		sw.WriteLine()
	Next

	Dim GeneratedSource As String = sw.ToString()
	Clipboard.SetText(GeneratedSource)
	TextBox1.Text = GeneratedSource
End Using

続きを読む...  
Posted at 22:43 / .NET / この記事のURL
コメント(0)
日本語版 Visual Studio 2008 登場! / 2007年12月14日(金)
Visual Studio 2008 日本語版の開発が完了。2 月より販売を開始

ついに、待望の VS2008 日本語版 の登場です。

パッケージ販売は 2008年2月8日からのようですが、MSDN Subscription の契約レベル次第では、既にダウンロードにて入手可能です。(約 4.5GB です。エディションによって異なりますが)

なお、来週18日には、無償版の Visual Studio 2008 Express Edition 日本語版もダウンロード可能になるとのことです。

続きを読む...  
Posted at 14:24 / .NET / この記事のURL
コメント(0)
[.NET]DateTimePickerの最大値に関する問題点 / 2007年05月10日(木)

DateTimePicker クラス に指定できる最大の日付値は、MaxDate プロパティで変更可能です。
そして、MaxDate プロパティに指定できる最大値は、MaximumDateTime フィールドの値です。


しかし、ここには幾つかの問題が存在しているようです。


SDK を見てみると、DateTimePicker.MaxDateTime フィールド について、
日付の最大値は 12/31/9998 23:59:59 に設定されます。
と記されています。9999 年ではないようですね。


では実際に、VB2005 を使って、その日付を指定してみるとどうなるでしょう。

なんと、最大値が設定される事はなく、かわりに ArgumentOutOfRangeException 例外が発生します。

DateTimePicker1.MaxDate = #12/31/9998 23:59:59#

エラーメッセージを見ると、本当の最大値は、9998/12/31 00:00:00.0000000 とあります。
実際、メッセージにある日付を指定してみると、今度は無事に設定できます。

DateTimePicker1.MaxDate = #12/31/9998 00:00:00#  'OK

どうやら、ドキュメントの記述が間違っているようですね。


さて。

時刻部の微妙な問題はあれど、最大値が9998年12月31日ちょうど、という事はわかりました。


となると、日付型の最大値である、9999/12/31 23:59:59.9999999 は設定できないはずです。
こちらも実験してみましょう。


Dim dt As Date '= DateTimePicker.MaximumDateTime
dt = Date.MaxValue
DateTimePicker1.MaxDate = dt            'OK
DateTimePicker1.MaxDate = DateTime.Now  'OK
DateTimePicker1.MaxDate = dt            '例外


最初の 1 回だけ、DateTime.MaxValue が設定できてしまいましたが、これはおかしいですね。
本来であれば設定できない値のはずです。


しかも、一度別の値にしてから再設定すると、今度はエラーが発生するのです。




調べてみると、どうやら MaxDate プロパティの内部的な初期値が、本来設定すべき DateTimePicker.MaximumDateTime という値ではなく、DateTime.MaxValue になってしまっているために起こる現象のようです。

最初の一回目は、「初期値と同じ値を入れたので、内部値が変化せず、エラーにならなかった」わけですね。


 
Posted at 22:06 / .NET / この記事のURL
コメント(2)
Express Edition 提供開始 / 2005年12月16日(金)

昨日から、Visual Studio 2005 Express Edition 日本語版の提供が開始されています。

今なら、無償でダウンロードする事ができるようです。(1年間限定らしいですが)


ISOイメージでの提供となっています。

ソフトウェア サイズ
Visual Web Developer 2005 Express Edition 586,284 KB
Visual Basic 2005 Express Edition 578,722 KB
Visual C# 2005 Express Edition 575,234 KB
Visual C++ 2005 Express Edition 611,540 KB

続きを読む...  
Posted at 09:02 / .NET / この記事のURL
コメント(0)
[.NET]System.IO.Path.Combineでコロンが許可されている理由 / 2005年10月17日(月)

.NET Framework の「System.IO.Path.Combineメソッド」で使える文字についてです。


川俣さんの技術雑記に、このような検証と考察がありました。

":"ですが、これが良く分かりません。":"はドライブ名などの区切り文字であって、これをファイル名に許す必然性が分かりません。"\\.\C:"のような表記に対応するために許しているとも考えられますが、おそらくドライブ表記が2回出てくるパスは無いような気がするので(根拠無し)、既に先頭に"c:"が付いているパス名にもう1回":"が入るのは不正なパスであるような気がします。しかし、Combineメソッドは例外を投げる対象としていません。

実は、NTFSでフォーマットされたディスクに対しては、ドライブ文字区切り以外にてコロン":"を含むパスがサポートされており、FileSystemObjectや、CreateFile API などから利用する事が可能です。

("C:\MyFile.TXT:MyData"のようなパスがありうる)

もしかしたら、そのことに関係した仕様になっているのかもしれませんね。


参考リンク

VB.NETでの実験サンプル。


 
Posted at 12:06 / .NET / この記事のURL
コメント(4)
[VB.NET] 16進表記→色名表記へ変換 / 2005年06月30日(木)

「#FF0000 → Red」のように、HTMLの16進表記を、色名表記に変換するサンプルです。


[06/30/2005]VB初心者友の会(超初心者専用Q&A掲示板)

これ自体は.NET Compact Framework用のサンプルですが、.NET Frameworkでも利用可能です。

Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
	Me.Button1.Text = "変換"
	Me.TextBox1.Text = "#789"
End Sub

Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
	Me.Text = ToColorName(Me.TextBox1.Text)
End Sub

'『Imports System.Drawing, System.Reflection』が必要です。
Public Shared Function ToColorName(ByVal htmlColor As String) As String
	Dim colorName As String = htmlColor
	Dim C As Color
	Dim _htmlColor As Color = FromHtmlColor(htmlColor)
	For Each P As PropertyInfo In GetType(Color).GetProperties(BindingFlags.IgnoreCase Or BindingFlags.GetProperty Or BindingFlags.Static Or BindingFlags.Public)
		'If _htmlColor.Equals(P.GetValue(C, Nothing)) Then
		If _htmlColor.ToArgb() = DirectCast(P.GetValue(C, Nothing), Color).ToArgb() Then
			colorName = P.Name
			Exit For
		End If
	Next
	Return colorName
End Function

Private Shared Function FromHtmlColor(ByVal htmlColor As String) As Color
	Dim _color As Color = Color.Empty
	If Len(htmlColor) > 0 Then
		If (htmlColor.Chars(0) = "#"c) AndAlso ((htmlColor.Length = 7) OrElse (htmlColor.Length = 4)) Then
			If htmlColor.Length = 7 Then
				_color = Color.FromArgb(Convert.ToInt32(htmlColor.Substring(1, 2), 16), Convert.ToInt32(htmlColor.Substring(3, 2), 16), Convert.ToInt32(htmlColor.Substring(5, 2), 16))
			Else
				_color = Color.FromArgb(Convert.ToInt32(New String(htmlColor.Chars(1), 2), 16), Convert.ToInt32(New String(htmlColor.Chars(2), 2), 16), Convert.ToInt32(New String(htmlColor.Chars(3), 2), 16))
			End If
		End If
	End If
	Return _color
End Function

 
Posted at 21:18 / .NET / この記事のURL
コメント(0)
[VB.NET] 定義済みの色の指定した名前から Color 構造体を作成 / 2004年12月21日(火)

"Red"、"Transparent"などの定義色名をColor構造体に変換します。


なお、これは.NET Compact Framework用のサンプルです。.NET Frameworkでも利用可能ですが、その場合は、Color.FromNameメソッドで十分でしょう。

'『Imports System.Drawing, System.Reflection』が必要です。
Public Shared Function GetColorFromName(ByVal Name As String) As Color
	Dim C As Color
	Dim P As PropertyInfo
	P = GetType(SystemColors).GetProperty(Name, BindingFlags.IgnoreCase Or BindingFlags.GetProperty Or BindingFlags.Static Or BindingFlags.Public)
	If Not P Is Nothing Then
		Return CType(P.GetValue(C, Nothing), Color)
	End If
	P = GetType(Color).GetProperty(Name, BindingFlags.IgnoreCase Or BindingFlags.GetProperty Or BindingFlags.Static Or BindingFlags.Public)
	If Not P Is Nothing Then
		Return CType(P.GetValue(C, Nothing), Color)
	End If
	Return Color.Empty
End Function

 
Posted at 11:06 / .NET / この記事のURL
コメント(0)
P R

Microsoft Most Valuable Professional, Visual Developer - Visual BasicMSMVP for Visual Basic


| 次へ
Global Media Online INC.