如何在python中为win32com模拟vb的控制数组?

发布于 2024-08-16 16:53:57 字数 1046 浏览 10 评论 0原文

我需要从 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 吗?

I need to dynamically create com objects from an activex dll and each of the objects can raise events which should be handled with event handlers.

I can do this easily with win32com.client.Dispatch and win32com.client.WithEvents and associate a "separate" class of event handlers with each of the objects. Like so:

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)

But if I dynamically create the objects, lets say in a list:

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

I want to code the event handlers only once, since I don't know how many objects I would be creating until run time. And I don't know how to get the object that raised the event from inside the event handler.

In VB 6, I've used the activex control using control arrays, and the event handlers simply get an "index" value of the control that raised the event.

Do you think something similar can be done in python ?
I am not sure what python decorators work for, but can they be used to "decorate" the MyEventHandlerClass for each index of the com object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

面犯桃花 2024-08-23 16:53:57

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 模块(参见 事件处理)如果您想以更明智的方式执行此操作。

It's a major flaw of win32com's event handling that you have to pass in a class object rather than a class instance.

You can attach state to your classes using win32com, however, by creating classes dynamically using 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

Output:

got event from object 0
got event from object 2

You might want to look into the comtypes module (see event handling) if you want to do this in a saner way.

后eg是否自 2024-08-23 16:53:57

控件数组在 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

Control Arrays were removed in VB.NET so I don't think they would be supported in the win32com.
Not sure if this would work for you but can you pass the index to the EventHandler class?

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))

If the event needs access to all of the controls in the array (not just the index), you can mimic a control array by looping through your listOfObjects in the EventHandler, and determining which object raised the Event... so for example, a RadioButton_CheckChanged() event would look like:

def RadioButton_CheckChanged():
    for radiobutton in listOfRadioButtons:
        if radiobutton.Checked:
            # this is the one that was clicked on
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文