Прежде чем я начну, я хотел бы сказать, что согласен с MarkJ. COM Interop сделает вашу жизнь намного проще и не потребует от вас столько работы.
SendMessage — это предпочтительный способ вызова той или иной стороны через обработчики сообщений Windows. PostMessage сложно использовать со сложными типами, так как временем жизни данных, связанных с сообщением Windows, как в .NET, так и в VB6, трудно управлять, пока сообщение находится в очереди, а завершение сообщения неизвестно, если вы не реализуете какой-либо механизм обратного вызова. .
В любом случае, отправка сообщений Windows из любого места в окно 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# Form, Window или Control можно с помощью свойства .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# аналогична. Чтобы получить HWND окна в VB6, используйте свойство .hWnd окна в VB6, которое должно получить сообщение.
Поскольку похоже, что вы используете свой собственный набор идентификаторов сообщений, есть дополнительные шаги для обработки пользовательских идентификаторов сообщений в VB6. Большинство людей справляются с этим путем создания подкласса окна формы и использования процедуры подкласса для фильтрации этих сообщений. Я включил пример кода, чтобы продемонстрировать C# для VB6, поскольку обработка пользовательских сообщений в VB6 сложнее.
Вот исходный код пары тестовых программ, библиотеки C# и проекта VB6 Forms. Библиотека C# должна быть настроена с помощью «Зарегистрировать для COM-взаимодействия» и «Сделать сборку 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, которая может изменять специальные атрибуты окон.
br> CallWindowProc — функция Win32, которая может передавать сообщения Windows назначенному обработчику окна (функции).
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# в качестве члена формы. Форма включает кнопку с идентификатором «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. Однако отправлять сложные типы и строки гораздо сложнее. Я вижу, что вы создали для этого отдельный вопрос, поэтому я дам ответы на него там.
Ссылка: Как отправить структуру из C# в VB6 и из VB6 в C#?
person
meklarian
schedule
24.11.2009