VB6 SendMessage发送自定义数据类型

VB6 SendMessage发送自定义数据类型

问题描述:

我目前成功地使用Win32 API的SendMessage函数在两个线程之间使用WM_SETTEXT参数发送文本。VB6 SendMessage发送自定义数据类型

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

所以我们可以说我有

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 

是否可能le哄这个转换?还是有其他最佳实践方法(快速和最优)?

+2

只是不同的线程在同一个进程(这是很难安全地在VB6中)或不同的进程?后者更严格。 – Deanna 2012-01-04 18:35:19

声明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并直接使用它,避免复制。

+0

如果我这样做,最后一个参数也必须是ByRef(用户定义的类型可能不会被val传递)。所以,让我说我通过ref ...我怎么去接收目标线程?目前,我正在通过sendmessage将文本框的文本设置为文本框的hwnd;用户定义的类型没有hwnd – 2012-01-04 19:21:52

+0

@AuthmanApatira请参阅编辑。 – GSerg 2012-01-04 19:55:44

+0

感谢迄今为止的帮助Greg。这似乎工作:SendMessage发送一个ByVal VarPtr(my_struct)。我的文本框将这个指针作为一个字符串接收,我将它指定为Long。我使用RtlMoveMemory函数将指针取消引用回我的用户定义类型。还剩下1个问题:UDT中的字符串只发送第一个字符,而不是整个字符串。对于我的目的来说,这实际上是可以的,因为我的UDT只是ints,double和bools ..但是在我关闭这个问题之前出于好奇,是否有办法获得完整的字符串大小? – 2012-01-04 20:18:25

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

但是,如果线程处于两个独立的进程中,则您的选项将少得多。

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

+0

同一进程中的多个线程。假设我使用varptr(blah)将指向我的对象的指针发送给客户端;我如何将指针(long)解引用到接收端的用户定义类型? – 2012-01-04 19:44:13

+0

RtlMoveMemory2 tmp2,VarPtr(tmp),LenB(tmp2)。如果tmp和tmp2在同一进程的内存空间中,则会将tmp复制到tmp2。如果你试图去跨进程使用我的答案。 RtlMoveMemory2是我的答案。 – Motes 2012-01-04 20:13:52

如何使用内存映射文件?

'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 
+0

不错的想法,特别是对于更大的转移。 – wqw 2012-01-04 21:07:47