Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. General talk
  3. Qt 6
  4. WA_TranslucentBackground Frameless windows problem with WIN32 API SetParent
QtWS25 Last Chance

WA_TranslucentBackground Frameless windows problem with WIN32 API SetParent

Scheduled Pinned Locked Moved Unsolved Qt 6
watranslucentbframelesswin32apitransparent
4 Posts 2 Posters 903 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • EmrecpE Offline
    EmrecpE Offline
    Emrecp
    wrote on last edited by
    #1

    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_())
    

    Thank you very much!

    1 Reply Last reply
    0
    • EmrecpE Offline
      EmrecpE Offline
      Emrecp
      wrote on last edited by
      #2

      Any idea? Maybe @SGaist can help me?

      1 Reply Last reply
      0
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        @Emrecp said in WA_TranslucentBackground Frameless windows problem with WIN32 API SetParent:

        self.parent = parent

        You are nuking the original property with this one. I am not saying that this is the cause of your issue but it may have some influence.

        Why are you mixing super calls and base class method invocation ?

        That said, when calling winId, your widget will get a native handle like explained in the method documentation. So I wonder if this triggers the effect you are seeing.

        Try reordering that stuff, and start by making the parenting and only then finish the custom setup.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        EmrecpE 1 Reply Last reply
        0
        • SGaistS SGaist

          Hi,

          @Emrecp said in WA_TranslucentBackground Frameless windows problem with WIN32 API SetParent:

          self.parent = parent

          You are nuking the original property with this one. I am not saying that this is the cause of your issue but it may have some influence.

          Why are you mixing super calls and base class method invocation ?

          That said, when calling winId, your widget will get a native handle like explained in the method documentation. So I wonder if this triggers the effect you are seeing.

          Try reordering that stuff, and start by making the parenting and only then finish the custom setup.

          EmrecpE Offline
          EmrecpE Offline
          Emrecp
          wrote on last edited by
          #4

          @SGaist
          removing self.parent = parent did not help. Problem still continues.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved