我们知道Window进程之间通过API的SendMessage方法传递消息。但是方法参数lParam是Long型,那么如果传递一个字符串(譬如命令行参数)应该怎么办呢,甚至一个对象、结构呢。VB的发送接收需要通过传递指针实现(换言之是字符串的内存地址),下面总结VB方式、C#方式各自如何实现消息的发送与接收;各自是可以互换的,譬如C#发送的消息,VB窗口可以收到;相反亦可以。当然同种语言之间更加没问题了。
VB发送端 Form1.frm:
复制代码
1 Option Explicit
2
3 Private Type COPYDATASTRUCT
4 dwData As Long
5 cbData As Long
6 lpData As Long
7 End Type
8
9 Private Const WM_COPYDATA = &H4A
10
11 Private Declare Function FindWindow Lib "user32" Alias _
12 "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName _
13 As String) As Long
14
15 Private Declare Function SendMessage Lib "user32" Alias _
16 "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal _
17 wParam As Long, lParam As Any) As Long
18
19 'Copies a block of memory from one location to another.
20 Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
21 (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
22
23 Private Sub Command1_Click()
24 Dim cds As COPYDATASTRUCT
25 Dim ThWnd As Long
26 Dim buf(1 To 1024) As Byte
27 Dim a As String, i As Long, lLen As Long
28
29 ' Get the hWnd of the target application
30 ThWnd = FindWindow(vbNullString, "Target")
31 a$ = "It Works on " & Format(Now, "yyyy-MM-dd HH:mm:ss") & " !"
32 ' Copy the string into a byte array, converting it to ASCII
33 lLen = LenB(StrConv(a, vbFromUnicode))
34 Call CopyMemory(buf(1), ByVal a, lLen)
35 cds.dwData = 3
36 cds.cbData = lLen + 1
37 cds.lpData = VarPtr(buf(1))
38 i = SendMessage(ThWnd, WM_COPYDATA, Me.hwnd, cds)
39 End Sub
40
41 Private Sub Form_Load()
42 ' This gives you visibility that the target app is running
43 ' and you are pointing to the correct hWnd
44 Me.Caption = Hex$(FindWindow(vbNullString, "Target"))
45 End Sub
复制代码
VB接收端
1。MsgHook.bas:
复制代码
1 Option Explicit
2
3 Type COPYDATASTRUCT
4 dwData As Long
5 cbData As Long
6 lpData As Long
7 End Type
8
9 Public Const GWL_WNDPROC = (-4)
10 Public Const WM_COPYDATA = &H4A
11 Global lpPrevWndProc As Long
12 Global gHW As Long
13
14 'Copies a block of memory from one location to another.
15 Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
16 (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)
17
18 Declare Function CallWindowProc Lib "user32" Alias _
19 "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As _
20 Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As _
21 Long) As Long
22
23 Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
24 (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As _
25 Long) As Long
26
27 Public Sub Hook()
28 lpPrevWndProc = SetWindowLong(gHW, GWL_WNDPROC, _
29 AddressOf WindowProc)
30 Debug.Print lpPrevWndProc
31 End Sub
32
33 Public Sub Unhook()
34 Dim temp As Long
35 temp = SetWindowLong(gHW, GWL_WNDPROC, lpPrevWndProc)
36 End Sub
37
38 Function WindowProc(ByVal hw As Long, ByVal uMsg As Long, _
39 ByVal wParam As Long, ByVal lParam As Long) As Long
40 If uMsg = WM_COPYDATA Then
41 Call mySub(lParam)
42 End If
43 WindowProc = CallWindowProc(lpPrevWndProc, hw, uMsg, wParam, lParam)
44 End Function
45
46 Sub mySub(lParam As Long)
47 Dim cds As COPYDATASTRUCT
48 Dim buf(1 To 1024) As Byte
49 Dim a As String
50
51 Call CopyMemory(cds, ByVal lParam, Len(cds))
52
53 Select Case cds.dwData
54 Case 1
55 Debug.Print "got a 1"
56 Case 2
57 Debug.Print "got a 2"
58 Case 3
59 Call CopyMemory(buf(1), ByVal cds.lpData, cds.cbData)
60 a$ = StrConv(buf, vbUnicode)
61 a$ = Left$(a$, InStr(1, a$, Chr$(0)) - 1)
62 Form1.Label1.Caption = a$
63 End Select
64 End Sub
复制代码
2。Target.frm:
复制代码
1 Option Explicit
2
3 Private Sub Form_Load()
4 gHW = Me.hwnd
5 Hook
6 Me.Caption = "Target"
7 Me.Show
8 Label1.Caption = Hex$(gHW)
9 End Sub
10
11 Private Sub Form_Unload(Cancel As Integer)
12 Unhook
13 End Sub
复制代码
C#的发送端:
复制代码
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Data;
8 using System.Windows.Documents;
9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14 using System.Runtime.InteropServices;
15
16 namespace CSMsgSender
17 {
18 /// <summary>
19 /// MainWindow.xaml 的交互逻辑
20 /// </summary>
21 public partial class MainWindow : Window
22 {
23 public MainWindow()
24 {
25 InitializeComponent();
26 }
27
28 private void button1_Click(object sender, RoutedEventArgs e)
29 {
30 int hwnd = FindWindow(null, "Target");
31 if (hwnd != 0)
32 {
33 string str = "It Works on " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " !";
34 byte[] arr = System.Text.Encoding.Default.GetBytes(str);
35 int len = arr.Length;
36 COPYDATASTRUCT cdata;
37 cdata.dwData = 3;
38 cdata.lpData = str;
39 cdata.cbData = len + 1;
40 SendMessage(hwnd, WM_COPYDATA, 10, ref cdata);
41 }
42 }
43
44 [DllImport("User32.dll")]
45 public static extern int SendMessage(int hwnd, int msg, int wParam, ref COPYDATASTRUCT lParam);
46 [DllImport("User32.dll")]
47 public static extern int FindWindow(string lpClassName, string lpWindowName);
48
49 private const int WM_COPYDATA = 0x004A;
50 public struct COPYDATASTRUCT
51 {
52 public int dwData;
53 public int cbData;
54 [MarshalAs(UnmanagedType.LPStr)]
55 public string lpData;
56 }
57 }
58 }
复制代码
C#接收端:
复制代码
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Data;
5 using System.Drawing;
6 using System.Linq;
7 using System.Text;
8 using System.Windows.Forms;
9 using System.Runtime.InteropServices;
10
11 namespace CSMsgReceiver
12 {
13 public partial class Form1 : Form
14 {
15 public Form1()
16 {
17 InitializeComponent();
18 this.Text = "Target";
19 }
20
21 protected override void DefWndProc(ref Message m)
22 {
23 switch (m.Msg)
24 {
25 case WM_COPYDATA:
26 COPYDATASTRUCT cdata = new COPYDATASTRUCT();
27 Type mytype = cdata.GetType();
28 cdata = (COPYDATASTRUCT)m.GetLParam(mytype);
29 this.textBox1.Text = cdata.lpData;
30 break;
31 default:
32 base.DefWndProc(ref m);
33 break;
34 }
35 }
36
37 //WM_COPYDATA消息的主要目的是允许在进程间传递只读数据。
38 private const int WM_COPYDATA = 0x004A;
39
40 //Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。
41 //其中,WM_COPYDATA对应的十六进制数为0x004A
42 public struct COPYDATASTRUCT
43 {
44 public int dwData;
45 public int cbData;
46 [MarshalAs(UnmanagedType.LPStr)]
47 public string lpData;
48 }
49 }
50 }
复制代码