injoker1
injoker1

Reputation: 183

Is there any way to make mouse events completely ignore windows in PyQt5?

I have tried to use setAttribute(Qt.Qt.WA_TransparentForMouseEvents),but mouse also can't pierce through Qtwindow.

I want make mouse event penetrate Qtwindow,like I have clicked mouse's right button at a Qtwindow which is located in Windows10 Desktop,then it will trigger win10 contextmenu.

Upvotes: 2

Views: 1622

Answers (2)

class main(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.Popup|Qt.WindowDoesNotAcceptFocus|Qt.WindowTransparentForInput)
        self.setAttribute(Qt.WA_AlwaysStackOnTop, True)

Upvotes: 1

Christian Karcher
Christian Karcher

Reputation: 3641

Would a transparent window suit your needs?

from PyQt5 import QtCore, QtWidgets, QtGui


class Overlay(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        self.setAttribute(QtCore.Qt.WA_TransparentForMouseEvents)
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground, True)
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        layout = QtWidgets.QHBoxLayout(self)
        label = QtWidgets.QLabel('Transparent and propagating')
        label.setFont(QtGui.QFont('Arial', 26))
        label.setStyleSheet("background-color : white")
        layout.addWidget(label)
        self.show()


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    form = Overlay()
    app.exec_()

I tried to figure out a way to directly transmit clicks to the desktop. The closest related question gave me some ideas, but ultimately I was not able to get it working, the clicks never reach the desktop. Maybe you can still get some ideas from this:

from PyQt5 import QtWidgets, QtGui
import win32api, win32con
from ctypes import windll


class Overlay(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        layout = QtWidgets.QHBoxLayout(self)
        label = QtWidgets.QLabel('Click to Desktop')
        label.setFont(QtGui.QFont('Arial', 26))
        label.setStyleSheet("background-color : white")
        layout.addWidget(label)
        # make window partially transparent to see where you are clicking
        self.setWindowOpacity(0.5)
        # get handle to desktop as described in linked question
        hProgman = windll.User32.FindWindowW("Progman", 0)
        hFolder = windll.User32.FindWindowExW(hProgman, 0, "SHELLDLL_DefView", 0)
        self.desktop = windll.User32.FindWindowExW(hFolder, 0, "SysListView32", 0)
        self.show()

    def mousePressEvent(self, event):
        # catch mouse event to route it to desktop
        x = event.globalPos().x()
        y = event.globalPos().y()
        lParam = win32api.MAKELONG(x, y)
        # left click on desktop (left button down + up, => should be replaced by event.button() pseudo switch case once working)
        windll.User32.SendInput(self.desktop, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, lParam)
        windll.User32.SendInput(self.desktop, win32con.WM_LBUTTONUP, 0, lParam)
        # display position for debugging (position gets displayed, but nothing gets clicked)
        print(f'clicked on desktop at position {x} and {y}')


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    form = Overlay()
    app.exec_()

Upvotes: 5

Related Questions