Прежде чем начать, я бы хотел сказать, что согласен с MarkJ. COM Interop сделает вашу жизнь намного проще и не потребует от вас столько работы.
SendMessage является предпочтительным способом вызова одной или другой стороны через обработчики сообщений Windows. PostMessage сложно использовать со сложными типами, поскольку временем жизни данных, связанных с сообщением Windows, как в .NET, так и в VB6 трудно управлять, пока сообщение находится в очереди, и завершение сообщения неизвестно, если вы не реализуете какую-либо форму механизма обратного вызова .
В любом случае, отправка оконных сообщений из любого места в окно C # просто требует, чтобы вы знали HWND окна C #, которое должно принимать сообщение. Ваш фрагмент выглядит как корректный обработчик, за исключением того, что оператор 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);
}
Извлечение дескриптора окна из формы, окна или элемента управления C # можно выполнить с помощью свойства .Handle.
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 # аналогична. Чтобы получить HWND окна в VB6, используйте свойство .hWnd окна в VB6, которое должно получить сообщение.
Поскольку кажется, что вы используете свой собственный набор идентификаторов сообщений, существуют дополнительные шаги для обработки пользовательских идентификаторов сообщений в VB6. Большинство людей справляются с этим путем создания подкласса окна формы и использования процедуры подкласса для фильтрации этих сообщений. Я включил пример кода для демонстрации C # для VB6, так как обработка пользовательских сообщений сложнее в VB6.
Вот исходный код для пары тестовых программ, библиотеки C # и проекта форм VB6. Библиотека C # должна быть настроена на «Регистрация для взаимодействия COM» и «Сделать сборку видимой» в настройках проекта.
Во-первых, библиотека C #. Эта библиотека содержит один компонент COM, который будет виден VB6 как тип 'CSMessageLibrary.TestSenderSimple'. Обратите внимание, что вам нужно включить подпись P / Invoke (например, метод VB6) для SendMessage.
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 #. Вы найдете это в каталоге bin / Debug или bin / Release в проекте C #.
Следующий код должен быть помещен в модуль. В моем тестовом проекте я использовал модуль под названием «Module1». Следующие определения должны быть отмечены в этом модуле.
WM_APP - используется в качестве пользовательского идентификатора сообщения, который не будет создавать помех.
GWL_WNDPROC - Константа, используемая для SetWindowLong для запроса модификации в обработчике окна.
SetWindowLong - функция Win32, которая может изменять специальные атрибуты на окнах.
CallWindowProc - функция Win32, которая может передавать сообщения Windows назначенному обработчику окна (функция).
SubclassWindow - функция модуля для настройки подклассов для назначенного окна.
UnsubclassWindow - функция модуля для разделения подклассов для назначенного окна.
SubWndProc - функция модуля, которая будет вставлена с помощью подклассов, чтобы позволить нам перехватывать сообщения пользовательских окон
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 # в качестве члена формы. Форма включает в себя кнопку с идентификатором «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 #?