VB6 SendMessage发送自定义数据类型

时间:2012-01-04 17:37:00

标签: vb6 ipc sendmessage

我目前正在成功使用Win32 API的SendMessage函数,使用WM_SETTEXT参数在两个线程之间发送文本。

我想要做的是发送自定义数据类型而不是原始数据类型。

所以让我说我有

Type myType
    a as Integer
    b(5) as Boolean
    d(15) as Double
End Type
Dim tmp as myType

我希望能够:

Call SendMessage(dstHWnd, WM_SETTEXT, 0, tmp)

我猜我必须使用WM_COPYDATA或类似的,但另一个问题是这会产生错误,因为我的数据类型无法按照函数定义转换为Any:

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Integer, ByVal lParam As Any) As Long

是否有可能哄骗这种转换?或者是否有另一种最佳实践方法(快速和最佳)?

3 个答案:

答案 0 :(得分:3)

SendMessage的最后一个参数声明为byref lParam as myType

但是,您正在滥用邮件系统。只有当你知道自己在做什么并且确信没有系统默认的处理逻辑将被应用于该消息时,它才会没问题。


为了澄清,在接收端,您正在执行以下操作来获取数据 首先,使用最后一个参数ByVal lParam As Long声明消息处理例程。还有一个功能:

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

然后,当您收到消息时:

if uMsg = WM_SETTEXT then
  dim t as myType
  copymemory t, byval lParam, len(t)

  'Using t here
end if

进一步澄清。

因为所有线程都在一个进程内,所以你可以简单地共享指针并按WM_COPYDATA的平均值进行操作。您只需要COPYDATASTRUCT结构的第一个成员。

在发送端,您设置COPYDATASTRUCT.dwData = VarPrt(your_struct)

在接收端,您执行上面显示的相同CopyMemory事项。

请注意,如果您的消息处理例程仅接收该单个消息(并且没有其他消息),那么您可以简单地将其最后一个参数声明为ByRef lParam As myType并直接使用它,从而避免复制。

答案 1 :(得分:3)

如何使用内存映射文件?

'Write to MyMMF

Private Function writeMyType(newMyType As myType)

    hMMF = OpenFileMapping(FILE_MAP_ALL_ACCESS, False, "MyMMF")

    If hMMF = 0 Then
        hMMF = CreateFileMapping(-1, 0, PAGE_READWRITE, 0, LenB(newMyType), "MyMMF")
    End If

    If Not hMMF = 0 Then
        pMemfile = MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0)
        RtlMoveMemory1 pMemfile, ByVal newMyType, LenB(newMyType)
    End If

    CloseHandle hMMF

End Function

'Read from MyMMF
Private Function readMyType(ByRef inMyType As myType)

    hMMF = OpenFileMapping(FILE_MAP_ALL_ACCESS, False, "MyMMF")

    If hMMF = 0 Then
        MsgBox "No data in MyMMF"
        Exit Function
    Else
        pMemfile = MapViewOfFile(hMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0)
        RtlMoveMemory2 ByVal inMyType, pMemfile, LenB(inMyType)
    End If

    CloseHandle hMMF

End Function


'Declares and Constants
Public Type myType
    a As Integer
    b(5) As Boolean
    d(15) as Double
End Type


Public Declare Function OpenFileMapping Lib "kernel32" Alias "OpenFileMappingA" (ByVal dwDesiredAccess As Integer, ByVal bInheritHandle As Integer, ByVal lpName As String) As Long
Public Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" (ByVal hFile As Long, ByVal lpAttributes As Long, ByVal flProtect As Integer, ByVal dwMaximumSizeHigh As Integer, ByVal dwMaximumSizeLow As Integer, ByVal lpName As String) As Long
Public Declare Function MapViewOfFile Lib "kernel32" (ByVal hFileMappingObject As Long, ByVal dwDesiredAccess As Long, ByVal dwFileOffsetHigh As Long, ByVal dwFileOffsetLow As Long, ByVal dwNumberOfBytesToMap As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long

Public Declare Sub RtlMoveMemory1 Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByVal Destination As Long, _
ByRef Source As Any, _
ByVal Length As Long)

Public Declare Sub RtlMoveMemory2 Lib "kernel32.dll" Alias "RtlMoveMemory" ( _
ByRef Destination As Any, _
ByVal Source As Long, _
ByVal Length As Long)

Public Const FILE_MAP_ALL_ACCESS = &H1F
Public Const PAGE_READWRITE = &H4

答案 2 :(得分:1)

如果它们是两个线程(每个都有自己的窗口?在VB6中?hmm)那么你只需要发送一个指向变量VarPtr(blah)的指针,并确保在返回之前复制出窗口过程。< / p>

但是,如果线程在两个独立的进程中,则选项要少得多。

您可以使用为您进行编组的WM_COPYDATA消息,或者设置一些共享/全局内存并通过普通SendMessage()传递指针/偏移量 正常的线程同步实践适用于后一种方法。