VB6 SendMessage发送自定义数据类型

VB6 SendMessage发送自定义数据类型,vb6,ipc,sendmessage,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) 我猜我将不得不

我目前正在使用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或类似工具,但另一个问题是,这会产生错误,因为我的数据类型无法转换为任何函数定义:

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

有可能诱使这种转换吗?或者是否有另一种快速优化的最佳实践方法?

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

但是,您正在滥用消息传递系统。只有当您知道自己在做什么,并且确信不会对该消息应用任何系统默认处理逻辑时,才可以

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

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.dwData=VarPrtyour_struct

在接收端,您可以执行与上面所示相同的CopyMemory操作


请注意,如果您的消息处理例程只接收一条消息而不接收其他消息,那么您可以简单地将其最后一个参数声明为ByRef lParam as myType并直接使用它,避免复制。

如果它们是两个线程,每个线程都有自己的窗口?在VB6中?嗯,那么您只需要发送一个指向变量VarPtrblah的指针,并确保在返回之前在窗口过程中进行复制

但是,如果线程位于两个单独的进程中,则选项要少得多

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

使用内存映射文件怎么样

'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

只是同一进程中的不同线程在VB6或不同进程中很难安全执行?后者要严格得多。如果我这样做,最后一个参数也必须是ByRef,用户定义的类型可能不会被byval传递。让我们假设我通过ref传递它。。。如何在目标线程中进行接收?目前,我正在通过sendmessage将文本框的文本设置为文本框的hwnd;用户定义的类型没有hwnd思想感谢到目前为止的帮助Greg。这似乎有效:SendMessage发送一个ByVal VarPtrmy_结构。我的文本框将此指针作为字符串接收,我将其键入回Long。我使用rtlmovemory函数将指针解引用回我的用户定义类型。只剩下一个问题:UDT中的字符串只发送它们的第一个字符,而不是整个字符串。这实际上对我来说没关系,因为我的UDT只是整数、双倍和布尔。。但在我结束这个问题之前,出于好奇,有没有办法获得完整的字符串大小?@AuthmanApatira字符串是作为指针传递的,而不是实际的数据。在使用这种技术时,您也需要尊重它们。你看过我上次的编辑吗,建议ByRef lParam作为接收端的myType?我看过了。。。但我不知道如何实现这一点。就我所知,VB6实际上并没有公开消息处理。我能做的最好的事情就是绑定到预定义的事件。在我的例子中,我在由hwnd定义的接收文本框的onchanged事件中进行处理。当接收到的数据呈现给我时,它已经是sendmessage长时间传递的指针的字符串版本,使用上述技术myorigWndProc=SetWindowLongPtrmyhWnd,GWLP_WNDPROC,AddressOfNewWndProc,其中myhWnd是窗口的句柄,NewWndProcByVal myhWnd为long,ByVal uMsg为long,ByVal wParam为long,只要是模块中的公共函数,就会替换默认的窗口消息处理例程。在NewWndProc结束时,确保调用NewWndProc=CallWindowProcMyOrigWndProc、myhWnd、uMsg、wParam、lParam,在窗口卸载之前,确保调用SetWindowLongPtr myhWnd、GWLP_WNDPROC、MyOrigWndProc以正确卸载。同一进程中有多个线程。假设我使用varptrblah向客户机发送指向我的对象的指针;如何在接收端解除长指向用户定义类型的指针的引用?rtlmovemory2 tmp2、VarPtrtmp、LenBtmp2。如果tmp和tmp2位于同一进程的内存空间中,则会将tmp复制到tmp2。如果你想跨进程,请使用我的答案。RtlMoveMemory2的定义是我的答案。好主意,特别是对于笨重的转移。