はじめに
前回に引き続いて,
Officeアドインで非同期処理
前回でほとんどの準備を行いましたが,
ネットワークアクセスなど時間のかかる処理は,
IMessageFilterの実装
まず,
IMessageFilter.
Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices
<ComImport, ComConversionLoss, InterfaceType(1S), Guid("00000016-0000-0000-C000-000000000046")>
Public Interface IMessageFilter
<PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function HandleInComingCall(dwCallType As UInteger, htaskCaller As IntPtr, dwTickCount As UInteger, lpInterfaceInfo As IntPtr) As Integer
<PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function RetryRejectedCall(htaskCallee As IntPtr, dwTickCount As UInteger, dwRejectType As UInteger) As Integer
<PreserveSig, MethodImpl(MethodImplOptions.InternalCall, MethodCodeType:=MethodCodeType.Runtime)> _
Function MessagePending(htaskCallee As IntPtr, dwTickCount As UInteger, dwPendingType As UInteger) As Integer
End Interface
このインターフェイスをThisAddInクラスで実装します。次のようにImplementsステートメントでIMessageFilterインターフェイスの実装を指定します。
ThisAddIn.
Public Class ThisAddIn
Implements IMessageFilter
'(省略)
Public Function HandleInComingCall(dwCallType As UInteger, htaskCaller As IntPtr, dwTickCount As UInteger, lpInterfaceInfo As IntPtr) As Integer Implements IMessageFilter.HandleInComingCall
End Function
Public Function MessagePending(htaskCallee As IntPtr, dwTickCount As UInteger, dwPendingType As UInteger) As Integer Implements IMessageFilter.MessagePending
End Function
Public Function RetryRejectedCall(htaskCallee As IntPtr, dwTickCount As UInteger, dwRejectType As UInteger) As Integer Implements IMessageFilter.RetryRejectedCall
End Function
End Class
IMessageFilterインターフェイスは,
Private Const SERVERCALL_ISHANDLED As Integer = 0
Public Function HandleInComingCall(dwCallType As UInteger, htaskCaller As IntPtr, dwTickCount As UInteger, lpInterfaceInfo As IntPtr) As Integer Implements IMessageFilter.HandleInComingCall
Return SERVERCALL_ISHANDLED
End Function
Officeアプリがすぐに要求した処理を行えない場合,
通常はダイアログを表示して,
Private Const SERVERCALL_RETRYLATER As Integer = 2
Public Function RetryRejectedCall(htaskCallee As IntPtr, dwTickCount As UInteger, dwRejectType As UInteger) As Integer Implements IMessageFilter.RetryRejectedCall
If dwRejectType = SERVERCALL_RETRYLATER Then
Return 100
Else
Return -1
End If
End Function
MessagePending関数は,
Private Const PENDINGMSG_WAITDEFPROCESS As Integer = 2
Public Function MessagePending(htaskCallee As IntPtr, dwTickCount As UInteger, dwPendingType As UInteger) As Integer Implements IMessageFilter.MessagePending
Return PENDINGMSG_WAITDEFPROCESS
End Function
以上で,
MessageFilterの登録
IMessageFilterインターフェイスを実装しただけでは意味がありません。非同期処理を行うときに,
次のようにThisAddInクラスに定義を追加しましょう。
' (ファイル先頭に Imports System.Runtime.InteropServices も追加すること)
<DllImport("ole32.dll")>
Private Shared Function CoRegisterMessageFilter(lpMessageFilter As IMessageFilter, ByRef lplpMessageFilter As IMessageFilter) As Integer
End Function
続いて,
Private Sub GetUserInfo(session As LiveConnectSession)
Dim previousMessageFilter As IMessageFilter = Nothing
CoRegisterMessageFilter(Me, previousMessageFilter) ' 登録
Me.LiveConnectClient = New LiveConnectClient(session)
Globals.Ribbons.MainRibbon.SignInButton.Enabled = False
Try
' (ここの内容は前回と同じ)
Catch ex As Exception
' (例外は無視)
' 再度サインインできるようボタンを有効化
Globals.Ribbons.MainRibbon.SignInButton.Enabled = True
Finally
CoRegisterMessageFilter(Nothing, previousMessageFilter) ' 解除
End Try
End Sub
以上で,