如何在 pyqt 中捕獲並處理 Alt+F4 快捷鍵

之一Yo發表於2022-05-29

前言

如果在 Windows 系統的任意一個視窗中按下 Alt+F4,預設行為是關閉視窗(或者最小化到托盤)。對於使用了亞克力效果的視窗,使用 Alt+F4 最小化到托盤,再次彈出視窗的時候可能出現亞克力背景和視窗陰影失效的問題,如下圖所示:

亞克力背景失效

所以本篇部落格將會介紹在 PyQt 中捕獲並處理 Alt+F4 的方法,亞克力無邊框視窗的實現方法參見 《如何在 pyqt 中自定義無邊框視窗》,下面進入正題。

實現過程

對於快捷鍵處理,第一反應是重寫 keyPressEvent() ,但是對於 Alt+F4 這種系統級別的快捷鍵此非法是無法捕獲的,重寫 nativeEvent 才是正解。按下 Alt+F4 之後,視窗就能收到 WM_SYSKEYDOWN 訊息,同時訊息的 wParam 等於 VK_F,這時候手動可以給視窗傳送一個 QCloseEvent,然後在關閉事件中進行處理。

class Window(QWidget):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.__closeByKey = False

    def nativeEvent(self, eventType, message):
        """ Handle the Windows message """
        msg = MSG.from_address(message.__int__())
        if msg.message == win32con.WM_SYSKEYDOWN:
            if msg.wParam == win32con.VK_F4:
                self.__closeByKey = True
                QApplication.sendEvent(self, QCloseEvent())
                return False, 0

        return super().nativeEvent(eventType, message)

    def closeEvent(self, e):
        quitOnClose = QApplication.quitOnLastWindowClosed()
        if not self.__closeByKey or quitOnClose:
            self.__closeByKey = False
            return super().closeEvent(e)

        # 最小化到托盤
        self.__closeByKey = False
        self.hide()

再次測試,發現原本黑色背景的問題已經被成功解決了(軟體的實現程式碼參見 Groove):

解決問題

相關文章