如题,我要实现两个进程窗体间的消息传递。
为了向另一个进程发送WM_COPYDATA消息,我封装了一个结构体:DataStruct
代码如下:
【模块中】:
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As String) As LongPublic Declare Function SendMessagelong Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As LongPublic Declare Function SendMessageAny Lib "user32" Alias "SendMessageA" _
    (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Any) As LongPublic Const WM_COPYDATA As Long = &H4A
Public frmHwnd As Long【窗体代码中】:
If frmHwnd <> 0 Then
'向窗体发送WM_COPYDATA消息
        DataStruct.lpData = Left(CtlText, 99)
        DataStruct.cbData = Len(DataStruct.lpData) + 1
        DataStruct.dwData = 100
        'SendMessage frmHwnd, WM_COPYDATA, 0, ByVal VarPtr(DataStruct)
        SendMessagelong frmHwnd, WM_COPYDATA, 0, ByVal VarPtr(DataStruct)
        'SendMessageAny frmHwnd, WM_COPYDATA, 0, ByVal DataStruct
End IfSendMessage语句,只有VarPtr(DataStruct)这行能触发接收进程程序中窗体的
DefWndProc回调事件,但接收不到数据-数据为空串(接收程序代码是正确的,已用2个c#程序
发送、接收消息测试通过)。
不知DataStruct数据如何传递,VarPtr?,RtlCopyMemory?ObjPtr?

解决方案 »

  1.   

    Public Declare Function SendMessageAny Lib "user32.dll" Alias "SendMessageA" ( _
         ByVal hwnd As Long, _
         ByVal wMsg As Long, _
         ByVal wParam As Long, _
         ByRef lParam As Any) As Long '<-注意是 ByRef'SendMessageAny frmHwnd, WM_COPYDATA, 0, DataStruct
      

  2.   

    DataStruct 所属的结构的类型定义在哪里?
      

  3.   

    还是不行,c#断点调试,接收到的字符串为空。
    vb其余代码为:
    Public CtlText As String    '控件文字
    Public Type COPYDATASTRUCT
        dwData As Integer
        cbData As Integer
        lpData As String
    End Type
    Public DataStruct As COPYDATASTRUCTCtlText = Text1.Text    '发送文字
    If frmHwnd <> 0 Then
            DataStruct.lpData = Left(CtlText, 99)
            DataStruct.cbData = Len(DataStruct.lpData) + 1
            DataStruct.dwData = 100
            SendMessageAny frmHwnd, WM_COPYDATA, 0, DataStruct
    End If-----------c#代码为-----------
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;using System.Runtime.InteropServices;//WindowsFormGetMsg
    namespace ProcessReceive
    {
        public partial class Form1 : Form
        {
            const int WM_COPYDATA = 0x004A;
            const int WM_USER = 0x0400;        public Form1()
            {
                InitializeComponent();
            }        private void Form1_Load(object sender, EventArgs e)
            {
                labelType.Text = "";
            }        protected override void DefWndProc(ref System.Windows.Forms.Message m)
            {
                COPYDATASTRUCT mystr = new COPYDATASTRUCT();
                Type mytype = mystr.GetType();
                switch(m.Msg)
                {
                    case WM_COPYDATA:
                        mystr =(COPYDATASTRUCT)m.GetLParam(mytype);
                        this.textBox1.Text =mystr.lpData;
                        labelType.Text = "WM_COPYDATA";
                        break;                default:
                        base.DefWndProc(ref m);
                        break;
                }
            }        private void button1_Click(object sender, EventArgs e)
            {
                textBox1.Text = "";
            }
        }    public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)] public string lpData;
        }
    }我的vb代码需要如何修改?
      

  4.   

    SendMessageAny 的函数声明 最后一个参数你改成ByRef了么?
      

  5.   

    SendMessageAny最后改成ByRef lParam As Any
      

  6.   

    不知COPYDATASTRUCT 结构体的定义是否正确呢?
      

  7.   

    改成这样定义试一下呢?Public Type COPYDATASTRUCT 
        dwData As Integer 
        cbData As Integer 
        lpData As String * 100 '假设你的字符串不超过100个字符'
    End Type 
      

  8.   

    已知道了,应该为:
    Public Type COPYDATASTRUCT
        dwData As Long
        cbData As Long
        lpData As String
    End Type
    Public DataStruct As COPYDATASTRUCT
    目前发送消息成功!
      

  9.   

    c#的int对应vb6的long型,指针都是long型的,我给忽略了,呵呵,看来使用语言不熟练是不行的
      

  10.   

    API 中应该是 ANSI 字符串。
    DataStruct.lpData = StrConv(Left(CtlText, 99),vbFromUnicode)
    DataStruct.cbData = LenB(DataStruct.lpData) + 1 
    DataStruct.dwData = 100
      

  11.   

    ProcessSend与c#的ProcessReceive程序通讯正常,但与vb的ProcessReceive程序通讯,
    只能接收到前面48个字节的数据。
    哪位把程序改改! 
    程序下载地址:
    http://download.csdn.net/source/1950913
      

  12.   

    10楼的StrConv不行呀,是不是接收进程也要相应的修改?
    Function WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Dim l As Long, sData As String
        
        'If Msg = WM_USER Then
        'End If
        If Msg = WM_COPYDATA Then
            pRecData = VarPtr(DatrStruct)
            '只能收到前面48个字符,不知道为什么???
            CopyMemory DatrStruct, ByVal lParam, LenB(DatrStruct)
            'DatrStruct.lpData = StrConv(DatrStruct.lpData, vbFromUnicode)
            Form1.Text1 = DatrStruct.lpData
            'WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
        Else
            WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
        End If
    End Function
      

  13.   

    pRecData 在哪里以及如何声明的?
      

  14.   

    DatrStruct在哪里以及如何声明的?
      

  15.   

    接收程序:
    【窗体】:
    Option Explicit
    Private Sub Form_Load()
        Text1.Text = "准备接收"
        TextHwnd1.Text = "句柄1:" & Text1.hwnd
        
    On Error GoTo 0
    'On Error Resume Next
        '这就是窗口子类化
        prevWndProc = GetWindowLong(Me.hwnd, GWL_WNDPROC)
        'AddressOf是取函数的地址,注意WndProc必须位于一个模块中
        SetWindowLong Me.hwnd, GWL_WNDPROC, AddressOf WndProc
        '-----------------
    End Sub'清空
    Private Sub Command1_Click()
        Text1.Text = ""
    End Sub模块:
    Option Explicit
    Public Const GWL_WNDPROC = (-4)
    Public Const WM_USER = &H400
    Public Const WM_COPYDATA As Long = &H4APublic Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
        (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
        (ByVal hwnd As Long, ByVal nIndex As Long) As Long
    Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
        (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As LongPublic Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
        (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
    'Public Declare Sub RtlMoveMemory Lib "KERNEL32" _
        (lpvDest As Any, lpvSource As Any, ByVal cbCopy As Long)Public prevWndProc As LongPublic Type COPYDATASTRUCT
        dwData As Long
        cbData As Long
        lpData As String
    End Type
    Public DatrStruct As COPYDATASTRUCT'为全局原子表添加一个原子
    '返回值:Long,如执行成功,返回原子值(&C000 到 &FFFF);零表示出错。会设置GetLastError
    Declare Function GlobalAddAtom Lib "kernel32" Alias "GlobalAddAtomA" _
    () '    (ByVal lpString As String) As IntegerPublic pRecData As Long
    Public sData As StringFunction WndProc(ByVal hwnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
        Dim l As Long, sData As String
        
        'If Msg = WM_USER Then
        'End If
        If Msg = WM_COPYDATA Then
            pRecData = VarPtr(DatrStruct)
            '只能收到前面48个字符,不知道为什么???
            CopyMemory DatrStruct, ByVal lParam, LenB(DatrStruct)
            'DatrStruct.lpData = StrConv(DatrStruct.lpData, vbFromUnicode)
            Form1.Text1 = DatrStruct.lpData
            'WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
        Else
            WndProc = CallWindowProc(prevWndProc, hwnd, Msg, wParam, lParam)
        End If
    End Function
      

  16.   

    ProcessSend与c#的ProcessReceive程序通讯正常,但与vb的ProcessReceive程序通讯, 
    只能接收到前面48个字节的数据。 
    哪位把程序改改! 
    程序下载地址: 
    http://download.csdn.net/source/1950913
      

  17.   

    dwData是结构长度,传lenb(DatrStruct)cbData是后面指针所指内容的长度,传lenb([字符串])lpData声明为一个String,然后直接赋值为字符串变量就行.
      

  18.   

    最后将结构体的定义改成了:
    Public Type COPYDATASTRUCT
        dwData As Long
        cbData As Long
        lpData As Long
    End Type
    Public DatrStruct As COPYDATASTRUCT
    两个vb的程序通讯成功
    感谢老马和楼上的各位!
      

  19.   

    声明为long是最好的,声明为string可能会遭遇VB自动进行的Unicode到ANSI的字符转换,导致各种问题。
    新年快乐!