Bonjour !
Voilà, j'au dû me mettre au C# il y a quelque jours afin de réaliser un composant ActiveX.
J'ai besoin que ce composant puisse m'envoyer des événements pouvant être "captés" depuis la page HTML qui l'utilisera.
Après avoir passer pas mal de temps à chercher de la doc sur la création d'activeX en C# et sur la gestion d'événements, jai pu arrivé à une solution ().
Lorsque j'appelle une méthode de mon objet intégré dans la page, cela lance bien un événement et arrive à bien être capté dans lapage HTML.
Mais pour les besoins que j'ai, ces évenements devront être lancés par un thread réalisant une tâche dépendante.
Et c'est là que le problème intervient. Lorsque depuis le thread, je fais appel la méthode de "l'objet parent" (si vous me permettez l'expression) cela me lève une Exception bien spécifique .. alors que cela fonctionne lorsqu'elle est appelée directement via la page HTML ??
Ainsi, pour les besoins de l'explication, j'ai tenté de vous proposer une version "light" de mon problème. Le composant repose sur un TextBox qui me permet de "tracer" différents messages.
Voici la page HTML qui intègre le composant :
et le code C# associé
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 <html> <head><title>ActiveXSourcingAutre</title> <script language="javascript"> function FoncActiveThreadJs() { if(monObj){ monObj.FoncActiveThread('CHAPI','CHAPO'); } else alert('JS: FoncActiveThreadJs() : monObj non disponible'); } function demLance() { if(monObj){ monObj.demandeLance(); } else alert('JS: demLance() : monObj non disponible'); } </script> </head> <body> <object id="monObj" classid="activex/ActiveXSourcingAutre.dll#ActiveXSourcingAutre.MyWindowControlAutre"></object> <script LANGUAGE="JavaScript" for="monObj" event="ClickEventThread(a,b)"> alert("Evenement capte avec ["+a+"]["+b+"]"); </script> <br /> <a href="javascript: FoncActiveThreadJs();">FoncActiveThreadJs</a><br /> <A href="javascript: demLance();">demLance</A> </body> </html>
Resultat obtenu :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using System.Runtime.InteropServices; using System.Threading; using System.Reflection; namespace ActiveXSourcingAutre { public delegate void ClickEventHandlerThread(string a, string b); [System.Runtime.InteropServices.GuidAttribute("9621A92C-3FBD-4be4-9153-51EEC1444507")] [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)] public interface ControlEventsAutre { [System.Runtime.InteropServices.DispIdAttribute(0x60035000)] void ClickEventThread(string a, string b); } [System.Runtime.InteropServices.InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIDispatch)] public interface MonInterfaceAutre { [System.Runtime.InteropServices.DispIdAttribute(0x60060003)] void demandeLance(); [System.Runtime.InteropServices.DispIdAttribute(0x60060007)] void FoncActiveThread(string a, string b); } public class MonThreadHandle { MyWindowControlAutre mxcparent; public MonThreadHandle(MyWindowControlAutre mxcparam) { this.mxcparent = mxcparam; } public void AffichageInterp() { mxcparent.FoncActiveThread("JOJO", "JUJU"); } public void ThreadLoop() { // .... Réalise différents traitements (attente de lectures asynchrones notamment ..) // et dans un cas particulier fait appel à la fonction suivante AffichageInterp(); } } [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None), System.Runtime.InteropServices.ComSourceInterfaces(typeof(ControlEventsAutre))] public class MyWindowControlAutre : System.Windows.Forms.UserControl, MonInterfaceAutre //, ComInteropControlInterface { System.Windows.Forms.TextBox tx = new TextBox(); MonThreadHandle threadHandle; Thread t; event ActiveXSourcingAutre.ClickEventHandlerThread ClickEventThread; private void InitializeComponent() { this.Name = "MyWindowControlAutre"; } public MyWindowControlAutre() : base() { initMyWindowControlAutre(); } private void initMyWindowControlAutre() { tx.Text = ""; Size = new System.Drawing.Size(700, 450); tx.Size = this.Size; tx.Multiline = true; tx.ScrollBars = ScrollBars.Vertical; tx.AcceptsReturn = true; tx.AcceptsTab = true; tx.WordWrap = true; this.Controls.Add(tx); } public void demandeLance() { Lance(); } //[STAThread] void Lance() { threadHandle = null; t = null; try { threadHandle = new MonThreadHandle(this); t = new Thread(new ThreadStart(threadHandle.ThreadLoop)); t.Start(); } catch { traceFen("Thead non lance"); return; } } public void FoncActiveThread(string a, string b) { traceFen("Etape A : FoncActiveThread :: a=" + a + " b=" + b); ClickEventThread = new ClickEventHandlerThread(ClickEventThread); MonOpThread(a, b); } public void MonOpThread(string a, string b) { try { traceFen("Etape B : MonOpThread :: MonOpThread a=" + a + " b=" + b); if (ClickEventThread != null) { traceFen("Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread"); ClickEventThread(a, b); } } catch (TargetException te) { traceFen("## Exception dans MonOpThread (TargetException):: Message [[" + te.Message + "]]"); } catch (Exception e) { traceFen("## Exception dans MonOpThread :: " + e.Message); } } public void traceFen(string p) { tx.Text += p + "\r\n"; } } }
Si depuis le navigateur, je lance un appel à la monObj.FoncActiveThread('CHAPI','CHAPO'), j'obtiens bien les traces suivantes :
l'événement est bien lancé et ma page HTML le capte bien.. nickel.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4Etape A : FoncActiveThread :: a=CHAPI b=CHAPO Etape B : MonOpThread :: MonOpThread a=CHAPI b=CHAPO Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread
Mais lorsque, toujours depuis le navigateur, je fais appel à monObj.demandeLance(), le composant va bien lancer dans un processus différent l'execution de la méthode ThreadLoop() de mon objet de type MonThreadHandle.
Depuis ce processus, sera alors appelé la même méthode que précedement (FoncActiveThread()) de l'objet "parent".
Le positionnement du handler est alors réalisé, mais lorsque je fais appel au même bout de code qui me permettait de réaliser l'envoi de l'évenement, une exception de type TargetException est alors lancée, indiquant "L'objet ne correspond pas au type cible."
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 Etape A : FoncActiveThread :: a=JOJO b=JUJU Etape B : MonOpThread :: MonOpThread a=JOJO b=JUJU Etape C : MonOpThread :: ClickEventThread diffrent null tente ClickEventThread ## Exception dans MonOpThread (TargetException):: Message [[L'objet ne correspond pas au type cible.]]
Donc si quelqu'un aurait une petite explication sur l'erreur retournée, cela serait avec grand plaisir .. d'autant que là .. j'essaie différents moyens . mais cela ne passe toujours pas ..
Merci d'avance pour votre attention .. et surtout à ceux qui auront lu ce looooong post.
Partager