title: SendMessage between WinForms Applications - form needs focus
body: <p>I'm using the Windows Messages API to communicate between two Windows Forms Apps. I took out a form that was a part of the application and made it into it's own app so that when it is loading the user can still work on the other forms now in a separate app from the one form.</p>
  
  <p>I need to be able to communicate between the two apps so that the now separate app form can tell the main app what to open. </p>
  
  <p>I use this code on the main form of the main app and it works great... Except when the main form doesn't have focus.</p>
  
  <pre><code>Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
      Try
          Select Case m.Msg
              Case &amp;H400
                  BS.BuildString(m.LParam)
              Case Else
                  MyBase.WndProc(m)
          End Select
      Catch ex As Exception
  
      End Try
  End Sub
  </code></pre>
  
  <p>I've never used the Windows Message API before, I just grabbed this from looking up how to communicate between forms, so I'm new at this. What I do know from doing some more research is that I need a Message only Window to handle the messages. I don't understand how to do this. 
  I've looked at a few articles and solutions like <a href="https://stackoverflow.com/questions/6786891/wndproc-how-to-get-window-messages-when-form-is-minimized">this one</a> and I think the problem I'm having is that I don't know how to implement it.</p>
  
  <p>Edit 1</p>
  
  <p>Here is how the second app finds and sends to the main app.</p>
  
  <pre><code>                'used to send a message using SendMessage API to the 
                  'main app to open the ID
                  Private WithEvents BS As New BuildString 
                  'get this running process
                  Dim proc As Process = Process.GetCurrentProcess()
                  'get all other (possible) running instances
                  Dim processes As Process() = Process.GetProcessesByName("ProcessName")
  
                  If processes.Length &gt; 0 Then
                      'iterate through all running target applications
                      For Each p As Process In processes
                          'now send the ID to the running instance of the main app
                          BS.PostString(p.MainWindowHandle, &amp;H400, 0, "ID:" &amp; ID)
                      Next
                  Else
                      MessageBox.Show("Main application not running")
                  End If
  </code></pre>
  
  <p>Here's the class for the BuildString that is in both apps.</p>
  
  <pre><code>Imports System.Text
  
  Public Class BuildString
  
  Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
  Public Event StringOK(ByVal Result As String)
  Private hwnd As Integer = 0
  Private wMsg As Integer = 0
  Private wParam As Integer = 0
  Private lParam As String = ""
  Private tempA(-1) As Byte
  Private enc As Encoding = Encoding.UTF8
  
  Public Property Encode() As Encoding
      Get
          Return enc
      End Get
      Set(ByVal value As Encoding)
          enc = value
      End Set
  End Property
  
  Public Sub BuildString(ByVal b As IntPtr)
      If b &lt;&gt; 0 Then
          'build temp array
          Dim tempB(tempA.Length) As Byte
          tempA.CopyTo(tempB, 0)
          tempB(tempA.Length) = b
          ReDim tempA(tempB.Length - 1)
          tempB.CopyTo(tempA, 0)
      Else
          'decode byte array to string
          Dim s As String
          If enc Is Encoding.UTF8 Then
              s = Encoding.UTF8.GetString(tempA)
          ElseIf enc Is Encoding.Unicode Then
              s = Encoding.Unicode.GetString(tempA)
          ElseIf enc Is Encoding.ASCII Then
              s = Encoding.ASCII.GetString(tempA)
          Else
              s = Encoding.Default.GetString(tempA)
          End If
          'send out result string via event
          RaiseEvent StringOK(s)
          ReDim tempA(-1)
      End If
  End Sub
  
  Public Sub PostString(ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String)
      Me.hwnd = hwnd
      Me.wMsg = wMsg
      Me.wParam = wParam
      Me.lParam = lParam
      'create a new thread to post window message
      Dim t As Threading.Thread
      t = New Threading.Thread(AddressOf SendString)
      t.Start()
  End Sub
  
  Private Sub SendString()
      'create byte array
      Dim ba() As Byte
      'encode string to byte array
      If enc Is Encoding.UTF8 Then
          ba = Encoding.UTF8.GetBytes(lParam)
      ElseIf enc Is Encoding.Unicode Then
          ba = Encoding.Unicode.GetBytes(lParam)
      ElseIf enc Is Encoding.ASCII Then
          ba = Encoding.ASCII.GetBytes(lParam)
      Else
          ba = Encoding.Default.GetBytes(lParam)
      End If
      Dim i As Integer
      For i = 0 To ba.Length - 1
          'start post message
          PostMessage(hwnd, wMsg, wParam, ba(i))
      Next
      'post a terminator message to destination window
      PostMessage(hwnd, wMsg, wParam, 0)
  End Sub
  </code></pre>
  
  <p>End Class</p>
  
  <p>Here is the code on the main app that is run once the message gets decoded.</p>
  
  <pre><code>Private Sub SB_StringOK(ByVal Result As String) Handles BS.StringOK
      Dim sArray() As String = Result.Split(";")
      'rest of the code to open the ID
  End Sub
  </code></pre>