【问题标题】:How to mimic vb's control array in python for win32com?如何在 python 中为 win32com 模拟 vb 的控制数组?
【发布时间】:2010-01-04 08:22:23
【问题描述】:

我需要从 activex dll 动态创建 com 对象,并且每个对象都可以引发应该由事件处理程序处理的事件。

我可以使用win32com.client.Dispatchwin32com.client.WithEvents 轻松做到这一点,并将“单独的”事件处理程序类与每个对象相关联。像这样:

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)

但如果我动态创建对象,让我们在列表中说:

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

我只想编写一次事件处理程序,因为直到运行时我才知道要创建多少个对象。而且我不知道如何从事件处理程序内部获取引发事件的对象。

在 VB 6 中,我通过 控件数组 使用了 activex 控件,事件处理程序只需获取引发事件的控件的“索引”值。

你认为在 python 中可以做类似的事情吗?
我不确定 python 装饰器的作用是什么,但它们可以用来为 com 对象的每个索引“装饰” MyEventHandlerClass 吗?

【问题讨论】:

    标签: python win32com


    【解决方案1】:

    win32com 事件处理的一个主要缺陷是你必须传入一个类对象而不是类实例。

    您可以使用 win32com 将状态附加到您的类,但是,通过使用 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
    

    输出:

    got event from object 0
    got event from object 2
    

    如果您想以更明智的方式执行此操作,您可能需要查看comtypes 模块(请参阅event handling)。

    【讨论】:

    • 是的!这行得通.. 谢谢 Ryan 我也会研究 comtypes 模块.. 看起来与 win32com 有点不同..
    【解决方案2】:

    在 VB.NET 中删除了控制数组,所以我认为 win32com 不会支持它们。 不确定这是否适合您,但您可以将索引传递给 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))
    

    如果事件需要访问数组中的所有控件(不仅仅是索引),您可以通过循环遍历 EventHandler 中的 listOfObjects 来模拟控件数组,并确定哪个对象引发了事件......所以例如,RadioButton_CheckChanged() 事件如下所示:

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

    【讨论】:

    • win32com 事件的最大缺陷是你需要传入一个可调用对象,而不是一个实例。但是,您可以传入一个包装好的“工厂”函数,该函数将返回一个具有必要状态的类实例。
    • @coonj:不幸的是...... WithEvents() 函数需要类实例的名称,而不是对象引用,因此它不起作用。但是我认为如果我们可以传入一个在obj_index 变量中具有索引值的新类,你的想法应该可行。那可能吗?我记得在某处读到类也是python中的对象,所以我认为它们可以被创建,但我不确定语法是什么......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-04
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 2020-04-02
    • 2013-09-13
    相关资源
    最近更新 更多