Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1529

Inter Process Communication between Outlook VSTO addin (in VB.NET) and VB6 App

$
0
0
I wrote applications in VB6, and an Outlook VSTO addin (in VB.NET) that communicate directly with the VB6 App.
Based on email in Outlook, I wanted to send information to be shown in the VB6 app.
2 ways to do it

1) communication with files (and the VB6 pool for the files), but it is not the best way to do it.

2) Using IPC (Inter Process Communication) where the VSTO send a message to the VB6 App.

So here is the code of the VSTO addin that send a message to the VB6 App

Code:

Imports System.Runtime.InteropServices

Friend Module Module_Communication

    Private Const WM_COPYDATA As Integer = &H4A

    <StructLayout(LayoutKind.Sequential)>
    Private Structure COPYDATASTRUCT
        Public dwData As IntPtr
        Public cbData As Integer
        Public lpData As String
    End Structure

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Private Function FindWindow(
        ByVal lpClassName As String,
        ByVal lpWindowName As String) As IntPtr
    End Function

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    Private Function SendMessage(
        ByVal hWnd As HandleRef,
        ByVal Msg As UInteger,
        ByVal wParam As IntPtr,
        ByRef lParam As COPYDATASTRUCT) As IntPtr
    End Function

    Public Function IPC_MyApp_SendText(sData As String) As Long

        Dim cds As COPYDATASTRUCT
        Dim wParam As IntPtr = frmProgress.Handle

        ' *** Find App Window we want to send text to...
        Dim Rx_Window As IntPtr

        Rx_Window = FindWindow(vbNullString, "MyApp")

        If Rx_Window <> IntPtr.Zero Then ' make sure window was found
            Dim href As New HandleRef(frmProgress, Rx_Window)
            cds.dwData = CType(3, IntPtr) ' NOTE: Using an indentifier of 3 for our MyApp Communication
            cds.lpData = sData
            cds.cbData = cds.lpData.Length + 1
            Call SendMessage(href, WM_COPYDATA, wParam, cds)
            GC.KeepAlive(frmProgress)

            Return 1
        Else
            Return 0
        End If

    End Function

End Module

And here is the code in VB6 App that manage the reception of the message
For that, I use Subclassing.
NB : It is not working in IDE, only in compiled app

Add a module for Subclassing and paste the code (coming from wqweto)

Code:

'=========================================================================
'
' MST Project (c) 2019 by wqweto@gmail.com
'
' The Modern Subclassing Thunk (MST) for VB6
'
' This project is licensed under the terms of the MIT license
' See the LICENSE file in the project root for more information
'
'=========================================================================
Option Explicit
DefObj A-Z
'Private Const MODULE_NAME As String = "mdModernSubclassing"

#Const ImplNoIdeProtection = (MST_NO_IDE_PROTECTION <> 0)
#Const ImplSelfContained = True

'=========================================================================
' API
'=========================================================================

Private Const SIGN_BIT  As Long = &H80000000
Private Const PTR_SIZE  As Long = 4
'--- for thunks
Private Const MEM_COMMIT As Long = &H1000
Private Const PAGE_EXECUTE_READWRITE As Long = &H40
Private Const CRYPT_STRING_BASE64 As Long = 1

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function CryptStringToBinary Lib "crypt32" Alias "CryptStringToBinaryA" (ByVal pszString As String, ByVal cchString As Long, ByVal dwFlags As Long, ByVal pbBinary As Long, pcbBinary As Long, Optional ByVal pdwSkip As Long, Optional ByVal pdwFlags As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function GetProcByOrdinal Lib "kernel32" Alias "GetProcAddress" (ByVal hModule As Long, ByVal lpProcOrdinal As Long) As Long
Private Declare Function DefSubclassProc Lib "comctl32" Alias "#413" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Long, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
#If Not ImplNoIdeProtection Then
  Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
  Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hWnd As Long, lpdwProcessId As Long) As Long
  Public Declare Function GetCurrentProcessId Lib "kernel32" () As Long
#End If
#If ImplSelfContained Then
  Private Declare Function GetEnvironmentVariable Lib "kernel32" Alias "GetEnvironmentVariableA" (ByVal lpName As String, ByVal lpBuffer As String, ByVal nSize As Long) As Long
  Private Declare Function SetEnvironmentVariable Lib "kernel32" Alias "SetEnvironmentVariableA" (ByVal lpName As String, ByVal lpValue As String) As Long
#End If

'=========================================================================
' Functions
'=========================================================================

Public Function InitAddressOfMethod(pObj As Object, ByVal MethodParamCount As Long) As frmMain
  Const STR_THUNK    As String = "6AAAAABag+oFV4v6ge9QEMEAgcekEcEAuP9EJAS5+QcAAPOri8LB4AgFuQAAAKuLwsHoGAUAjYEAq7gIAAArq7hEJASLq7hJCIsEq7iBi1Qkq4tEJAzB4AIFCIkCM6uLRCQMweASBcDCCACriTrHQgQBAAAAi0QkCIsAiUIIi0QkEIlCDIHqUBDBAIvCBTwRwQCri8IFUBHBAKuLwgVgEcEAq4vCBYQRwQCri8IFjBHBAKuLwgWUEcEAq4vCBZwRwQCri8IFpBHBALn5BwAAq4PABOL6i8dfgcJQEMEAi0wkEIkRK8LCEAAPHwCLVCQE/0IEi0QkDIkQM8DCDABmkItUJAT/QgSLQgTCBAAPHwCLVCQE/0oEi0IEg/gAfgPCBABZWotCDGgAgAAAagBSUf/gZpC4AUAAgMIIALgBQACAwhAAuAFAAIDCGAC4AUAAgMIkAA==" ' 25.3.2019 14:01:08
  Const THUNK_SIZE    As Long = 16728
  Dim hThunk          As Long
  Dim lSize            As Long

  hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
  If hThunk = 0 Then
      Exit Function
  End If
  Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk, THUNK_SIZE)
  lSize = CallWindowProc(hThunk, ObjPtr(pObj), MethodParamCount, GetProcAddress(GetModuleHandle("kernel32"), "VirtualFree"), VarPtr(InitAddressOfMethod))
  Debug.Assert lSize = THUNK_SIZE
End Function

Public Function InitSubclassingThunk(ByVal hWnd As Long, pObj As Object, ByVal pfnCallback As Long) As IUnknown
  Const STR_THUNK    As String = "6AAAAABag+oFgepwEB4BV1aLdCQUg8YIgz4AdC+L+oHHABIeAYvCBQgRHgGri8IFRBEeAauLwgVUER4Bq4vCBXwRHgGruQkAAADzpYHCABIeAVJqGP9SEFqL+IvCq7gBAAAAqzPAq4tEJAyri3QkFKWlg+8YagBX/3IM/3cM/1IYi0QkGIk4Xl+4NBIeAS1wEB4BwhAAZpCLRCQIgzgAdSqDeAQAdSSBeAjAAAAAdRuBeAwAAABGdRKLVCQE/0IEi0QkDIkQM8DCDAC4AkAAgMIMAJCLVCQE/0IEi0IEwgQADx8Ai1QkBP9KBItCBHUYiwpS/3EM/3IM/1Eci1QkBIsKUv9RFDPAwgQAkFWL7ItVGIsKi0EshcB0OFL/0FqJQgiD+AF3VIP4AHUJgX0MAwIAAHRGiwpS/1EwWoXAdTuLClJq8P9xJP9RKFqpAAAACHUoUjPAUFCNRCQEUI1EJARQ/3UU/3UQ/3UM/3UI/3IQ/1IUWVhahcl1EYsK/3UU/3UQ/3UM/3UI/1EgXcIYAA==" ' 1.4.2019 11:41:46
  Const THUNK_SIZE    As Long = 452
  Static hThunk      As Long
  Dim aParams(0 To 10) As Long
  Dim lSize            As Long

  aParams(0) = ObjPtr(pObj)
  aParams(1) = pfnCallback
  #If ImplSelfContained Then
      If hThunk = 0 Then
        hThunk = pvThunkGlobalData("InitSubclassingThunk")
      End If
  #End If
  If hThunk = 0 Then
      hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
      If hThunk = 0 Then
        Exit Function
      End If
      Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk, THUNK_SIZE)
      aParams(2) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemAlloc")
      aParams(3) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemFree")
      Call DefSubclassProc(0, 0, 0, 0)                                            '--- load comctl32
      aParams(4) = GetProcByOrdinal(GetModuleHandle("comctl32"), 410)            '--- 410 = SetWindowSubclass ordinal
      aParams(5) = GetProcByOrdinal(GetModuleHandle("comctl32"), 412)            '--- 412 = RemoveWindowSubclass ordinal
      aParams(6) = GetProcByOrdinal(GetModuleHandle("comctl32"), 413)            '--- 413 = DefSubclassProc ordinal
      '--- for IDE protection
      Debug.Assert pvGetIdeOwner(aParams(7))
      If aParams(7) <> 0 Then
        aParams(8) = GetProcAddress(GetModuleHandle("user32"), "GetWindowLongA")
        aParams(9) = GetProcAddress(GetModuleHandle("vba6"), "EbMode")
        aParams(10) = GetProcAddress(GetModuleHandle("vba6"), "EbIsResetting")
      End If
      #If ImplSelfContained Then
        pvThunkGlobalData("InitSubclassingThunk") = hThunk
      #End If
  End If
  lSize = CallWindowProc(hThunk, hWnd, 0, VarPtr(aParams(0)), VarPtr(InitSubclassingThunk))
  Debug.Assert lSize = THUNK_SIZE
End Function

Public Function CallNextSubclassProc(pSubclass As IUnknown, ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  #If pSubclass Then '--- touch args
  #End If
  CallNextSubclassProc = DefSubclassProc(hWnd, wMsg, wParam, lParam)
End Function

Public Function InitHookingThunk(ByVal idHook As Long, pObj As Object, ByVal pfnCallback As Long) As IUnknown
  Const STR_THUNK    As String = "6AAAAABag+oFgepwECQAV1aLdCQUg8YIgz4AdCqL+oHHOBIkAIvCBVQRJACri8IFkBEkAKuLwgWgESQAqzPAq7kJAAAA86WBwjgSJABSahj/UhBai/iLwqu4AQAAAKszwKuri3QkFKWlg+8Yi0oM/0IMgWIM/wAAAI0Eyo0EyI1MiDTHAf80JLiJeQTHQQiJRCQEi8ItOBIkAAXEESQAUMHgCAW4AAAAiUEMWMHoGAUA/+CQiUEQ/3QkEGoAUf90JBiLD/9RGIlHDItEJBiJOF5fuGwSJAAtcBAkAAUAFAAAwhAAi0QkCIM4AHUqg3gEAHUkgXgIwAAAAHUbgXgMAAAARnUSi1QkBP9CBItEJAyJEDPAwgwAuAJAAIDCDACQi1QkBP9CBItCBMIEAA8fAItUJAT/SgSLQgR1FIsK/3IM/1Eci1QkBIsKUv9RFDPAwgQAkFWL7ItVCIsKi0EshcB0KlL/0FqJQgiD+AF3Q4sKUv9RMFqFwHU4iwpSavD/cST/UShaqQAAAAh1JVIzwFBQjUQkBFCNRCQEUP91FP91EP91DP9yEP9SFFlYWoXJdRGLCv91FP91EP91DP9yDP9RIF3CEACQ" ' 1.4.2019 11:43:54
  Const THUNK_SIZE    As Long = 5628
  Static hThunk      As Long
  Dim aParams(0 To 10) As Long
  Dim lSize            As Long

  aParams(0) = ObjPtr(pObj)
  aParams(1) = pfnCallback
  #If ImplSelfContained Then
      If hThunk = 0 Then
        hThunk = pvThunkGlobalData("InitHookingThunk")
      End If
  #End If
  If hThunk = 0 Then
      hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
      If hThunk = 0 Then
        Exit Function
      End If
      Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk, THUNK_SIZE)
      aParams(2) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemAlloc")
      aParams(3) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemFree")
      aParams(4) = GetProcAddress(GetModuleHandle("user32"), "SetWindowsHookExA")
      aParams(5) = GetProcAddress(GetModuleHandle("user32"), "UnhookWindowsHookEx")
      aParams(6) = GetProcAddress(GetModuleHandle("user32"), "CallNextHookEx")
      '--- for IDE protection
      Debug.Assert pvGetIdeOwner(aParams(7))
      If aParams(7) <> 0 Then
        aParams(8) = GetProcAddress(GetModuleHandle("user32"), "GetWindowLongA")
        aParams(9) = GetProcAddress(GetModuleHandle("vba6"), "EbMode")
        aParams(10) = GetProcAddress(GetModuleHandle("vba6"), "EbIsResetting")
      End If
      #If ImplSelfContained Then
        pvThunkGlobalData("InitHookingThunk") = hThunk
      #End If
  End If
  lSize = CallWindowProc(hThunk, idHook, App.ThreadID, VarPtr(aParams(0)), VarPtr(InitHookingThunk))
  Debug.Assert lSize = THUNK_SIZE
End Function

Public Function CallNextHookProc(pHook As IUnknown, ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
  Dim lPtr            As Long

  lPtr = ObjPtr(pHook)
  If lPtr <> 0 Then
      Call CopyMemory(lPtr, ByVal (lPtr Xor SIGN_BIT) + 12 Xor SIGN_BIT, PTR_SIZE)
  End If
  CallNextHookProc = CallNextHookEx(lPtr, nCode, wParam, lParam)
End Function

Public Function InitFireOnceTimerThunk(pObj As Object, ByVal pfnCallback As Long, Optional Delay As Long) As IUnknown
  Const STR_THUNK    As String = "6AAAAABag+oFgeogERkAV1aLdCQUg8YIgz4AdCqL+oHHBBMZAIvCBSgSGQCri8IFZBIZAKuLwgV0EhkAqzPAq7kIAAAA86WBwgQTGQBSahj/UhBai/iLwqu4AQAAAKszwKuri3QkFKWlg+8Yi0IMSCX/AAAAUItKDDsMJHULWIsPV/9RFDP/62P/QgyBYgz/AAAAjQTKjQTIjUyIMIB5EwB101jHAf80JLiJeQTHQQiJRCQEi8ItBBMZAAWgEhkAUMHgCAW4AAAAiUEMWMHoGAUA/+CQiUEQiU8MUf90JBRqAGoAiw//URiJRwiLRCQYiTheX7g0ExkALSARGQAFABQAAMIQAGaQi0QkCIM4AHUqg3gEAHUkgXgIwAAAAHUbgXgMAAAARnUSi1QkBP9CBItEJAyJEDPAwgwAuAJAAIDCDACQi1QkBP9CBItCBMIEAA8fAItUJAT/SgSLQgR1HYtCDMZAEwCLCv9yCGoA/1Eci1QkBIsKUv9RFDPAwgQAi1QkBIsKi0EohcB0J1L/0FqD+AF3SYsKUv9RLFqFwHU+iwpSavD/cSD/USRaqQAAAAh1K4sKUv9yCGoA/1EcWv9CBDPAUFT/chD/UhSLVCQIx0IIAAAAAFLodv///1jCFABmkA==" ' 27.3.2019 9:14:57
  Const THUNK_SIZE    As Long = 5652
  Static hThunk      As Long
  Dim aParams(0 To 9)  As Long
  Dim lSize            As Long

  aParams(0) = ObjPtr(pObj)
  aParams(1) = pfnCallback
  #If ImplSelfContained Then
      If hThunk = 0 Then
        hThunk = pvThunkGlobalData("InitFireOnceTimerThunk")
      End If
  #End If
  If hThunk = 0 Then
      hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
      If hThunk = 0 Then
        Exit Function
      End If
      Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk, THUNK_SIZE)
      aParams(2) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemAlloc")
      aParams(3) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemFree")
      aParams(4) = GetProcAddress(GetModuleHandle("user32"), "SetTimer")
      aParams(5) = GetProcAddress(GetModuleHandle("user32"), "KillTimer")
      '--- for IDE protection
      Debug.Assert pvGetIdeOwner(aParams(6))
      If aParams(6) <> 0 Then
        aParams(7) = GetProcAddress(GetModuleHandle("user32"), "GetWindowLongA")
        aParams(8) = GetProcAddress(GetModuleHandle("vba6"), "EbMode")
        aParams(9) = GetProcAddress(GetModuleHandle("vba6"), "EbIsResetting")
      End If
      #If ImplSelfContained Then
        pvThunkGlobalData("InitFireOnceTimerThunk") = hThunk
      #End If
  End If
  lSize = CallWindowProc(hThunk, 0, Delay, VarPtr(aParams(0)), VarPtr(InitFireOnceTimerThunk))
  Debug.Assert lSize = THUNK_SIZE
End Function

Property Get ThunkPrivateData(pThunk As IUnknown, Optional ByVal Index As Long) As Long
  Dim lPtr            As Long

  lPtr = ObjPtr(pThunk)
  If lPtr <> 0 Then
      Call CopyMemory(ThunkPrivateData, ByVal (lPtr Xor SIGN_BIT) + 8 + Index * 4 Xor SIGN_BIT, PTR_SIZE)
  End If
End Property

Property Let ThunkPrivateData(pThunk As IUnknown, Optional ByVal Index As Long, ByVal lValue As Long)
  Dim lPtr            As Long

  lPtr = ObjPtr(pThunk)
  If lPtr <> 0 Then
      Call CopyMemory(ByVal (lPtr Xor SIGN_BIT) + 8 + Index * 4 Xor SIGN_BIT, lValue, PTR_SIZE)
  End If
End Property

Public Function InitCleanupThunk(ByVal hHandle As Long, sModuleName As String, sProcName As String) As IUnknown
  Const STR_THUNK    As String = "6AAAAABag+oFgepQEDwBV1aLdCQUgz4AdCeL+oHHPBE8AYvCBcwQPAGri8IFCBE8AauLwgUYETwBq7kCAAAA86WBwjwRPAFSahD/Ugxai/iLwqu4AQAAAKuLRCQMq4tEJBCrg+8Qi0QkGIk4Xl+4UBE8AS1QEDwBwhAAkItEJAiDOAB1KoN4BAB1JIF4CMAAAAB1G4F4DAAAAEZ1EotUJAT/QgSLRCQMiRAzwMIMALgCQACAwgwAkItUJAT/QgSLQgTCBAAPHwCLVCQE/0oEi0IEdRL/cgj/UgyLVCQEiwpS/1EQM8DCBAAPHwA=" ' 25.3.2019 14:03:56
  Const THUNK_SIZE    As Long = 256
  Static hThunk      As Long
  Dim aParams(0 To 1)  As Long
  Dim pfnCleanup      As Long
  Dim lSize            As Long

  #If ImplSelfContained Then
      If hThunk = 0 Then
        hThunk = pvThunkGlobalData("InitCleanupThunk")
      End If
  #End If
  If hThunk = 0 Then
      hThunk = VirtualAlloc(0, THUNK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
      If hThunk = 0 Then
        Exit Function
      End If
      Call CryptStringToBinary(STR_THUNK, Len(STR_THUNK), CRYPT_STRING_BASE64, hThunk, THUNK_SIZE)
      aParams(0) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemAlloc")
      aParams(1) = GetProcAddress(GetModuleHandle("ole32"), "CoTaskMemFree")
      #If ImplSelfContained Then
        pvThunkGlobalData("InitCleanupThunk") = hThunk
      #End If
  End If
  If Left$(sProcName, 1) = "#" Then
      pfnCleanup = GetProcByOrdinal(GetModuleHandle(sModuleName), Mid$(sProcName, 2))
  Else
      pfnCleanup = GetProcAddress(GetModuleHandle(sModuleName), sProcName)
  End If
  If pfnCleanup <> 0 Then
      lSize = CallWindowProc(hThunk, hHandle, pfnCleanup, VarPtr(aParams(0)), VarPtr(InitCleanupThunk))
      Debug.Assert lSize = THUNK_SIZE
  End If
End Function

Private Function pvGetIdeOwner(hIdeOwner As Long) As Boolean
  #If Not ImplNoIdeProtection Then
      Dim lProcessId      As Long

      Do
        hIdeOwner = FindWindowEx(0, hIdeOwner, "IDEOwner", vbNullString)
        Call GetWindowThreadProcessId(hIdeOwner, lProcessId)
      Loop While hIdeOwner <> 0 And lProcessId <> GetCurrentProcessId()
  #End If
  pvGetIdeOwner = True
End Function

#If ImplSelfContained Then
  Private Property Get pvThunkGlobalData(sKey As String) As Long
      Dim sBuffer          As String

      sBuffer = String$(50, 0)
      Call GetEnvironmentVariable("_MST_GLOBAL" & App.hInstance & "_" & sKey, sBuffer, Len(sBuffer) - 1)
      pvThunkGlobalData = Val(Left$(sBuffer, InStr(sBuffer, vbNullChar) - 1))
  End Property

  Private Property Let pvThunkGlobalData(sKey As String, ByVal lValue As Long)
      Call SetEnvironmentVariable("_MST_GLOBAL" & App.hInstance & "_" & sKey, lValue)
  End Property
#End If


In the main Form

add the declaration
Code:

Private m_pSubclass    As IUnknown
In the Form_load

Code:

If Not InDesignMode() Then Set m_pSubclass = InitSubclassingThunk(hWnd, Me, InitAddressOfMethod(Me, 5).MyApp_Subclass(0, 0, 0, 0, 0))

Add the procedure
Code:

Public Function MyApp_Subclass(ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long, Handled As Boolean) As Long
  ' #VBIDEUtils#************************************************************
  ' * Author          :
  ' * Web Site        :
  ' * E-Mail          :
  ' * Date            : 10/02/2019
  ' * Time            : 17:56
  ' * Module Name      : frmMain
  ' * Module Filename  : Main.frm
  ' * Procedure Name  : MyApp_Subclass
  ' * Purpose          :
  ' * Parameters      :
  ' *                    ByVal hWnd As Long
  ' *                    ByVal wMsg As Long
  ' *                    ByVal wParam As Long
  ' *                    ByVal lParam As Long
  ' *                    Handled As Boolean
  ' * Purpose          :
  ' **********************************************************************
  ' * Comments        :
  ' *
  ' *
  ' * Example          :
  ' *
  ' * See Also        :
  ' *
  ' * History          :
  ' *
  ' *
  ' **********************************************************************

  #If hWnd And wParam And Handled Then '--- touch args
  #End If

  Select Case wMsg
      Case WM_COPYDATA
        Call Communication_Received(lParam)
        Handled = True
  End Select

End Function


Create a new module that will contains the code for managing IPC messages

Code:

Option Explicit

Private Type COPYDATASTRUCT
  dwData              As Long
  cbData              As Long
  lpData              As Long
End Type

Public Const WM_COPYDATA = &H4A

'' *** Copies a block of memory from one location to another.
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Public Function StringItem(sDelimString As String, sDelim As String, ByVal lItemIndex As Long, Optional sDefault As String = vbNullString) As String
  ' #VBIDEUtils#***********************************************************
  ' * Author          :
  ' * Web Site        :
  ' * E-Mail          :
  ' * Date            : 02/12/2001
  ' * Time            : 15:28
  ' * Module Name      : Lib_Module
  ' * Module Filename  : Lib.bas
  ' * Procedure Name  : StringItem
  ' * Purpose          :
  ' * Parameters      :
  ' *                    sDelimString As String
  ' *                    sDelim As String
  ' *                    ByVal lItemIndex As Long
  ' *                    Optional sDefault As String = vbNullString
  ' * Purpose          :
  ' **********************************************************************
  ' * Comments        :
  ' *
  ' *
  ' * Example          :
  ' *
  ' * See Also        :
  ' *
  ' * History          :
  ' *
  ' *
  ' **********************************************************************

  Dim asItems()        As String
  Dim lUbound          As Long

  asItems = Split(sDelimString, sDelim)
  lUbound = UBound(asItems)
  lItemIndex = lItemIndex - 1
  If lUbound >= lItemIndex Then
      StringItem = asItems(lItemIndex)
  Else
      StringItem = sDefault
  End If

End Function

Sub Communication_Received(lParam As Long)
  ' #VBIDEUtils#************************************************************
  ' * Author          :
  ' * Web Site        :
  ' * E-Mail          :
  ' * Date            : 08/28/2019
  ' * Time            : 13:23
  ' * Module Name      : Communication_Module
  ' * Module Filename  : Communication.bas
  ' * Procedure Name  : Communication_Received
  ' * Purpose          :
  ' * Parameters      :
  ' *                    lParam As Long
  ' * Purpose          :
  ' **********************************************************************
  ' * Comments        :
  ' *
  ' *
  ' * Example          :
  ' *
  ' * See Also        :
  ' *
  ' * History          :
  ' *
  ' *
  ' **********************************************************************

  ' #VBIDEUtilsERROR#
  On Error GoTo ERROR_Communication_Received

  Dim cds              As COPYDATASTRUCT
  Dim buf(1 To 255)    As Byte
  Dim sMessage        As String

  Dim sCommand        As String
  dim sData                        as String       

  Call CopyMemory(cds, ByVal lParam, Len(cds))

  Select Case cds.dwData
      Case 1:
        'MsgBox "got a 1"

      Case 2:
        'MsgBox "got a 2"

      Case 3: ' *** VSTO Addin Communication
        Call CopyMemory(buf(1), ByVal cds.lpData, cds.cbData)
        sMessage = StrConv(buf, vbUnicode)
        sMessage = Left$(sMessage, InStr(1, sMessage, Chr$(0)) - 1)

                sCommand = StringItem(sMessage, ":", 1)
                sData = StringItem(sMessage, ":", 2)

        ' *** We Manage the message
        ' *** and we do the needed  work
                Select Case sMessage
              Case "ShowMessage"
                                        Msgbox sData
                                       
              Case "yyyy"

                End Select
  End Select

EXIT_Communication_Received:
  On Error Resume Next

  Exit Sub

  ' #VBIDEUtilsERROR#
ERROR_Communication_Received:
  Resume EXIT_Communication_Received

End Sub


Finally a sampleshowing how to send a message from the VSTO addin to the VB6 Application

Code:

Call IPC_MyApp_SendText("ShowMessage:This is great")

Viewing all articles
Browse latest Browse all 1529

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>