如何通过文件名直接用Python调用flash.ocx组件?
实现直接指定flash.ocx文件路径的播放器方案
QAxWidget(PyQt5)及多数基于COM的UI组件依赖系统对OCX的注册,无法直接通过文件路径传入setControl。要实现指定本地flash.ocx文件,可通过动态注册组件或手动加载OCX绕开系统注册两种方式实现,以下是具体方案:
方案一:PyQt5 动态注册+调用
flash.ocx的CLSID是固定值{D27CDB6E-AE6D-11cf-96B8-444553540000},只需先动态注册本地OCX文件,即可通过该CLSID调用对应组件。
代码实现
from PyQt5 import QtCore, QtGui, QAxContainer, QtWidgets import subprocess import os def register_ocx(ocx_path): if not os.path.exists(ocx_path): raise FileNotFoundError(f"OCX文件不存在:{ocx_path}") # 调用regsvr32静默注册OCX,需管理员权限运行程序 try: subprocess.run( ["regsvr32", "/s", ocx_path], check=True, shell=True ) except subprocess.CalledProcessError: print("OCX注册失败,请确保程序以管理员权限运行") class Ui_Flash(QAxContainer.QAxWidget): def __init__(self, ocx_path, swf_path, parent=None): super(Ui_Flash, self).__init__(parent) register_ocx(ocx_path) self.resize(800, 600) # 使用flash.ocx的固定CLSID self.setControl("{D27CDB6E-AE6D-11cf-96B8-444553540000}") self.dynamicCall("LoadMovie(long,string)", 0, swf_path) self.show() if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) # 替换为本地flash.ocx和SWF文件的实际路径 ui = Ui_Flash(r"D:\path\to\flash.ocx", r"test.swf") ui.show() sys.exit(app.exec_())
方案二:Tkinter + ctypes 手动加载OCX(无需系统注册)
通过ctypes直接加载flash.ocx文件,手动创建COM对象并嵌入Tkinter窗口,绕开系统注册步骤。该方式需处理较多COM接口细节,适合需避免修改系统注册表的场景。
代码实现
import tkinter as tk from ctypes import windll, POINTER, HRESULT, c_void_p, byref from ctypes.wintypes import HWND # 初始化COM库 ole32 = windll.ole32 ole32.CoInitialize(None) # flash.ocx的固定CLSID和接口ID CLSID_ShockwaveFlash = c_void_p(0xD27CDB6E, 0xAE6D, 0x11CF, 0x96, 0xB8, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00) IID_IOleObject = c_void_p(0x00000112, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46) class FlashPlayer(tk.Frame): def __init__(self, parent, ocx_path, swf_path): super().__init__(parent) self.parent = parent self.swf_path = swf_path # 加载本地flash.ocx try: self.flash_lib = windll.LoadLibrary(ocx_path) except OSError: raise Exception(f"无法加载OCX文件:{ocx_path}") # 获取COM类工厂并创建对象 self.pClassFactory = POINTER(c_void_p)() dll_get_class_obj = self.flash_lib.DllGetClassObject dll_get_class_obj.argtypes = [POINTER(c_void_p), POINTER(c_void_p), POINTER(c_void_p)] dll_get_class_obj.restype = HRESULT hr = dll_get_class_obj(byref(CLSID_ShockwaveFlash), byref(IID_IOleObject), byref(self.pClassFactory)) if hr != 0: raise Exception(f"创建COM对象失败,错误码:{hr}") # 将OCX嵌入Tkinter窗口(需完善COM接口调用以实现SWF加载,此处为框架示例) self.hwnd = HWND(self.winfo_id()) # 需进一步实现IOleObject的SetClientSite、DoVerb等接口完成嵌入 # 完整功能可结合win32com.client动态调用COM方法加载SWF self.pack(fill=tk.BOTH, expand=True) if __name__ == "__main__": root = tk.Tk() root.title("Flash Player") root.geometry("800x600") # 替换为本地flash.ocx和SWF文件的实际路径 player = FlashPlayer(root, r"D:\path\to\flash.ocx", r"test.swf") root.mainloop() # 释放COM资源 ole32.CoUninitialize()
关键注意事项
- flash.ocx仅支持32位Python环境,64位环境无法加载。
- 方案一需管理员权限运行程序,方案二需自行处理COM接口的细节调用。
- 确保本地flash.ocx版本与系统环境兼容。
内容的提问来源于stack exchange,提问作者Guf
相关产品推荐
相关产品推荐

