Я использую API сообщений Windows для связи между двумя приложениями Windows Forms. Я вынул форму, которая была частью приложения, и превратила ее в свое приложение, так что когда она загружается, пользователь все равно может работать с другими формами в отдельном приложении из одной формы.SendMessage между WinForms Приложения - требуется фокус формы
Мне нужно иметь возможность общаться между двумя приложениями, чтобы теперь отдельная форма приложения могла сообщать главному приложению, что открыть.
Этот код используется в основной форме основного приложения, и он отлично работает ... За исключением случаев, когда основная форма не имеет фокуса.
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Try
Select Case m.Msg
Case &H400
BS.BuildString(m.LParam)
Case Else
MyBase.WndProc(m)
End Select
Catch ex As Exception
End Try
End Sub
Я никогда раньше не использовал API для Windows Message, я просто схватил это от глядя, как общаться между формами, так что я новичок в этом. То, что я знаю из других исследований, заключается в том, что для обработки сообщений мне нужно окно только для сообщений. Я не понимаю, как это сделать. Я рассмотрел несколько статей и решений, таких как this one, и я думаю, что проблема, с которой я столкнулась, заключается в том, что я не знаю, как ее реализовать.
Edit 1
Вот как второе приложение находит и отправляет к основному приложению.
'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 > 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, &H400, 0, "ID:" & ID)
Next
Else
MessageBox.Show("Main application not running")
End If
Вот класс для BuildString, который находится в обоих приложениях.
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 <> 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
End Class
Вот код на главном приложение, которое запускается, когда сообщение получает декодируется.
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
Форма не обязательно должна быть активной (или иметь фокус) для приема сообщений; как вы упомянули, все, что ему нужно, это очередь сообщений. Пожалуйста, покажите код, который вы используете во втором приложении, чтобы найти дескриптор первого, и затем отправьте свое сообщение. –
Я показал остальную часть кода @JustinRyan. «Как вы уже сказали», я упомянул форму, которая не должна быть активной? Где? Очередь сообщений? Я посмотрю. – Keevan
Ваш код сообщения кажется правильным, поскольку я его прочитал. Получает ли ваше принимающее окно что-либо нетипичное, например, свернуть до системного трея или скрыть его в какой-то момент (кроме как просто неактивного)? Пока существует окно, оно должно иметь возможность принимать сообщения. Если это не так, я бы попробовал альтернативный способ получить дескриптор окна (например, [FindWindow] (http://msdn.microsoft.com/en-us/library/windows/desktop/ms633499 (v = vs.85) .aspx)) вместо поиска по имени процесса. –