我知道我可以在C#中的代码接收到下面的消息,我怎么送VB6,并在VB6接收,并从VB6送?
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message m)
{
int _iWParam = (int)m.WParam;
int _iLParam = (int)m.LParam;
switch ((ECGCardioCard.APIMessage)m.WParam)
{
// handling code goes here
}
base.WndProc(ref m);
}
我开始之前,我想说,我同意MarkJ。 COM互操作会让你的生活变得更轻松,也不会要求你做尽可能多的工作。
SendMessage消息是调用一个一侧或另一侧通过Windows消息处理程序的首选方式。 PostMessage的是艰难与复杂类型使用,与Windows消息在相关的数据的生命周期.NET和VB6是难以管理,而该消息在排队,除非你实现了某种形式的回调机制的消息完成未知。
总之,从任何地方到一个C#窗口发送消息窗口只要求你知道这是接收消息的C#窗口的HWND。 您的片段看起来是正确的,因为一个处理程序,除了switch语句应该检查对消息参数第一。
protected override void WndProc(ref Message m)
{
int _iWParam = (int)m.WParam;
int _iLParam = (int)m.LParam;
switch ((ECGCardioCard.APIMessage)m.Msg)
{
// handling code goes here
}
base.WndProc(ref m);
}
从C#形式检索窗口句柄,窗口或控制可以通过.Handle属性来完成。
Control.Handle物业@ MSDN
我们假设在这里,你有窗口句柄从C#传递给VB6的一些方法。
从VB6的窗口SendMessage函数的签名如下:
Private Declare Function SendMessage Lib "USER32.DLL" _
(ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
要调用它,你会做一些像下面这样。 为简洁起见,uMsg是WM_APP(32768),wParam参数/ lParam的是0:
Dim retval As Long
retval = SendMessage(hWnd, 32768, 0, 0)
同样地,发送从C#的消息是类似的。 为了获得在VB6窗口的HWND,使用窗口中VB6的.hWnd属性应该接收的消息。
因为它似乎是您使用的是自己的一组消息标识符,还有额外的步骤来处理VB6自定义消息标识符。 大多数人通过继承窗体窗口,并使用类过程来过滤这些信息处理这个问题。 我已经包括示例代码来演示C#来VB6因为处理自定义消息是在VB6棘手。
下面是对测试程序,一个C#库和VB6窗体项目的源代码。 C#的图书馆应以“注册为COM互操作”,并配置“让大会COM可见”在项目设置。
首先,C#库。 这个库包含了一个COM组件,这将是可见的VB6作为类型“CSMessageLibrary.TestSenderSimple”。 请注意,您需要包括一个SendMessage函数的P / Invoke签名(如VB6方法)。
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace CSMessageLibrary
{
[ComVisible(true)]
public interface ITestSenderSimple
{
// NOTE: Can't use IntPtr because it isn't VB6-compatible
int hostwindow { get; set;}
void DoTest(int number);
}
[ComVisible(true)]
public class TestSenderSimple : ITestSenderSimple
{
public TestSenderSimple()
{
m_HostWindow = IntPtr.Zero;
m_count = 0;
}
IntPtr m_HostWindow;
int m_count;
#region ITestSenderSimple Members
public int hostwindow
{
get { return (int)m_HostWindow; }
set { m_HostWindow = (IntPtr)value; }
}
public void DoTest(int number)
{
m_count++;
// WM_APP is 0x8000 (32768 decimal)
IntPtr retval = SendMessage(
m_HostWindow, 0x8000, (IntPtr)m_count, (IntPtr)number);
}
#endregion
[DllImport("user32.dll", CharSet = CharSet.Auto)]
extern public static IntPtr SendMessage(
IntPtr hwnd, uint msg, IntPtr wparam, IntPtr lparam);
}
}
现在,在VB6的一面,你将需要添加支持的子类的窗口。 除了更好的解决方案,可以为每个窗口的应用,我们还是要的东西,展示了如何建立一个窗口。
首先,运行此示例,请确保您已经建立了C#应用程序,并正确地与COM注册它。 然后从VB6添加引用.tlb文件是沿着C#输出。 您将在C#项目下的bin / Debug或Bin / Release目录中找到它。
下面的代码应放置成模块。 在我的测试项目中,我使用了一种叫做“模块1”模块。 以下定义应在此模块中注明。
WM_APP - 用作一个自定义的消息标识符,这将是无干扰的。
GWL_WNDPROC - 常量,其用于SetWindowLong函数来请求修改的窗口处理。
SetWindowLong函数 - Win32函数可在Windows修改的特殊属性。
CallWindowProc的 - 即可以中继窗口信息发送到指定的窗口句柄(函数)Win32函数。
调用SubclassWindow - 模块功能设置为子类指定的窗口。
UnsubclassWindow - 模块功能推倒继承了指定的窗口。
SubWndProc - 将通过子类插入模块功能,让我们截取自定义Windows消息。
Public Const WM_APP As Long = 32768
Private Const GWL_WNDPROC = (-4)
Private procOld As Long
Private Declare Function CallWindowProc Lib "USER32.DLL" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal uMsg As Long, _
ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function SetWindowLong Lib "USER32.DLL" Alias "SetWindowLongA" _
(ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Sub SubclassWindow(ByVal hWnd As Long)
procOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf SubWndProc)
End Sub
Public Sub UnsubclassWindow(ByVal hWnd As Long)
procOld = SetWindowLong(hWnd, GWL_WNDPROC, procOld)
End Sub
Private Function SubWndProc( _
ByVal hWnd As Long, _
ByVal iMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
If hWnd = Form1.hWnd Then
If iMsg = WM_APP Then
Dim strInfo As String
strInfo = "wParam: " & CStr(wParam) & vbCrLf & "lParam: " & CStr(lParam)
Call MsgBox(strInfo, vbOKOnly, "WM_APP Received!")
SubWndProc = True
Exit Function
End If
End If
SubWndProc = CallWindowProc(procOld, hWnd, iMsg, wParam, lParam)
End Function
在测试形式,我已经有线了测试C#对象的一个实例为以下形式的构件。 形式包括按钮,其ID是“COMMAND1”。 亚类是设置时的形式的负载,并且当关闭窗体然后取出。
Dim CSharpClient As New CSMessageLibrary.TestSenderSimple
Private Sub Command1_Click()
CSharpClient.DoTest (42)
End Sub
Private Sub Form_Load()
CSharpClient.hostwindow = Form1.hWnd
Module1.SubclassWindow (Form1.hWnd)
End Sub
Private Sub Form_Unload(Cancel As Integer)
CSharpClient.hostwindow = 0
Module1.UnsubclassWindow (Form1.hWnd)
End Sub
以4个字节发送适合的数值参数是微不足道的,无论是作为wParam参数或lParam的。 然而,发送复杂类型和字符串是更加艰难。 我看到你已经创建了一个单独的问题,所以我会提供答案那边。
REF:如何发送一个结构从C#到VB6,并从VB6到C#?
要在VB6送你需要使用一个API调用( SendMessage函数或PostMessage的)。 为了接收VB6,你需要使用子类(复杂-这里是我知道的最好的方式 )。
你有没有考虑使用COM互操作呢? 这是一个容易得多VB6和C#比Windows消息之间的沟通方式。
使用PostMessage的Windows API函数。
在类的开头:
[DllImport("User32.dll", EntryPoint="PostMessage")]
private static extern int PostMessage(int hWnd, int Msg, int wParam, int lParam);
const int WM_USER = 0x0400;
const int CM_MARK = WM_USER + 1;
然后通过覆盖类的WndProc处理消息。
protected override void WndProc(ref Message m)
{
if (m.Msg == CM_MARK) {
if (this.ActiveControl is TextBox) {
((TextBox)this.ActiveControl).SelectAll();
}
}
base.WndProc(ref m);
} // end sub.
然后在您输入的事件:
private void txtMedia_Enter(object sender, EventArgs e)
{
PostMessage(Handle.ToInt32(), CM_MARK, 0, 0);
} // end sub.
这工作,因为你强迫你的自定义处理Windows不会Enter事件的它的默认处理后,会出现与它相关的鼠标操作。 你把消息队列您的请求,并依次进行处理,在WndProc中的事件。 当您的活动被调用时,你要确保当前窗口是一个文本框,然后选择它,如果它是。