gpt4 book ai didi

c# - 如何在VB6和C#之间发送/接收Windows消息?

转载 作者:太空狗 更新时间:2023-10-30 00:28:57 24 4
gpt4 key购买 nike

我知道我可以用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);
}

最佳答案

在我开始之前,我想说我同意马克。COM互操作将使您的生活更轻松,不需要您做那么多的工作。
SendMessage是通过Windows消息处理程序调用一方或另一方的首选方法。postmessage很难用于复杂类型,因为当消息排队时,.net和vb6中与windows消息相关联的数据的生存期很难管理,并且除非实现某种形式的回调机制,否则消息的完成情况未知。
无论如何,从任何地方向c窗口发送windows消息只需要知道接收消息的c窗口的hwnd。作为处理程序,您的代码片段看起来是正确的,只是switch语句应该首先检查msg参数。

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);
}

可以通过.handle属性从C窗体、窗口或控件检索窗口句柄。
Control.Handle Property @ 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中还有一些额外的步骤来处理自定义消息标识符。大多数人通过将窗体窗口子类化并使用子类过程过滤这些消息来处理此问题。由于在vb6中处理自定义消息更为棘手,因此我提供了示例代码来演示c到vb6。
这是两个测试程序、一个C库和一个VB6窗体项目的源代码。应在项目设置中将C库配置为“注册COM互操作”和“使程序集COM可见”。
首先是图书馆。此库包含一个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引用添加到C输出旁边的.tlb文件。您可以在c项目下的bin/debug或bin/release目录中找到它。
以下代码应放入模块中。在我的测试项目中,我使用了一个名为“module1”的模块。本单元应注意以下定义。
wm_app-用作无干扰的自定义消息标识符。
gwl_wndproc-用于setwindowlong请求修改窗口处理程序的常量。
setwindowlong-可以修改windows上特殊属性的win32函数。
callwindowproc-win32函数,可以将windows消息中继到指定的窗口处理程序(函数)。
子类窗口-为指定窗口设置子类的模块函数。
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

在测试表单中,我将test 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: How do I send a struct from C# to VB6, and from VB6 to C#?

关于c# - 如何在VB6和C#之间发送/接收Windows消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1645204/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com