rvblog
Messages postés792Date d'inscriptionvendredi 4 mars 2005StatutMembreDernière intervention12 juin 2012
-
14 sept. 2006 à 18:52
rvblog
Messages postés792Date d'inscriptionvendredi 4 mars 2005StatutMembreDernière intervention12 juin 2012
-
16 sept. 2006 à 15:13
Salut à toutes et à tous,
je ne pose, en principe que 2 questions par an, la 1ère était brève, voici la 2ème:
Cette question, je la pose à toute la communauté, et plus particulièrement aux "affranchis" de l'API Window (2k sp4, et XP).
Evidemment, vu comme cela, on pourrait se dire que cette question a sa place dans le thème API! Mais non, la réponse y a peut-être sa place, si c'est un "affranchi" qui y répond, mais la réponse peut être d'un autre domaine (si je l'avais, je saurais duquel).
Contexte :
En VB6, je crée 3 projets : une bibliothèque d'interfaces (dll ActiveX), un complément (dll ActiveX) et un client utilisant le complément (exe standard).
Le sujet est donc en rapport avec les interfaces, mais plus particulièrement, l'implémentation des notifications serveur vers client (et non le contraire, quoique le problème s'y pose, je crois, aussi).
Le besoin est :
Le complément, après avoir reçu, via une interface, un signal le lui demandant, veut envoyer une image (icone, image...) à son client, via une autre interface (de la même bibliothèque).
Pour répondre à ce besoin, et en suivant les préconisations Microsoft, j'ai réalisé l'architecture suivante (je ne décris que la notification serveur vers client) :
La bibliothèque XOMforNBCModules expose une interface IModuleEvents, qui déclare une fonction SetPicture, dont voici les signatures que j'ai essayées :
1/ Public Function SetPicture(Byref picPicture As StdPicture)
End Function
2/ Public Function SetPicture(Byref picPicture AsObject)
End Function
3/ Public Function SetPicture() As StdPicture
End Function
4/ Public Function SetPicture() AsObject
End Function
La bibliothèque expose aussi une classe publique clsModuleEvents qui implémente l'interface (Implements IModuleEvents), et reçoit, pour contrat, une fonction, dont voici les signatures correspondant aux divers essais :
1/ Public Function IModuleEvents_SetPicture(picPicture As stdole.Picture) AsVariant
End Function
2/ Public Function IModuleEvents_SetPicture(picPicture AsObject) AsVariant
End Function
3/ Public Function IModuleEvents_SetPicture() As stdole.Picture
End Function
4/ Public Function IModuleEvents_SetPicture() AsObject
End Function
Cette classe publique clsModuleEvents déclare un évènement dont la signature est aussi adaptée aux différents essais :
Public Event SetPicture(Byref picPicture As StdPicture) , pour le 1/ et le 3/
ou
Public Event SetPicture(Byref picPicture AsObject) , pour le 2/ et le 4/
et quelque soit le cas, la fonction implémentée élève l'évènement, par exemple :
1/ Public Function IModuleEvents_SetPicture(picPicture As stdole.Picture) AsVariant
RaiseEvent SetPicture(picPicture)
End Function
Le complément UserModule déclare une propriété ModuleEvents, de type XOMforNBCModules.IModuleEvents (sans handler d'évènements), et l'initialise avec une instance de la classe publique XOMforNBCModules.clsModuleEvents, ce qui donne :
Private m_ModuleEvents As XOMforNBCModules.IModuleEvents
Public PropertyGet ModuleEvents() As XOMforNBCModules.IModuleEvents
Set ModuleEvents = m_ModuleEvents
End Property
Public PropertySet ModuleEvents(byval vNewValue As XOMforNBCModules.IModuleEvents)
Set m_ModuleEvents = vNewValue
End Property
Private Sub Class_Initialize()
Set m_ModuleEvents = New XOMforNBCModules.clsModuleEvents
End Sub
Le complément UserModule , dans une procédure de l'interface des signaux client vers serveur, fait un appel à la méthode de notification SetPicture :
Private Sub IModuleServices_GetPicture()
...
...
m_ModuleEvents.SetPicture(picLaPictureBox.Picture)
End Sub
Le client déclare une propriété ModuleEvents, de type XOMforNBCModules.clsModuleEvents, et l'initialise avec une instance de la classe publique XOMforNBCModules.clsModuleEvents qu'il a reçu via l'instance du complément, ce qui donne :
Private WithEvents m_ModuleEvents As XOMforNBCModules.clsModuleEvents
Public Property Get ModuleEvents() As XOMforNBCModules.clsModuleEvents
Set ModuleEvents = m_ModuleEvents
End Property
Public Property Set ModuleEvents(byval vNewValue As XOMforNBCModules.clsModuleEvents)
Set m_ModuleEvents = vNewValue
End Property
Le client récupère un évènement déclenché lors de la notification par son serveur, ce qui donne :
Private Sub m_ModuleEvents_SetPicture(picPicture As stdole.StdPicture)
...
End Sub
ou
Private Sub m_ModuleEvents_SetPicture(picPicture AsObject)
...
End Sub
On remarquera, au passage, que VB s'amuse allègrement à changer le nom du type StdPicture au fur et à mesure de son passage à travers les signatures : je délcare StdPicture, il transcrit stdole.Picture, puis je déclare StdPicture, il transcrit stdole.StdPicture!
Au delà de cette constatation (ce qui n'exclue pas qu'elle puisse être la clé de la solution à mon problème), il m'apparait impossible de faire passer mon objet Picture à travers ce maillage. Dès l'appel de la fonction de notification SetPicture par le serveur, VB dit :
-2147418113, Erreur Automation, Défaillance irrémédiable (que l'audience se rassure, le message fait peur, mais il ne se passe rien de terrible).
On notera qu'avec la signature typée Object, je peux lui passer n'importe quel type d'objet (enfin ceux que j'ai essayé, intrinsèque ou utilisateur), sauf des Picture (même un espion, qui m'en dit beaucoup sur le Height, Width, Name... d'un PictureBox que je lui passe, est incapable de me dire autre chose que <Erreur Automation> lorsque je cherche à observer sa propriété Picture).
Aussi, je me demande si quelqu'un peut m'en apprendre plus sur la portée et la durée de vie de la propriété Picture d'un PictureBox, situé sur un formulaire (visible ou caché), instancié dans une dll ActiveX, cherchant à traverser une interface dll ActiveX, pour rejoindre un exe Standard?
J'aurais pu commencer par cette simple question, mais il aurait fallu que j'explique ensuite :) Normalement, si mes calculs sont, vous n'êtes pas très nombreux à la lire :)
Merci d'avance à ceux qui arrivent jusque là sans zapper, merci encore plus à ceux qui me donneront la clé.
à+
PS : ce n'est pas vital, j'ai une solution paliative qui consiste à passer un tableau de bits grâce à GetBitmapsBits, mais ce n'est pas standard (enfin pas en terme d'interface utilisateur), et j'hésite à demander aux développeurs de compléments de manipuler l'API pour m'envoyer une image, car s'ils ne le font pas de leur côté (ou s'ils le font mal), moi, de l'autre côté j'utilise quand même SetBitmapsBits pour récupérer les données, et c'est risqué.
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
PCPT
Messages postés13272Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201847 15 sept. 2006 à 22:48
ah beh çà peut carrément jouer oui! je suis en 9EF9BF70-DFE1-42A1-A4C8-39718C7E381D&displaylang=en SP6.
exemple de bug (sans rapport) :
un slider maison avec des point line etc...
impossible de le redimentionner (manuellement et par code), uniquement parce que "pas de SP".
résolu en installant le SP6. pas de miracle....
ps : non par contre j'eu cru lire quelque part que tu voulais gérer les rss... lu sur une source il me semble...
j'ai prévu d'intégrer une bonne partie rss/xml ...
mon MP est ton MP ^^
<hr size ="2" width="100%" />Prenez un instant pour répondre à ce sondage svp
PCPT
Messages postés13272Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201847 15 sept. 2006 à 02:24
salut rvblog,
en voilà une question qu'elle est détaillée ^^
bon, procédons par étape.
durée de vie d'un stdpicture dans un contexte normal (c'est à dire simple utilisation et sans être déchargé), il dure de son instanciation à sa destruction.
je détaille pour tous les lecteurs (dont moi ^^)
test : nouveau projet exe, un bouton (et 2 jpg à la racine de c:\)
'= ====================================
' TEST 1
'=====================================
' =-=-=-=-=-=-=-=
' Form1.frm (exe)
' =-=-=-=-=-=-=-=
'
Option Explicit
Dim obj As New StdPicture
'
Private Sub Form_Load()
Set obj = LoadPicture ("c:\tmp1.jpg")
Me.Picture = obj
End Sub
'
Private Sub Form_Unload(Cancel As Integer)
Set obj = Nothing
End Sub
Private Sub Command1_Click()
Me.Picture = LoadPicture ("c:\tmp2.jpg")
l'objet se charge, ok. et le click nous prouve que me.picture et obj sont dissociés (désolé je fais des tests en même temps... la première ligne de click est pour vérifier si obj a changé, ce qui n'est pas le cas)
même principe avec une dll.
donc j'ajoute un projet dll nommé pj_dll, et la classe ClsUserModule
(ps, l'exe = form1 pour pj_exemple)
on sauve tout et la dll (projet) est en référence.
même config que pour test1 :
'=====================================
' TEST 2
'=====================================
' =-=-=-=-=-=-=-=
' Form1.frm (exe)
' =-=-=-=-=-=-=-=
'
Option Explicit
Private WithEvents UserModule As Pj_dll.ClsUserModule
'
Private Sub Form_Load()
Set UserModule = New Pj_dll.ClsUserModule
End Sub
'
Private Sub Form_Unload(Cancel As Integer)
Set UserModule = Nothing
End Sub
'
Private Sub Command1_Click()
UserModule.RaiseEventNow
End Sub
Private Sub UserModule_test(ByVal PIC As stdole.StdPicture)
Me.Picture = PIC
End Sub
' =-=-=-=-=-=-=-=-=-=-=-=
' ClsUserModule.cls (dll)
' =-=-=-=-=-=-=-=-=-=-=-=
'
Option Explicit
Dim obj As New StdPicture
Public Event test(ByVal PIC As StdPicture)
'
Public Sub RaiseEventNow()
Set obj = LoadPicture ("c:\tmp1.jpg")
RaiseEvent test(obj)
End Sub
'
Private Sub Class_Terminate()
Set obj = Nothing
End Sub
à noter que j'ai mis BYVAL parce que le client ne traite pas PIC (donc pas de modif....)
mais essayé en BYREF et modifié comme pour le test1, nikel aussi....
on passe donc à la biblio.
on ajoute un projet activex (dll) nommé XOMforNBCModules et tout le reste.... comme dans l'énoncé.
ce nouveau projet est référencé uniquement pour Pj_dll.
ahaa... premier point pour le Implements (auquel je suis peu habitué d'ailleurs), les fonctions sont private et non public comme dans ton exemple.
bref, changé manuellement.
blablabla, 20 minutes viennent de passer (je fais en direct), d'où sort IModuleServices_?
et tu implementes IModuleEvents dans clsModuleEvents ?
je reste avec VB ouvert de côté...
désolé de ce début de faux espoir
++
<hr size="2" width="100%" />Prenez un instant pour répondre à ce sondage svp
je suis pas encore au bureau, mais d'ors et déjà, je te remercie de participer. C'est vrai, la mise en oeuvre est un peu fastidieuse.
Une fois de plus, PCPT a raison, la fonction, une fois implémentée, est privée (erreur de non copier/coller, comme quoi!).
IModuleServices est une autre classe d'interface, qui me sert dans l'autre sens (client vers serveur) à demander un service, genre GetPicture (j'essayais d'ailleurs, au début, de lui passer un objet Picture par référence, pas mieux, et toujours exclusivement pour l'objet Picture).
Effectivement, c'est bien la classe publique clsModuleEvents qui implémente l'interface. C'est une préconisation Microsoft qui permet au client d'être "rappelé" par son serveur (l'exemple MSDN est une application qui fait le café, avec la classe Coffee et la classe NotifyMe, on notera que l'exemple fourni est à corriger pour devenir fonctionnel). Si j'implémentais, à l'intérieur du client, l'interface IModuleEvents, je ne pourrais pas partager la classe privée implémentant l'interface, tout simplement parce qu'elle ne serait pas déclarée dans l'interface (donc privée, vue du client).
PS: j'en ai enfin fini avec mes robots, me revoilà!
PS2: où puis-je avoir des nouvelles de ton projet relatif au sondage POP?
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
effectivement, quelques précisions sont nécessaires:
d'abord, tu dis "ajouter un projet", il est important que la bibliothèque d'interface utilise une autre instance de VB, sans quoi, tu es obligé de la compiler et la registrer. Le serveur et le client peuvent cohabiter dans le même groupe de projet.
Ensuite, à terme, le client et le serveur doivent référencer la bibliothèque d'interfaces (XOMforNBCModules). Le Client doit aussi, dans ton exemple, référencer pj_dll (dans mon projet, le client trouve son serveur par une interface, pas de liaison précoce avec lui).
A) Le code de la bibliothèque :
1/ Ajoutes la classe interface IModuleEvents :
Public Function SetPicture(ByVal PIC As StdPicture)
‘c’est tout, mais il faut laisser le commentaire
End Function
2/ Ajoutes la classe publique clsModuleEvents2 (c’est elle qui sera vue par le client, comme par le serveur) :
Option Explicit
Public Event test(ByVal PIC As StdPicture)Implements IModuleEvents<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>
Private Sub Class_Terminate()
Set obj = Nothing
End Sub
Private Function IModuleEvents_SetPicture(ByVal PIC As stdole.Picture) As Variant
RaiseEvent test(PIC)
End Function
B) Le code du serveur (pj_dll) :
1/ Ajoutes la classe clsMain :
Dim obj As New StdPicture
Private m_ModuleEvents2 As XOMforNBCModules. IModuleEvents
Public Property Get ModuleEvents2() As XOMforNBCModules.IModuleEvents
Set ModuleEvents2 = m_ModuleEvents2
End Property
Public Property Let ModuleEvents2(ByVal vNewValue As XOMforNBCModules.IModuleEvents)
Set m_ModuleEvents2 = vNewValue
End Property
Private Sub Class_Initialize()
Set m_ModuleEvents2 = New XOMforNBCModules.clsModuleEvents2
End Sub
Public Sub GetPicture()
‘est appelé par le signal
Set obj = LoadPicture("c:\tmp1.jpg")
‘emet la notification
m_ModuleEvents2.SetPicture obj
End Sub
C) Le code du client (pj_exemple) :
Option Explicit
‘pour référencer le serveur
Private UserModule As pj_dll.ClsMain
‘pour en recevoir les notifications
Private WithEvents ModuleEvents As XOMforNBCModules.clsModuleEvents2
Private Sub Form_Load()
Set UserModule = New pj_dll. ClsMain
‘récupère la référence du handler d’évènements
Set ModuleEvents = UserModule.ModuleEvents2
‘emet le signal
UserModule.GetPicture
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set UserModule = Nothing
End Sub
Private Sub ModuleEvents_test(ByVal PIC As stdole.StdPicture)
'… c’est ici que devrait arriver la notification
End Sub
Voilà, ça peut déjà aider.
à+
PS : 14 robots quand même!
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
PCPT
Messages postés13272Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201847 15 sept. 2006 à 20:15
re,
bon, je suis tes étapes pas à pas.
je ne vois pas pourquoi la biblio ne doit pas être dans la même instance mais j'abdique ;)
tout nouveau.... (même le dossier ^^)nouveau projet, nouvelle dll (projet XOMforNBCModules, classe IModuleEvents)
contient ta fonction en A)1/
j'ajoute la classe clsModuleEvents2 qui contient ton A)2/ (sauf que j'ai inversé le implements et le event)
je n'y touche plus (alors que obj n'est pas déclaré...). pas de compilation, je laisse le projet ouvert pour le moment.
nouveau projet, nouvelle dll (projet pj_dll, classe clsMain)
j'y colle ton B)1/
la biblio ne sera pas liée, pour le moment je ne touche à rien.
ps : heureusement que je regarde.. tu dois être sous opera, tes "'" sont remplacés par "?" donc
"?est appelé par le signal" devient "Print est; appelé; par; le; signal" ^^
à cette dll j'ajoute un projet exe (projet pj_exemple, form Frm_Main)
j'y copie ton code en C/ , passe l'exe en projet de démarrage, référencie pj_dll.
on teste comme çà. évidemment la biblio n'est pas reconnue de la dll.
je déclare évidemment un obj, le code est ci-dessous
'XOMforNBCModules.clsModuleEvents2 (cls)
Option Explicit
'
Dim obj As New StdPicture
Implements IModuleEvents
Public Event test(ByVal PIC As StdPicture)
Private Sub Class_Terminate()
Set obj = Nothing
End Sub
Private Function IModuleEvents_SetPicture(ByVal PIC As stdole.Picture) As Variant
RaiseEvent test(PIC)
End Function
rvblog
Messages postés792Date d'inscriptionvendredi 4 mars 2005StatutMembreDernière intervention12 juin 20127 15 sept. 2006 à 21:09
Navré de pas être très synchro, j'ai fini tard,
et pas très rigoureux, je faisais 2 choses en même temps!
Bon, l'instance différente pour la bibliothèque :
j'exécute cette biblio pour ne pas à avoir à la compiler à chaque fois, car pour la compiler, il ne faut pas de projet ouvert qui la référence (fastidieux). Quand je l'exécute (option Attendre la création de composant), VB publie l'interface et son GUID (en live). Il est donc important de démarrer la bibliothèque (il s'agit bien de l'exécuter) avant d'ouvrir les projets l'utilisant, et de ne faire que des modifications "point d'arrêt"!
J'ai mesuré mon manque de précisions pour que quelqu'un mette en oeuvre ce bout de projet, en voyant que le code que tu avais généré pour le faire. J'ai donc réutilisé un peu de ce que tu avais fait, et j'ai mal nettoyé. Effectivement, le destructeur de clsModuleEvents2 est un modèle d'efficacité (en plus la déclaration d'une gourmante Variant au dernier moment, si ça c'est pas du luxe!).
Les ? des commentaires viennent de Word! curieux comportement, je l'avoue (pas d'explication).
Pas besoin d'obj dans clsModuleEvents2, on est d'accord.
Mais là, tu m'épates encore, OS XP? moi c'est W2K ou NT4, et pas d'image!
!!
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
PCPT
Messages postés13272Date d'inscriptionlundi 13 décembre 2004StatutMembreDernière intervention 3 février 201847 15 sept. 2006 à 22:17
arf, beh je ne vais t'être d'aucun secours alors....
ce que je viens de faire :
je lance le groupe (donc dll + exe, pas biblio qui était déjà compilée)
je compile la dll, puis compile l'exe. fermeture sans sauver.
test exe : çà roule (çà serait malheureux ^^)
je suis sous XP Pro SP1
je fais une copie du dossier ("2" de son nom ) à la racine du C.
j'y ajoute un reg.bat contenant :
regsvr32.exe -c XOMforNBCModules.dll
regsvr32.exe -c pj_dll.dll
et un reg9x.bat contenant :
C:\WINDOWS\SYSTEM\regsvr32.exe -c XOMforNBCModules.dll
C:\WINDOWS\SYSTEM\regsvr32.exe -c pj_dll.dll
(et des unreg, pareil, ordre inverse avec -u)
je reboot sur W2K SP4
je lance le reg, puis l'exe, j'ai bien mon image
unreg.
je reboot sur W98 MAJ dernier cri ^^
pareil avec l'autre reg, test ok aussi!
nb : seule ma partition XP contient VB. les autres ont juste les runtimes.
désolé je n'ai pas NT mais le problème doit venir d'ailleurs .
j'ai détaillé pas à pas... je ne vois pas qu'est-ce qui peut clocher...
je reste dispo, quitte à m'envoyer le projet par mail s'il diffère....
++
<hr size="2" width="100%" />Prenez un instant pour répondre à ce sondage svp
rvblog
Messages postés792Date d'inscriptionvendredi 4 mars 2005StatutMembreDernière intervention12 juin 20127 15 sept. 2006 à 22:32
chuis furax,
VB6 Sp4! viendrait-ce du SP? je cherche une doc tout de suite!
à+
PS: t'ais-je déjà parlé du projet Forum Explorer? Orienté RSS multi-sites (CSSS, programmez, programmers-heaven...), templates de messages, références aux solutions existantes, extension de la banque d'image externalisée des répondeurs, ..., mais uniquement pour répondre sur VB France?
Non?
Faudra que je le fasse alors! Mais il faut que j'avance la spec (mise de côté pour m'occuper des robots, vivement mes récup).
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>
eh oui, =401740 PCPT a raison, le Service Pack a toute son importance!
Bien vu, de plus, il semble que l'instruction Implements est réellement besoin d'être avant les déclarations, et il paraît aussi nécessaire de recompiler un peu tout le monde sur des gros changements d'interfaces (je ne saurais pas quantifier à partir de quand le changement est "gros"), pour remettre à jour les informations publiées par VB (après l'upgrade SP6 de VB, tout ne marchait toujours pas, après la remise en ordre de l'implements, seul le serveur [modifié pour l'occasion] recevait des notifications, après recompilation du tout, c'est tombé en marche ! )
La morale : Quand on change de PC, pas de Ghost possible, mais pas d'économie de Service Pack à faire!
à+
rvblog<sup>n
Je veux ton bien....et je l'aurais....mais jamais avant la page 4 des derniers échanges</sup>