Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. A frameless and translucent QWidget with WS_THICKFRAME
QtWS25 Last Chance

A frameless and translucent QWidget with WS_THICKFRAME

Scheduled Pinned Locked Moved General and Desktop
10 Posts 3 Posters 5.5k 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.
  • L Offline
    L Offline
    lingdhox
    wrote on last edited by
    #1

    In mfc/win32, usually use updatelayeredwindow to implement translucent window. The window can have WS_THICKFRAME and WS_CAPTION properties. The System animation of minimized depends WS_CAPTION. The System animation of auto maximum depends WS_THICKFRAME.

    But in Qt, it only can set FramelessWindowHint flag.

    This is YY written by Qt. --link removed--
    Spy indicate YY have WS_EX_LAYERED, WS_THICKFRAME, WS_CAPTION. I don't know how it works with WS_THICKFRAME?

    [andreyc: looks like spam or phishing message. I removed a link]

    1 Reply Last reply
    0
    • Z Offline
      Z Offline
      zeljko
      wrote on last edited by
      #2

      QWidget::winID is windows HWND of your window, so you can try to handle it directly via win api.

      1 Reply Last reply
      0
      • L Offline
        L Offline
        lingdhox
        wrote on last edited by
        #3

        [quote author="zeljko" date="1399727234"]QWidget::winID is windows HWND of your window, so you can try to handle it directly via win api.[/quote]

        I tried to handle QWidget directly via win api. But this leads to another problem. The QWidget's interface can't refresh after maximized.
        Here is a sample code.
        @
        test2.h
        #include <QWidget>

        class test2 : public QWidget
        {
        Q_OBJECT

        public:
        test2(QWidget *parent);
        ~test2();

        public slots:
        void OnBtnClicked();

        protected:
        bool nativeEvent( const QByteArray & eventType, void * message, long * result );
        void paintEvent(QPaintEvent*);
        bool event(QEvent * event);

        // wm msg handler
        bool HandleGetMinMaxInfoMsg(MSG *msg, long *result);

        private:

        };
        @

        @ test2.cpp
        #include "test2.h"
        #include <Windows.h>
        #include <QEvent>
        #include <QDebug>
        #include <QDesktopWidget>
        #include <windowsx.h>
        #include <QWindow>
        #include <QSurfaceFormat>
        #include <QPushButton>
        #include <QPainter>
        #include <QApplication>

        test2::test2(QWidget *parent)
        : QWidget(parent)
        {
        QPushButton *pbn = new QPushButton("test", this);
        pbn->move(100, 100);
        connect(pbn, SIGNAL(clicked()), this, SLOT(OnBtnClicked()));

        setWindowFlags(Qt::FramelessWindowHint | Qt::Window );
        setAttribute(Qt::WA_TranslucentBackground);

        }

        test2::~test2()
        {

        }

        bool test2::event(QEvent * e)
        {
        if(e->type() == QEvent::WinIdChange)
        {
        HWND hWnd = (HWND)this->winId();
        LONG lStyle = ::GetWindowLong(hWnd, GWL_STYLE);
        ::SetWindowLong(hWnd, GWL_STYLE, lStyle | WS_OVERLAPPED | WS_THICKFRAME);
        }
        return QWidget::event(e);
        }

        bool test2::nativeEvent( const QByteArray & eventType, void * message, long * result )
        {
        MSG *msg = (MSG *)message;
        const int captionHeight = 32;
        const int frameWidth = 5;

        switch (msg->message )
        {

        case WM_GETMINMAXINFO :
        HandleGetMinMaxInfoMsg(msg, result);
        *result = 0;
        return true;
        }

        return QWidget::nativeEvent(eventType, message, result);
        }

        void test2::paintEvent( QPaintEvent* )
        {
        QPainter painter(this);

        HWND hWnd = (HWND)this->winId();
        RECT winRect;
        ::GetWindowRect(hWnd, &winRect);
        QRect qWinRect = QRect(0, 0, winRect.right - winRect.left, winRect.bottom - winRect.top);

        QRect rc = rect();
        qDebug () << "paintevent" << rc << qWinRect;

        painter.fillRect(rc, QColor(0,0,0));
        rc.adjust(6, 30, -6, -6);
        painter.fillRect(rc, QColor(0, 0, 255, 250));

        }

        bool test2::HandleGetMinMaxInfoMsg( MSG *msg, long *result )
        {
        QRect maxRect = QApplication::desktop()->availableGeometry();
        QSize szMin = this->minimumSize();
        QSize szMax = this->maximumSize();
        PMINMAXINFO lpMMI = (PMINMAXINFO)msg->lParam;
        lpMMI->ptMaxSize.x = maxRect.width();
        lpMMI->ptMaxSize.y = maxRect.height();
        lpMMI->ptMaxPosition.x = 0;
        lpMMI->ptMaxPosition.y = 0;
        lpMMI->ptMinTrackSize.x = szMin.width();
        lpMMI->ptMinTrackSize.y = szMin.height();
        lpMMI->ptMaxTrackSize.x = szMax.width();
        lpMMI->ptMaxTrackSize.y = szMax.height();

        return true;

        }

        void test2::OnBtnClicked()
        {
        static bool bMin = false;
        bMin = !bMin;

        if(bMin)
        {
        showMaximized();
        }
        else
        {
        showNormal();
        }
        }
        @

        I have tried to simplify.

        1 Reply Last reply
        0
        • M Offline
          M Offline
          MuldeR
          wrote on last edited by
          #4

          Did you take care of this?

          bq. Certain window data is cached, so changes you make using SetWindowLong will not take effect until you call the SetWindowPos function. Specifically, if you change any of the frame styles, you must call SetWindowPos with the SWP_FRAMECHANGED flag for the cache to be updated properly.

          My OpenSource software at: http://muldersoft.com/

          Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

          Go visit the coop: http://youtu.be/Jay...

          1 Reply Last reply
          0
          • L Offline
            L Offline
            lingdhox
            wrote on last edited by
            #5

            [quote author="MuldeR" date="1399870644"]Did you take care of this?
            [/quote]
            The SetWindowPos function with the SWP_FRAMECHANGED flag does not take effect. I don't sure whether called properly.
            bq.
            @SWP_FRAMECHANGED
            Applies new frame styles set using the SetWindowLong function. Sends a WM_NCCALCSIZE message to the window, even if the window's size is not being changed. If this flag is not specified, WM_NCCALCSIZE is sent only when the window's size is being changed.@

            Actually I don't change the window's size, just change the background.
            So I think the SetWindowPos function should not refer with this problem.

            1 Reply Last reply
            0
            • Z Offline
              Z Offline
              zeljko
              wrote on last edited by
              #6

              Then SWP_FRAMECHANGED should be send by SetWindowLong ?

              1 Reply Last reply
              0
              • M Offline
                M Offline
                MuldeR
                wrote on last edited by
                #7

                After SetWindowLong() you need to call SetWindowPos() in order to make the changes take effect. Otherwise you can get "strange" results.

                Regardless of the function's name, SetWindowPos() is not just for moving or resizing the window. Read the MSDN article about SetWindowLong() ;-)

                @SetWindowLong(hWnd, GWL_STYLE, lStyle | WS_OVERLAPPED | WS_THICKFRAME);
                SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);@

                My OpenSource software at: http://muldersoft.com/

                Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

                Go visit the coop: http://youtu.be/Jay...

                1 Reply Last reply
                0
                • L Offline
                  L Offline
                  lingdhox
                  wrote on last edited by
                  #8

                  [quote author="zeljko" date="1399880583"]Then SWP_FRAMECHANGED should be send by SetWindowLong ?[/quote]

                  [quote author="MuldeR" date="1399897540"]
                  @SetWindowLong(hWnd, GWL_STYLE, lStyle | WS_OVERLAPPED | WS_THICKFRAME);
                  SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED);@[/quote]

                  I really tried, call SetWindowPos() after SetWindowLong(). It has no effect.
                  I found a solution to solve this problem, call ::ShowWindow(hWnd, SW_SHOWMAXIMIZED) instead of showMaximized(). But this Widget does exist lots of bugs as call many win32 api.

                  -_-! I can't find a perfect solution. So I have to abandon the System animation and win32 api call.

                  Thank you for you help.(@MuldeR and @zeljko)

                  1 Reply Last reply
                  0
                  • Z Offline
                    Z Offline
                    zeljko
                    wrote on last edited by
                    #9

                    ShowWindow(hWnd, SW_SHOWMAXIMIZED) works but QWidget::showMaximized not ?!? c'mon :) ...
                    Have you tried (just for test) to hide widget after setting WS_THICKFRAME and then show it again ?

                    1 Reply Last reply
                    0
                    • L Offline
                      L Offline
                      lingdhox
                      wrote on last edited by
                      #10

                      [quote author="zeljko" date="1399957716"]ShowWindow(hWnd, SW_SHOWMAXIMIZED) works but QWidget::showMaximized not ?!? c'mon :) ...
                      Have you tried (just for test) to hide widget after setting WS_THICKFRAME and then show it again ?[/quote]
                      Yeah.. You can try the test code(test.h, test.cpp). My Qt version 5.1.1.
                      I am also very strange! :)

                      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