我正在使用Windows消息API在两个Windows Forms应用程序之间进行通信。我将应用程序的一部分表单取出并制作成自己的应用程序,这样当它正在加载时,用户仍然可以在另一个表单中工作,该表单现在是从一个独立的应用程序中而不是原来的应用程序中打开的。
我需要能够在两个应用程序之间通信,以便现在单独的应用程序表单可以告诉主应用程序要打开什么。
我在主应用程序的主表单上使用此代码,它运行得很好...除非主表单没有焦点。
我以前从未使用过Windows消息API,我只是通过查找如何在窗体之间通信而得到了这个。所以我对此还很陌生。经过进一步的研究,我知道我需要一个仅用于处理消息的窗口。但我不知道该怎么做。我查看了一些文章和解决方案,如这篇,我认为我遇到的问题是我不知道如何实现它。
编辑1
以下是第二个应用程序如何查找并发送给主应用程序的方法。
这是两个应用中都有的 BuildString 类的代码。
我需要能够在两个应用程序之间通信,以便现在单独的应用程序表单可以告诉主应用程序要打开什么。
我在主应用程序的主表单上使用此代码,它运行得很好...除非主表单没有焦点。
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
我以前从未使用过Windows消息API,我只是通过查找如何在窗体之间通信而得到了这个。所以我对此还很陌生。经过进一步的研究,我知道我需要一个仅用于处理消息的窗口。但我不知道该怎么做。我查看了一些文章和解决方案,如这篇,我认为我遇到的问题是我不知道如何实现它。
编辑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
结束类
这是主应用程序上的代码,一旦消息被解码就运行。
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
MainWindowHandle
返回了一个不同的句柄(尽管我的理解是这不是预期行为)。我会使用断点来检查返回的句柄(或将它们输出到调试窗口)以确保句柄不会改变。 - Justin Ryan