2012-01-04 147 views
0

現在、Win32 APIのSendMessage関数を使用して、WM_SETTEXTパラメータを使用して2つのスレッド間でテキストを送信しています。VB6カスタムデータ型を送信するSendMessage

私がしたいのは、プリミティブデータ型の代わりにカスタムデータ型を送信することです。

Call SendMessage(dstHWnd, WM_SETTEXT, 0, tmp) 

私はWM_COPYDATAまたは類似を使用する必要があります推測していますが、他の問題は、これが生成される:

だから私のことができるようにしたいのは、私が

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

を持っているとしましょう私のデータ型が関数定義ごとに、どれにキャストすることができないので、エラー:それはpossibが

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 

ですこの変換を行うには?または、ベストプラクティスの代替方法(高速かつ最適)がありますか?

+2

(VB6で安全に実行するのが難しい)同じプロセス内の異なるスレッドまたは異なるプロセスですか?後者ははるかに厳しいです。 – Deanna

答えて

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 

はさらにビットを明確にするためにも機能があります。

すべてのスレッドは1つのプロセス内にあるため、単純にポインタを共有して、平均でWM_COPYDATAで実行できます。 COPYDATASTRUCT構造の最初のメンバーだけが必要です。

送信側では、COPYDATASTRUCT.dwData = VarPrt(your_struct)と設定します。

受信側では、上記と同じCopyMemoryのことを行います。

メッセージ処理ルーチンがその単一のメッセージ(および他のメッセージは受信しない)を受信する場合は、最後のパラメータをByRef lParam As myTypeと単に宣言して、コピーを避けて直接使用することに注意してください。

+0

これを行うと、最後のparamもByRefでなければなりません(ユーザー定義の型はbyvalを渡すことはできません)。だから私はrefで渡すと言うことができます...どのように私は宛先のスレッドで受信について行くのですか?現在、テキストボックスのテキストをテキストボックスのhwndにsendmessageで設定しています。ユーザー定義型はありません。 –

+0

@AuthmanApatira編集を参照してください。 – GSerg

+0

グレッグに助けてくれてありがとう。これは動作するようです:SendMessage ByVal VarPtr(my_struct)を送信します。 My Textboxはこのポインタを文字列として受け取ります。これをLongに戻します。 RtlMoveMemory関数を使用して、ユーザー定義型にポインタを逆参照します。ちょうど1つの問題が残っています:UDTの文字列は文字列全体ではなく、最初の文字のみを送信します。私のUDTは単なるint、double、boolなので、実際には私の目的のために大丈夫です。しかし、この質問を閉じる前に好奇心から出てきました。完全な文字列サイズを得る方法はありますか? –

1

もし2つのスレッド(VB6でそれぞれ独自のウィンドウを持っているのであれば)は、変数VarPtr(blah)へのポインタを送るだけで、復帰する前にウィンドウプロシージャをコピーする必要があります。

ただし、スレッドが2つのプロセスに分かれている場合は、はるかに少ないオプションがあります。

あなたは後者の方法に適用されますWM_COPYDATAあなたのためのマーシャリングを行い、メッセージ、またはセットアップいくつかの共有/グローバルメモリを使用し、通常のSendMessage() 、通常のスレッド同期の実践を経て、ポインタ/オフセットを渡すことができます。

+0

同じプロセス内の複数のスレッド。 varptr(blah)を使ってオブジェクトへのポインタをクライアントに送ると仮定します。どのように私は受信側のユーザー定義型にポインタ(長い)を参照解除するのですか? –

+0

RtlMoveMemory2 tmp2、VarPtr(tmp)、LenB(tmp2)。 tmpとtmp2が同じプロセスのメモリ空間にある場合、tmpはtmp2にコピーされます。あなたのプロセス間に行くことが私の答えを使用する場合。 RtlMoveMemory2が定義されているのは私の答えです。 – Motes

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

素敵なアイデアです。 – wqw

関連する問題