| [.NET]イベント付きCOMオブジェクトの解放 / 2009年07月28日(火)
|
VB.NET から イベント付き COM オブジェクトを扱う場合の注意点として覚書。
KB317109やKB306682 などでは、使用した 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イメージでの提供となっています。
続きを読む...
|
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)
|
|
|