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

WA_TranslucentBackground Frameless windows problem with WIN32 API SetParent

Scheduled Pinned Locked Moved Unsolved Qt 6
watranslucentbframelesswin32apitransparent
4 Posts 2 Posters 909 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.
  • E Offline
    E Offline
    Emrecp
    wrote on 8 Aug 2021, 09:33 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
    • E Offline
      E Offline
      Emrecp
      wrote on 10 Aug 2021, 16:31 last edited by
      #2

      Any idea? Maybe @SGaist can help me?

      1 Reply Last reply
      0
      • S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 10 Aug 2021, 18:34 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

        E 1 Reply Last reply 15 Aug 2021, 07:06
        0
        • S SGaist
          10 Aug 2021, 18:34

          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.

          E Offline
          E Offline
          Emrecp
          wrote on 15 Aug 2021, 07:06 last edited by
          #4

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

          1 Reply Last reply
          0

          2/4

          10 Aug 2021, 16:31

          • Login

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