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. How to draw to the windows Title Bar with Qt? Is this possible?

How to draw to the windows Title Bar with Qt? Is this possible?

Scheduled Pinned Locked Moved General and Desktop
10 Posts 3 Posters 18.3k 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.
  • G Offline
    G Offline
    giesbert
    wrote on 20 Jan 2011, 16:55 last edited by
    #1

    Hi,

    for our project, I have to change the Titlebar look and feel of the application (including the app buttons, minimize etc.). Is there a way to do this with Qt? Is it possible to use Qt in WM_NCPAINT with some tricks?

    I know, it's possible by overwriting WM_NCPAINT message and drawing with windows SDK, but's a bit uncomfortable, especially, as I need gradients.

    I'm using Qt 4.6.3 and MSVS 2008 on windows XP, 2008 Server R1, Windows 7.

    Nokia Certified Qt Specialist.
    Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

    1 Reply Last reply
    0
    • G Offline
      G Offline
      giesbert
      wrote on 23 Jan 2011, 13:51 last edited by
      #2

      Ok, I have one solution, although it's not the best and currently does not do the Application icon and the Titlebar buttons, but I'm sure, it will also be solvable....

      This is my simple widget, just a bit of a Gradient :-)
      @
      void Widget::paintEvent(QPaintEvent*)
      {
      QPainter paint(this);

      paint.fillRect(rect(), QColor(0,180,0));
      
      QLinearGradient grad(0,0,0,rect().height());
      grad.setColorAt(0, QColor(255,255,255,180));
      grad.setColorAt(0.33, QColor(255,255,255,80));
      grad.setColorAt(0.33, QColor(255,255,255,0));
      grad.setColorAt(1, QColor(255,255,255,0));
      paint.fillRect(rect(), grad);
      

      }
      @

      To draw the window frame, you have to overwrite WM_NCPAINT on Windows

      @
      bool Widget::winEvent(MSG* pMessage, long *result)
      {
      if(pMessage->message == WM_NCPAINT)
      {
      paintPicture(pMessage, result);
      return true;
      }
      return QWidget::winEvent(pMessage, result);
      }
      @

      I decided to draw everything into a picture and blit this picture on the screen. This way I have the complete possibilities of Qt for drawing (like Gradients etc.) and can draw into the window frame. The code is not really documented :-) as it's test code. If you have any questions about the sollution, feel free to ask...

      Perhaps I will craete a wiki page if I managed the rest of the title bar like the buttons...

      @
      void Widget::paintPicture(MSG* pMessage, long *result)
      {
      RECT winRect1;
      RECT winRectCl;
      ::GetWindowRect(winId(), &winRect1);
      ::GetClientRect(winId(), &winRectCl);
      HDC hDeviceContext = ::GetWindowDC(winId());
      LONG lStyle = ::GetWindowLong(winId(), GWL_STYLE);

      POINT ptTopLeft = {winRectCl.left, winRectCl.top};
      POINT ptBottomRight = {winRectCl.right, winRectCl.bottom};
      
      ::ClientToScreen(winId(), &ptTopLeft);
      ::ClientToScreen(winId(), &ptBottomRight);
      winRectCl.left = ptTopLeft.x - winRect1.left;
      winRectCl.top = ptTopLeft.y - winRect1.top;
      winRectCl.right = ptBottomRight.x - winRect1.left;
      winRectCl.bottom = ptBottomRight.y - winRect1.top;
      
      winRect1.right = winRect1.right - winRect1.left;
      winRect1.bottom = winRect1.bottom - winRect1.top;
      winRect1.top = 0;
      winRect1.left = 0;
      
      HRGN hRgnOuter = ::CreateRectRgn(winRect1.left, winRect1.top, winRect1.right, winRect1.bottom);
      HRGN hRgnInner = ::CreateRectRgn(winRectCl.left, winRectCl.top, winRectCl.right, winRectCl.bottom);
      HRGN hRgnCombine = ::CreateRectRgn(winRect1.left, winRect1.top, winRect1.right, winRect1.bottom);
      
      ::CombineRgn(hRgnCombine, hRgnOuter, hRgnInner, RGN_DIFF);
      ::SelectClipRgn(hDeviceContext, hRgnCombine);
      
      QPixmap pix(winRect1.right, winRect1.bottom);
      QPainter paint(&pix);
      QRect rc(0,0,winRect1.right, winRect1.bottom);
      
      paint.fillRect(rc, QColor(28,28,28));
      QLinearGradient grad(0,0,0,40);
      grad.setColorAt(0, QColor(255,255,255,180));
      grad.setColorAt(0.33, QColor(255,255,255,80));
      grad.setColorAt(0.33, QColor(255,255,255,0));
      grad.setColorAt(1, QColor(255,255,255,0));
      paint.fillRect(QRect(0,0,winRect1.right, 40), grad);
      
      HBITMAP hBmp = pix.toWinHBITMAP();
      HDC hDC = ::CreateCompatibleDC(hDeviceContext);
      ::SelectObject(hDC, hBmp);
      ::BitBlt(hDeviceContext, winRect1.left, winRect1.top, winRect1.right, winRect1.bottom, hDC, 0, 0, SRCCOPY);
      ::DeleteDC(hDC);
      ::DeleteObject(hBmp);
      
      ::DeleteObject(hRgnOuter);
      ::DeleteObject(hRgnInner);
      ::DeleteObject(hRgnCombine);
      ::ReleaseDC(winId(), hDeviceContext);
      *result = 0;
      

      }
      @

      Nokia Certified Qt Specialist.
      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Mazur
        wrote on 24 Jan 2011, 01:24 last edited by
        #3

        Hello, is it possible for you to post some more code? I mean what libs are you #including? I tried your code in my program and I am getting linker error:

        @debug/nmainwindow.o:J:\nts (1).tar\ns (1)\ns-build-desktop/../ts/nindow.cpp:150: undefined reference to `CreateRectRgn16'@

        etc.. But I am including "windows.h" and "wingdi.h", I have also tried #define FL_DLL.

        Thank You,
        Mazur

        delete this->signature;

        1 Reply Last reply
        0
        • G Offline
          G Offline
          giesbert
          wrote on 24 Jan 2011, 07:47 last edited by
          #4

          I did nothing special for that. It's not an #include thing, it's the library you need. If you want to know, which lib is needed, go to "MSDN":http://msdn.microsoft.com/en-us/ and search for the function, that is missed. It should display, which library to use, which must be done in the pro file.

          But the show solution does not work completely, it does not how the app icon, the buttons are definitely incorrect etc...

          Nokia Certified Qt Specialist.
          Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on 24 Jan 2011, 07:49 last edited by
            #5

            By the way, for CreateRectRgn it should be something like

            @
            LIBS += -lGdi32
            @

            which must be added to the project file

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

            1 Reply Last reply
            0
            • S Offline
              S Offline
              sfabry
              wrote on 24 Jan 2011, 08:07 last edited by
              #6

              Basically :

              use @setWindowFlags(Qt::FramelessWindowHint);@ on your top window, this will remove the OS generated window frame.

              Then simply creates a widget that does what you want for example vertical layout with custom title bar widget and your central widget. Retrieve move events from your titlebar widget and reimplement the window movement etc...

              There's a good tutorial in here but in French (maybe try automatic translation) or go directly into the source code of the tutorial which is commented in English.
              "Lien vers le Tuto":http://qt.developpez.com/tutoriels/braindeadbzh/customwindow/

              1 Reply Last reply
              0
              • G Offline
                G Offline
                giesbert
                wrote on 24 Jan 2011, 08:58 last edited by
                #7

                That's not really a solution, I already tried this.

                There is some impact (especially on windows):

                • a windows without a title bar can't be maximized, only full screen, if you call maximize, it will become full screen (windows specifica)
                • implementing the system menu must be done by hand for the title bar
                • a system menu on right click in the windows tab pane is always incorrect as the states are not know by windows correctly, changing them does not really work
                • If you do maximizing by hand and only use the client area of the screen, you can resize the window (from windows point of view).

                That's why changing the NC paint makes more sense on MS Windows

                Nokia Certified Qt Specialist.
                Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  sfabry
                  wrote on 24 Jan 2011, 10:22 last edited by
                  #8

                  Ok if you need all windows specs, it's different. But as it is windows itself that paint the windows title bar, it nothing about Qt to draw on it I suppose ? Just windows code as you are talking about. Won't be cross platform.

                  What is the point of having a custom title bar if you need all windows specific menus and functions, why not keep the windows defaults ?

                  1 Reply Last reply
                  0
                  • G Offline
                    G Offline
                    giesbert
                    wrote on 24 Jan 2011, 10:36 last edited by
                    #9

                    Perhaps you want a custom look and feel and perhaps more buttons. I know it's possible and we need it for our Cooperate design etc.

                    I know that using windows specifica is not cross platform, but some things will never work cross platform :-(

                    And user expect programs on platform to behave like others on those platform...

                    Nokia Certified Qt Specialist.
                    Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                    1 Reply Last reply
                    0
                    • G Offline
                      G Offline
                      giesbert
                      wrote on 1 Mar 2011, 19:20 last edited by
                      #10

                      Due to the same discussion in another thread, I close this one:

                      "Painting in the NonClientArea":http://developer.qt.nokia.com/forums/viewthread/3847/

                      [EDIT: wrong link, Volker]

                      Nokia Certified Qt Specialist.
                      Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

                      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