كيف تحاكي صفيف التحكم في VB في بيثون لـ Win32Com؟
سؤال
أحتاج إلى إنشاء كائنات COM ديناميكيًا من DLL ActiveX ويمكن لكل من الكائنات رفع الأحداث التي يجب معالجتها مع معالجات الأحداث.
يمكنني القيام بذلك بسهولة win32com.client.Dispatch
و win32com.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 ، ولكن هل يمكن استخدامهم "لتزيين" MyEventHandlerClass لكل فهرس كائن COM؟
المحلول
إنه عيب كبير في معالجة الأحداث 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 الوحدة النمطية (انظر التعامل مع الحدث) إذا كنت ترغب في القيام بذلك بطريقة Saner.
نصائح أخرى
تمت إزالة صفائف التحكم في 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))
إذا احتاج الحدث إلى إمكانية الوصول إلى جميع عناصر التحكم في الصفيف (وليس فقط الفهرس) ، فيمكنك تقليد صفيف تحكم عن طريق الحلق من خلال listofobjects في eventHandler ، وتحديد الكائن الذي رفع الحدث ... لذلك على سبيل المثال ، أ سيبدو حدث RadiObutton_CheckChanged ():
def RadioButton_CheckChanged():
for radiobutton in listOfRadioButtons:
if radiobutton.Checked:
# this is the one that was clicked on