VB6 SendMessage发送自定义数据类型

发布于 2024-12-24 03:10:46 字数 627 浏览 2 评论 0原文

我目前正在成功使用 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

是吗?可以诱导这种转变吗?或者是否有替代的最佳实践方法(快速且最佳)?

I'm currently successfully using Win32 API's SendMessage function to send text between two threads using the WM_SETTEXT parameter.

What I would like to do is send a custom data type instead of primitive data types.

So let's say I have

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

I would like to be able to:

Call SendMessage(dstHWnd, WM_SETTEXT, 0, tmp)

I am guessing I would have to use WM_COPYDATA or similar, but the other issue is this produces a error because my data type cannot be casted into Any, per function definition:

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

Is it possible to coax this conversion? Or is there an alternative best-practices method (fast and optimal)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烧了回忆取暖 2024-12-31 03:10:46

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

Declare the last parameter of SendMessage as byref lParam as myType.

You are, however, abusing the messaging system. It's only fine while you know what you're doing and you're sure no system-default procesing logic will ever be applied to that message.


To clarify, on the receiving end, you're doing the following to get the data.
First, you declare your message processing routine with the last parameter being ByVal lParam As Long. Also have a function:

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

Then, when you receive a message:

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

  'Using t here
end if

To clarify a bit further.

Because all threads are inside one process, you can simply share pointers and do that by the mean of WM_COPYDATA. You'll only need the first member of the COPYDATASTRUCT structure.

On the sending end, you set COPYDATASTRUCT.dwData = VarPrt(your_struct).

On the receiving end, you do that same CopyMemory thing shown above.

Note that if your message processing routine is only going to receive that single message (and no other messages), then you can simply declare its last parameter as ByRef lParam As myType and use it directly, avoiding the copying.

尛丟丟 2024-12-31 03:10:46

使用内存映射文件怎么样?

'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

How about using a Memory Mapped File?

'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
静待花开 2024-12-31 03:10:46

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

但是,如果线程位于两个独立的进程中,那么您的选择就会少得多。

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

If they are two threads (each with their own window? in VB6? hmm) then you just need to send a pointer to the variable VarPtr(blah) and make sure you copy out in the window procedure before returning.

If however, the threads are in two separate processes, you have far fewer options.

You can either use the WM_COPYDATA message which does the marshalling for you, or setup some shared/global memory and pass pointer/offsets via a normal SendMessage()
Normal thread sync practices apply to the latter methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文