2010-01-04 4 views
1

Je dois créer dynamiquement des objets com à partir d'une dll activex et chacun des objets peut déclencher des événements qui devraient être traités avec des gestionnaires d'événements.Comment imiter le tableau de contrôle de vb en python pour win32com?

Je peux le faire facilement avec win32com.client.Dispatch et win32com.client.WithEvents et associer une classe «séparée» de gestionnaires d'événements à chacun des objets. Comme si:

class evt_1: 
    def OnEvent(self): 
     print "got event from object 1" 

class evt_2: 
    def OnEvent(self): 
     print "got event from object 2" 

obj_1 = win32com.client.Dispatch("mycom") 
ev_1 = win32com.client.WithEvents(obj_1, evt_1) 

obj_2 = win32com.client.Dispatch("mycom") 
ev_1 = win32com.client.WithEvents(obj_2, evt_2) 

Mais si je crée dynamiquement les objets, permet de dire que dans une liste:

listOfObjects = [] 
for i in range(10): 
    obj = win32com.client.Dispatch("mycom") 
    listOfObjects.append(obj) 
    ev = win32com.client.WithEvents(obj, MyEventHandlerClass) 

Je veux coder les gestionnaires d'événements qu'une seule fois, puisque je ne sais pas combien d'objets Je créerais jusqu'à l'exécution. Et je ne sais pas comment obtenir l'objet qui a déclenché l'événement depuis le gestionnaire d'événements.

Dans VB 6, j'ai utilisé le contrôle activex en utilisant les tableaux de contrôle , et les gestionnaires d'événements ont simplement une valeur "index" du contrôle qui a déclenché l'événement.

Pensez-vous que quelque chose de similaire peut être fait en python?
Je ne sais pas à quoi servent les décorateurs python, mais peuvent-ils être utilisés pour "décorer" MyEventHandlerClass pour chaque index de l'objet com?

Répondre

0

Il est un défaut majeur de l'événement de win32com manipulation que vous devez passer un objet de classe plutôt que d'une instance de classe.

Vous pouvez joindre l'état à vos classes en utilisant win32com, cependant, en créant des classes dynamiquement à l'aide new.classobj:

from win32com.client import Dispatch, WithEvents 
from new import classobj 

class MyEventHandler(object): 
    def OnVisible(self, visible): 
     print "got event from object %d" % self.obj_index 

listOfObjects = [] 
for i in range(3): 
    handler = classobj('Handler_%s' % i,(MyEventHandler,),{}) 
    handler.obj_index = i 
    ie = Dispatch("InternetExplorer.Application") 
    listOfObjects.append(ie) 
    WithEvents(ie, handler) 

listOfObjects[0].Visible = 1 
listOfObjects[2].Visible = 1 

Sortie:

got event from object 0 
got event from object 2 

Vous pouvez regarder dans le module comtypes (voir event handling) si vous voulez faire cela d'une manière plus saine.

+0

Oui! cela fonctionne .. merci Ryan Je vais aussi regarder dans le module comtypes .. ressemble un peu différent de win32com .. – sarshad

0

Les tableaux de contrôle ont été supprimés dans VB.NET, donc je ne pense pas qu'ils seraient pris en charge dans le win32com. Vous ne savez pas si cela fonctionnerait pour vous mais pouvez-vous passer l'index à la classe EventHandler?

class MyEventHandler: 
    def __init__(self, index): 
     self.obj_index = index 

    def OnEvent(self): 
     print "got event from object %d" % self.obj_index 

listOfObjects = [] 
for i in range(10): 
    obj = win32com.client.Dispatch("mycom") 
    listOfObjects.append(obj) 
    ev = win32com.client.WithEvents(obj, MyEventHandlerClass(i)) 

Si l'événement doit avoir accès à tous les contrôles dans le tableau (et pas seulement l'index), vous pouvez simuler un tableau de contrôle en boucle à travers vos listOfObjects dans le gestionnaire d'événements, et déterminer quel objet a déclenché l'événement. .. Ainsi, par exemple, un événement RadioButton_CheckChanged() ressemblerait à ceci:

def RadioButton_CheckChanged(): 
    for radiobutton in listOfRadioButtons: 
     if radiobutton.Checked: 
      # this is the one that was clicked on 
+0

La grande faille de win32com pour les événements est que vous devez passer dans un appelable, et non une instance. Cependant, vous pouvez passer une fonction "factory" enveloppée qui retournera une instance de classe avec l'état nécessaire. –

+0

@coonj: Malheureusement .. La fonction WithEvents() nécessite le nom d'une instance de classe, pas une référence d'objet, donc cela n'a pas fonctionné. Mais je pense que votre idée devrait fonctionner si nous pouvons transmettre une nouvelle classe ayant une valeur d'index dans une variable 'obj_index'. Est-ce possible? Je me souviens avoir lu quelque part que les classes sont des objets en python aussi, donc je pense qu'ils pourraient être créés mais je ne suis pas sûr de ce que serait la syntaxe .. – sarshad

Questions connexes