Before starting, I would like to say that I agree with MarkJ. COM Interop will make your life much easier and will not require you to work.
SendMessage is the preferred way to call one or the other using Windows Message handlers. PostMessage is difficult to use with complex types, because the lifetime of the data associated with a Windows message in .NET and VB6 is difficult to control while the message is queued and the message completion is unknown unless you implement some form of callback mechanism.
Anyway, sending Windows messages from anywhere to the C # window just requires that you know the HWND of the C # window that should receive the message. Your snippet looks correct as a handler, except that the switch statement must first check the Msg parameter.
protected override void WndProc(ref Message m) { int _iWParam = (int)m.WParam; int _iLParam = (int)m.LParam; switch ((ECGCardioCard.APIMessage)m.Msg) {
Getting a window handle from C # Form, Window, or Control can be done using the .Handle property.
Control.Handle Property @MSDN
Suppose you have a way to port a window handle from C # to VB6.
From VB6, the signature of the SendMessage window is as follows:
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
To call it, you would do something like the following. For brevity, uMsg is WM_APP (32768), wParam / lParam is 0:
Dim retval As Long retval = SendMessage(hWnd, 32768, 0, 0)
Similarly, sending a message with C # is similar. To get HWND windows in VB6, use the .hWnd property of the window in VB6, which should receive the message.
It looks like you are using your own set of message identifiers, there are additional steps for handling custom message identifiers in VB6. Most people handle this by subclassing the form window and using the subclass procedure to filter these messages. I have included sample code to demonstrate C # on VB6, since handling custom messages is more complicated in VB6.
Here is the source code for a couple of test programs, a C # library, and a VB6 Forms project. The C # library must be configured with "Register for COM Interoperability" and "Make the Assembly COM-Visible" in the project settings.
First, the C # library. This library contains one COM component that will be visible to VB6 as the type CSMessageLibrary.TestSenderSimple. Note that you need to enable the P / Invoke signature (e.g. VB6 method) for SendMessage.
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace CSMessageLibrary { [ComVisible(true)] public interface ITestSenderSimple {
Now, on the VB6 side, you will need to add subclass support to the window. In addition to the best solutions that can be applied for each window, we’ll just move on to something that shows how to configure one window.
First, to run this sample, make sure you create a C # application and register it correctly with COM. Then add the link from VB6 to the .tlb file, which is next to the C # output. You will find this in the bin / Debug or bin / Release directory in a C # project.
The following code should be placed in the module. In my test project, I used a module called "Module1". The following definitions should be indicated in this module.
WM_APP - used as the user identifier of the message, which will be without interference.
GWL_WNDPROC - a constant that is used for SetWindowLong to request modification of a window handler.
SetWindowLong is a Win32 function that can change special attributes in windows.
The CallWindowProc function is Win32, which can send Windows messages to the designated window handler (function).
SubclassWindow - a module function for setting up a subclass for a selected window.
UnsubclassWindow - a module function for dropping a subclass for a selected window.
SubWndProc is a module function that will be inserted through a subclass so that we can intercept Windows user messages.
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
In the test form, I hooked up an instance of the C # test object as a member of the form. The form includes a button with the identifier "Command1". The subclass is configured when the form is loaded, and then deleted when the form is closed.
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
Sending numeric arguments that fit in 4 bytes is trivial, like in wParam or lParam. However, sending complex types and strings is much more complicated. I see that for this you have created a separate question, so I will give answers to it.
REF: How to send a structure from C # to VB6 and from VB6 to C #?