wxPython与Windows 7任务栏

1 投票
1 回答
1135 浏览
提问于 2025-04-17 03:33

为了简洁起见:我正在尝试用 wxPython 实现 这个功能,但是我在把那段代码放到 wxPython 的脚本里时遇到了困难。

我的简单 PyQt 测试代码运行得很好。代码如下:

from PyQt4 import QtGui
from threading import Thread
import time
import sys
import comtypes.client as cc
import comtypes.gen.TaskbarLib as tbl

TBPF_NOPROGRESS = 0
TBPF_INDETERMINATE = 0x1
TBPF_NORMAL = 0x2
TBPF_ERROR = 0x4
TBPF_PAUSED = 0x8

cc.GetModule("taskbar.tlb")
taskbar = cc.CreateObject("{56FDF344-FD6D-11d0-958A-006097C9A090}", interface=tbl.ITaskbarList3)

class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        self.setWindowTitle("Test")

        self.progress_bar = QtGui.QProgressBar(self)
        self.setCentralWidget(self.progress_bar)
        self.progress_bar.setRange(0, 100)

        self.progress = 0

        self.show()

        thread = Thread(target=self.counter)
        thread.setDaemon(True)
        thread.start()

    def counter(self):
        while True:
            self.progress += 1
            if self.progress > 100:
                self.progress = 0

            time.sleep(.2)

            self.progress_bar.setValue(self.progress)

            taskbar.HrInit()
            hWnd = self.winId()
            taskbar.SetProgressState(hWnd, TBPF_ERROR)        
            taskbar.SetProgressValue(hWnd, self.progress, 100)

app = QtGui.QApplication(sys.argv)
ui = MainWindow()
sys.exit(app.exec_())

但是,当我尝试执行 wxPython 的对应代码时,任务栏的功能没有按预期工作。以下是 wxPython 的代码:

import wx
import time
import comtypes.client as cc
import comtypes.gen.TaskbarLib as tbl
from threading import Thread

TBPF_NOPROGRESS = 0
TBPF_INDETERMINATE = 0x1
TBPF_NORMAL = 0x2
TBPF_ERROR = 0x4
TBPF_PAUSED = 0x8

cc.GetModule("taskbar.tlb")
taskbar = cc.CreateObject("{56FDF344-FD6D-11d0-958A-006097C9A090}", interface=tbl.ITaskbarList3)

class MainWindow(wx.Frame):
    def __init__(self, parent, ID, title):
        wx.Frame.__init__(self, parent, ID, title)

        self.panel = wx.Panel(self)
        self.gauge = wx.Gauge(self.panel)
        self.gauge.SetValue(0)

        self.progress = 0

        self.Show()

        thread = Thread(target=self.counter)
        thread.setDaemon(True)
        thread.start()

    def counter(self):
        while True:
            self.progress += 1
            if self.progress > 100:
                self.progress = 0

            time.sleep(.2)

            self.gauge.SetValue(self.progress)

            taskbar.HrInit()
            hWnd = self.GetHandle()

            taskbar.SetProgressState(hWnd, TBPF_ERROR)
            taskbar.SetProgressValue(hWnd, self.progress, 100)

app = wx.PySimpleApp()
frame = MainWindow(None, wx.ID_ANY, "Test")
app.SetTopWindow(frame)
app.MainLoop()

我觉得问题主要出在 wxWindow 的窗口句柄(hWnd)方法上,它和 Qt 的对应方法不一样,前者返回一个整数,而后者返回一个“sip.voidptr 对象”。

问题是我已经用 wxPython 写了整整 1200 多行代码,所以我不能重新写成 Qt 的代码(更不用说它们的许可证不同了)。

你觉得我该怎么办?我应该放弃吗?
非常感谢你的帮助 :)

编辑

多亏了 Robert O'Connor,现在它可以工作了。不过,我还是不明白为什么 GetHandle 返回一个整数,而 winId 返回一个对象。在 .idl 文件中,参数 hwnd 在所有函数定义中都声明为 long。也许这也是个简单的问题 ;) 有什么想法吗?

1 个回答

1

在下面这一行:

hWnd = self.panel.GetId()

你应该用 GetHandle() 代替 GetId()

补充说明:这最开始是作为评论发的,但我觉得把它重新发成回答更合适。

关于你问题的补充:如果现在可以正常工作了,那就说明没有问题了 ;) 好吧,认真说一下……

在Python中,整型(Ints)和长整型(Longs)是统一的。如果我猜得没错,comtypes可能在后台做了一些类型转换。我不确定在处理comtypes时是否需要担心这些细节,但在这个情况下似乎并不重要。

我对PyQT没有经验,但在Python中,你可以在对象上定义一些特殊的方法,比如 __int____long__,用来模拟整型和长整型。如果我猜得没错,你在PyQT中得到的对象定义了其中一个方法。

撰写回答