You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过文件名直接用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 16:54:15