Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

WA_TranslucentBackground Frameless windows problem with WIN32 API SetParent



  • Hello,
    Here is video: https://streamable.com/0a6q8r
    When I use my custom Frameless and rounded form (I must use Qt.WA_TranslucentBackground for rounded form), WIN32API SetParent doesn't work.
    But when normal window (no custom form or custom form WITHOUT WA_TranslucentBackground), SetParent API works fine.
    I'm waiting for your help, Thanks!

    Here is my code:

    import sys,os, subprocess, psutil, time
    import win32gui
    from win32con import *
    from PySide6 import QtCore, QtWidgets
    from PySide6.QtWidgets import *
    from PySide6.QtCore import *
    from PySide6.QtGui import *
    
    
    BORDERLESS_CUSTOM_FORM = True
    class MACTema(QDialog):
        def __init__(self, w, parent=None):
            QDialog.__init__(self, parent)
    
            self.parent = parent
            self._w = w
            self.setupUi()
            contentLayout = QHBoxLayout()
            contentLayout.setContentsMargins(0, 3, 0, 3)
            contentLayout.addWidget(w)
    
            self.windowContent.setLayout(contentLayout)
            self.setWindowTitle(w.windowTitle())
            self.setGeometry(w.geometry())
    
            self._w.setAttribute(Qt.WA_DeleteOnClose, True)
            self._w.destroyed.connect(self.__child_was_closed)
    
        def setupUi(self):
            self.vboxWindow = QtWidgets.QVBoxLayout(self)
            self.vboxWindow.setContentsMargins(0, 0, 0, 0)
    
            self.windowFrame = QWidget(self)
            self.windowFrame.setObjectName('windowFrame')
    
            self.vboxFrame = QtWidgets.QVBoxLayout(self.windowFrame)
            self.vboxFrame.setContentsMargins(0, 0, 0, 0)
    
            self.titleBar = QWidget()
            self.titleBar.setContentsMargins(0, 0, 0, 0)
            self.titleBar.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed))
    
            self.hboxTitle = QHBoxLayout(self.titleBar)
            self.hboxTitle.setContentsMargins(0, 0, 4, 0)
            self.hboxTitle.setSpacing(0)
    
            self.lblIcon = QLabel()
            if not self._w.windowIcon().isNull():
                self.lblIcon.setPixmap(self._w.windowIcon().pixmap(QSize(64, 64)))
            self.lblIcon.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            self.lblIcon.setFixedSize(QSize(64 + 16, 32 + 2))
            self.lblIcon.setContentsMargins(5, 5, 0, 0)
    
            self.lblTitle = QLabel('Title')
            self.lblTitle.setObjectName('lblTitle')
            self.lblTitle.setAlignment(Qt.AlignBottom | Qt.AlignHCenter)
            self.lblTitle.setAttribute(Qt.WA_TransparentForMouseEvents, True)
            spButtons = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
    
            self.btnMaximize = QPushButton()  # clicked pyqtSlot => on_btnMaximize_clicked
            self.btnMaximize.setObjectName('btnMaximize')
            self.btnMaximize.setSizePolicy(spButtons)
    
            self.btnClose = QPushButton()  # clicked pyqtSlot => on_btnClose_clicked
            self.btnClose.setObjectName("btnClose")
            self.btnClose.setContentsMargins(0, 0, 0, 0)
            self.btnClose.setSizePolicy(spButtons)
    
            self.btnMinimize = QPushButton()  # click => on_btnMinimize_clicked
            self.btnMinimize.setObjectName("btnMinimize")
            self.btnMinimize.setSizePolicy(spButtons)
            self.vboxFrame.addWidget(self.titleBar)
            self.windowContent = QWidget(self.windowFrame)
            self.vboxFrame.addWidget(self.windowContent)
            self.vboxWindow.addWidget(self.windowFrame)
            self.hboxTitle.addWidget(self.lblIcon)
            self.hboxTitle.addWidget(self.lblTitle)
            self.hboxTitle.addWidget(self.btnMinimize)
            self.hboxTitle.addWidget(self.btnMaximize)
    
            self.hboxTitle.addWidget(self.btnClose)
            self.CONTROLBOX_WIDTH = self.btnClose.width()
            self.setWindowFlags(Qt.WindowType.Window | Qt.FramelessWindowHint | Qt.WindowMinimizeButtonHint)
    
    
    
    
    
    
    
    
            if True: # Problem here
                self.setAttribute(Qt.WA_TranslucentBackground)
    
    
    
    
    
            COLOR_ACIK_MINIMIZE, COLOR_KAPALI_MINIMIZE = "rgb(0, 120, 0)", "rgb(0,200,0)"
            COLOR_ACIK_CLOSE, COLOR_KAPALI_CLOSE = "rgb(255, 0, 0)", "rgb(255, 50, 50)"
            COLOR_MINIMIZE = COLOR_ACIK_MINIMIZE
            COLOR_CLOSE = COLOR_ACIK_CLOSE
    
    
            CONTROL_BOX_MAC = f"""
            #windowFrame {{      
              border-top-left-radius:10px;border-top-right-radius:10px;
              border-bottom-left-radius:5px;border-bottom-right-radius:5px;  
              background-color: palette(Window);}}        
    #btnClose, #btnMaximize, #btnMinimize {{ 
        margin: 4px;  
    	border: none;
    	border-radius: 8px;	
    	width:17px;
    	height:17px;
    	max-height:17px; 
    	max-width:17px;
    
    
    }}
    #btnMaximize {{
      	border: none;
    	border-radius: 8px;	
    	background-color: rgb(255, 170, 0);
    }}
    #btnMaximize::hover {{
      	background-color: rgba(255, 170, 0, 175);
    }}
    #btnMinimize {{
     	border: none;
    	border-radius: 8px;		
    
    	background-color: {COLOR_MINIMIZE};
    }}
    #btnMinimize::hover {{
        background-color: rgba(0, 120, 0, 175);
    
    }}
    #btnClose {{
    	border: none;
    	border-radius: 8px;		
    	background-color: {COLOR_CLOSE};
    }}
    #btnClose::hover {{
      background-color: rgba(255, 0, 0, 175);
    }}
    #btnClose::disabled, #btnMaximize::disabled, #btnMinimize::disabled {{
      background-color: palette(midlight);
    }}
    """
            self.setStyleSheet(CONTROL_BOX_MAC)
    
    
            QtCore.QMetaObject.connectSlotsByName(self)
            self.effect = QtWidgets.QGraphicsDropShadowEffect()
            self.effect.setBlurRadius(10)
            self.effect.setXOffset(0)
            self.effect.setYOffset(0)
            self.effect.setColor(QColor(0, 0, 0, 150))
            self.windowFrame.setGraphicsEffect(self.effect)
            self.setContentsMargins(8, 8, 8,8)
    
        @Slot()
        def on_btnClose_clicked(self):
            self.close()
    
        def __child_was_closed(self):
            self._w = None  # The child was deleted, remove the reference to it and close the parent window
            self.close()
    
        def setWindowTitle(self, title):
            super(MACTema, self).setWindowTitle(title)
            self.lblTitle.setText(title)
    
    
    
    class MyForm(QMainWindow):
        def __init__(self):
            super(MyForm, self).__init__()
            self.setupUi()
            if BORDERLESS_CUSTOM_FORM:
                self.mac = MACTema(w=self)
                self.mac.setGeometry(QRect(350,200,1280,720))
                self.mac.show()
            else:
                self.setGeometry(QRect(350, 200, 1280, 720))
                self.show()
            QApplication.processEvents()
            self.CalcSetParentFunction()
    
    
        def setupUi(self):
            widCenter = QWidget()
            qv= QVBoxLayout(widCenter)
            self.frame = QFrame()
            qv.addWidget(self.frame)
            self.setCentralWidget(widCenter)
    
        def CalcSetParentFunction(self):
            psutil.Popen("notepad.exe", stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, shell=True) # starts notepad
            time.sleep(2)
            self.hwnd = win32gui.FindWindow(None, "Untitled - Notepad") # Untitled - Notepad
            print("Notepad Hwnd: 0x%X"% self.hwnd)
            if not self.hwnd:
                return
            lStyle = win32gui.GetWindowLong(self.hwnd, GWL_STYLE);
            lStyle &= ~(WS_POPUP | WS_CHILD)
            #lStyle |= WS_CHILD
            win32gui.SetWindowLong(self.hwnd, GWL_STYLE, lStyle);
    
    
            win32gui.SetParent(self.hwnd, self.frame.winId())
            self.tmr = QTimer(self)
            self.tmr.timeout.connect(self.UpdateGUI)
            self.tmr.setInterval(100)
            self.tmr.start()
    
        def UpdateGUI(self):
            win32gui.RedrawWindow(self.hwnd, None, None, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ALLCHILDREN)
    
    
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        os.system("taskkill /f /im notepad.exe")
        Form = MyForm()
        sys.exit(app.exec_())
    


  • Any idea?


Log in to reply