user32.SetWindowCompositionAttribute 与 PyQt5 导致 ctypes.ArgumentError

问题描述 投票:0回答:1

最近我通过

安装了一个名为 BlurWindow 的 python 包
pip install BlurWindow

这个Python包有助于实现应用程序窗口的透明模糊背景。虽然它说这个模块适用于 tkinter、qt 和许多其他软件包,但就我而言,它仅适用于 tkinter 和 PySide2,但不适用于 PyQt5。

我的代码如下:

import sys

from PySide2.QtWidgets import *
from PySide2.QtCore import *

# from PyQt5.QtWidgets import *
# from PyQt5.QtCore import *

from BlurWindow.blurWindow import GlobalBlur


class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setAttribute(Qt.WA_TranslucentBackground)
        # self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint | Qt.WindowMinMaxButtonsHint)   # set window flags
        self.resize(500, 400)

        l = QLabel('How do you like the blurry window?', self)

        GlobalBlur(self.winId(), Dark=False, Acrylic=False, QWidget=self)

        self.setStyleSheet("color: white; background-color: rgba(0, 0, 0, 0)")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())

这段代码运行良好。但是当我评论这两行(第 3 行和第 4 行)时:

from PySide2.QtWidgets import *
from PySide2.QtCore import *

并取消注释这两行(第 6 行和第 7 行):

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

出现此错误:

Traceback (most recent call last):
  File "E:\PythonProjects\Zambo\lib\runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "E:\PythonProjects\Zambo\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "E:\PythonProjects\Zambo\lib\site-packages\BlurWindow\blurWindow.py", line 191, in <module>
    mw = MainWindow()
  File "E:\PythonProjects\Zambo\lib\site-packages\BlurWindow\blurWindow.py", line 185, in __init__
    GlobalBlur(hWnd,Dark=True,QWidget=self)
  File "E:\PythonProjects\Zambo\lib\site-packages\BlurWindow\blurWindow.py", line 160, in GlobalBlur
    blur(HWND,hexColor,Acrylic,Dark)
  File "E:\PythonProjects\Zambo\lib\site-packages\BlurWindow\blurWindow.py", line 136, in blur
    user32.SetWindowCompositionAttribute(HWND, data)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1

我不知道为什么这段代码适用于 PySide2 但不适用于 PyQt5!

这是我在所示代码中使用的 blurWindow.py 模块。

我使用的是 Windows 10,并在 anaconda 虚拟环境中使用 Python 3.9.5。但我已经在 Python 3.6 和 3.8 上测试了这段代码,但 PyQt5 库在任何地方都不起作用,而是显示相同的错误。

我即将完成我的项目,我将在其中实现这种模糊效果。而且由于我在项目中使用了 PyQt5 库,因此用 PySide2 替换 PyQt5 库对我来说将是一个很大的麻烦。任何帮助将不胜感激!

python python-3.x pyqt5 ctypes pyside2
1个回答
1
投票

一开始,我认为这可能与 [SO]: ctypes.ArgumentError when using kivy with pywinauto 是一样的,但事实证明它更简单。

这是BlurWindow中的一个错误。运行 blurWindow.py 会产生相同的行为(使用 PyQt5.12.3)。

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q068651351]> sopr.bat
### Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ###

[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.08.07_test0\Scripts\python.exe" BlurWindow\blurWindow.py
Traceback (most recent call last):
  File "BlurWindow\blurWindow.py", line 188, in <module>
    mw = MainWindow()
  File "BlurWindow\blurWindow.py", line 182, in __init__
    GlobalBlur(hWnd,Dark=True,QWidget=self)
  File "BlurWindow\blurWindow.py", line 157, in GlobalBlur
    blur(HWND,hexColor,Acrylic,Dark)
  File "BlurWindow\blurWindow.py", line 133, in blur
    user32.SetWindowCompositionAttribute(HWND, data)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1
[prompt]> :: Test the 2 modules
[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.08.07_test0\Scripts\python.exe" -c "import PyQt5.QtWidgets as pqqw; help(pqqw.QWidget.winId)"
Help on built-in function winId:

winId(...)
    winId(self) -> sip.voidptr


[prompt]> "e:\Work\Dev\VEnvs\py_pc064_03.08.07_test0\Scripts\python.exe" -c "import PySide2.QtWidgets as psqw; help(psqw.QWidget.winId)"
Help on method_descriptor:

winId(self) -> int
    winId(self) -> int

如图所示,两个模块QtWidgets.QWidget.winId的返回值之间存在“小”差异。 CTypes 不知道转换 PyQt5's。

短篇故事

由于您在此处复制了 MainWindow 代码,因此修复很简单,替换:

GlobalBlur(self.winId(), Dark=False, Acrylic=False, QWidget=self)

作者:

GlobalBlur(int(self.winId()), Dark=False, Acrylic=False, QWidget=self)

它应该可以正常工作。但请检查下一节开头的 URL,看看您可能会遇到什么情况。

说来话长

这更多是关于 BlurWindow 的。错误发生在通过 CTypes 调用 (!!!未记录!!!) user32.SetWindowCompositionAttribute 时。
这里重要的一点是:[SO]:通过 ctypes 从 Python 调用的 C 函数返回不正确的值(@CristiFati 的答案)。请注意,它是 Undefined Behavior,并且只能靠运气才能起作用。

已提交 [GitHub]:Peticali/PythonBlurBehind - 修复 SetWindowCompositionAttribute 失败合并于 210805)。它包含对当前问题的正确修复。

检查[SO]:如何使用 python 和 win32print 更改打印队列中作业的用户名(@CristiFati 的答案)(最后)以了解进一步的可能方法。
您可以下载补丁并在本地应用更改。检查 [SO]:在 PyCharm 社区版中通过鼠标右键单击上下文菜单运行/调试 Django 应用程序的 UnitTests? (@CristiFati 的回答)修补 utrunner 部分)了解如何在 Win 上应用补丁(基本上,以 一个“+” 符号开头的每一行都进入,以 one 开头的每一行“-” 符号熄灭)。我正在使用 Cygwinbtw
但由于它只是一个文件,您可以下载它并覆盖现有的文件。
无论如何,请先备份

© www.soinside.com 2019 - 2024. All rights reserved.