Avant de commencer, je voudrais dire que je suis d'accord avec MarkJ. COM Interop vous facilitera la vie et ne vous demandera pas de faire autant de travail.
SendMessage est le moyen préféré d'appeler un côté ou l'autre via les gestionnaires de messages Windows. PostMessage est difficile à utiliser avec des types complexes, car la durée de vie des données associées à un message Windows dans .NET et VB6 est difficile à gérer pendant la mise en file d'attente du message et la fin du message est inconnue sauf si vous implémentez un mécanisme de rappel . De toute façon, l'envoi de messages Windows de n'importe où à une fenêtre C# nécessite simplement que vous connaissiez le HWND de la fenêtre C# qui doit recevoir le message. Votre extrait semble correct en tant que gestionnaire, sauf que l'instruction switch doit d'abord vérifier le paramètre 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);
}
Récupération peut être fait une poignée de fenêtre à partir d'un formulaire C#, Fenêtre ou contrôle via la propriété .Handle.
Control.Handle Property @ MSDN
Nous supposerons ici que vous avez une façon de transférer la poignée de fenêtre de C# pour VB6.
De VB6, la signature de la fenêtre SendMessage est la suivante:
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
Pour appeler, vous feriez quelque chose comme ce qui suit. Par souci de concision, uMsg est WM_APP (32768), wParam/lParam sont 0:
Dim retval As Long
retval = SendMessage(hWnd, 32768, 0, 0)
De même, l'envoi d'un message de C# est similaire. Pour obtenir le HWND d'une fenêtre dans VB6, utilisez la propriété .hWnd de la fenêtre dans VB6 qui devrait recevoir le message.
Comme il semble que vous utilisez votre propre ensemble d'identifiants de message, il existe des étapes supplémentaires pour gérer les identifiants de message personnalisés dans VB6. La plupart des personnes gèrent cela en sous-classant une fenêtre de formulaire et en utilisant la procédure de sous-classe pour filtrer ces messages. J'ai inclus un exemple de code pour démontrer C# à VB6, car la gestion des messages personnalisés est plus compliquée dans VB6.
Voici le code source de la paire de programmes de test, une bibliothèque C# et un projet de formulaires VB6. La bibliothèque C# doit être configurée avec "Register for COM Interop" et "Make Assembly COM-Visible" dans les paramètres du projet.
D'abord, la bibliothèque C#. Cette bibliothèque contient un seul composant COM qui sera visible à VB6 sous le type 'CSMessageLibrary.TestSenderSimple'. Notez que vous devez inclure une signature P/Invoke (comme la méthode VB6) pour SendMessage.Maintenant, du côté VB6, vous aurez besoin d'ajouter un support pour sous-classer une fenêtre. Mis à part de meilleures solutions qui peuvent être appliquées par fenêtre, nous allons juste aller avec quelque chose qui montre comment configurer une seule fenêtre. Tout d'abord, pour exécuter cet exemple, assurez-vous que vous avez construit l'application C# et que vous l'avez correctement enregistré avec COM. Ajoutez ensuite une référence de VB6 au fichier .tlb qui se trouve à côté de la sortie C#. Vous le trouverez dans le répertoire bin/Debug ou bin/Release sous le projet C#.
Le code suivant doit être placé dans un module. Dans mon projet de test j'ai utilisé un module appelé 'Module1'. Les définitions suivantes doivent être notées dans ce module. WM_APP - Utilisé comme un identificateur de message personnalisé qui sera sans interférence.
GWL_WNDPROC - Constante utilisée pour SetWindowLong pour demander une modification du gestionnaire de fenêtre.
SetWindowLong - Fonction Win32 qui peut modifier les attributs spéciaux sur les fenêtres.
CallWindowProc - Fonction Win32 qui peut transmettre des messages Windows à un gestionnaire de fenêtre désigné (fonction).
SubclassWindow - Fonction de module pour configurer le sous-classement pour une fenêtre désignée. UnsubclassWindow - Fonction de module pour démonter le sous-classement pour une fenêtre désignée.
SubWndProc - Fonction du module qui sera insérée via le sous-classement, pour nous permettre d'intercepter les messages Windows personnalisés.
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
Dans le formulaire de test, j'ai câblé une instance de l'objet C# de test en tant que membre du formulaire. Le formulaire inclut un bouton dont l'ID est 'Command1'. La sous-classe est configurée lorsque le formulaire est chargé, puis supprimée lorsque le formulaire est fermé.
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
Envoi d'arguments numériques qui correspondent à 4 octets est trivial, soit en tant que wParam ou lParam. Cependant, l'envoi de types complexes et de chaînes est beaucoup plus difficile. Je vois que vous avez créé une question distincte pour cela, alors je vais fournir des réponses là-dessus.
REF: How do I send a struct from C# to VB6, and from VB6 to C#?
+1. Il y a une façon plus "objecty" de faire le sous-classement VB6 si http://visualstudiomagazine.com/articles/2009/07/16/subclassing-the-xp-way.aspx – MarkJ
Je suis allé avec cette méthode juste pour garder l'échantillon plus court. La technique à ce lien est définitivement supérieure, cependant. – meklarian
Quel super article !! +1 – used2could