Patrik
Patrik

Reputation: 413

Qt::nativeEvent calls

I am working on a Windows 8 x64 laptop. Developing with Qt5. I have some difficulties to handle non-client area color (especially the color frame). I did not find some easy-to-use functions or processes to do that. I found that the DWM message to handle for the title bar color is WM_DWMCOLORIZATIONCOLORCHANGED and I would like to modify its wParam variable to set a new color.

For now I am trying to extend the frame into the client area, using the QtWin::extendFrameIntoClientArea function in an implementation of the nativeEvent function. as it follows:

bool SkyFlies::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
  Q_UNUSED(result);
  Q_UNUSED(eventType);

  MSG *msg = static_cast<MSG*>(message);
  if(msg->message == WM_ACTIVATE)
  {
     const QMargins marge(-1, -1, -1, -1);
     QtWin::extendFrameIntoClientArea(this, marge);
  }
  return false;
}

My question is the following: In the piece of code where I would like to call the preceding function,

SkyFlies::SkyFlies()
{
  ...
  this->nativeEvent();
  ...
}

I would like to know how to fill the function parameters. I know it sounds a bit foolish, but I quite stuck.

Thanks!

Here is an update:

errors like LNK2019 unresolved external symbol... really suck!!!

As I googled my concerns, I found a pretty code to customize the window frame. I used it in my code and after fixing compiler errors, I got a LNK 2019 error for the DwmExtendFrameIntoClientArea function here is the code: the header file-

#include <QtWidgets>

#ifdef Q_OS_WIN

#include <Windows.h>
#include <WinUser.h>
#include <windowsx.h>
#include <dwmapi.h>
#include <minmax.h>
#include <gdiplus.h>
#include <gdipluscolor.h>

#endif

class SkyFlies : public QMainWindow
{
    Q_OBJECT

    ...

    void showEvent(QShowEvent *event);  // Manage window borders
    void windowBorderless();    // Show a borderless window for Windows system
    void windowShadow();    // Set shadow border effect

    ...
};

The implementation file-

// Manage window borders
void SkyFlies::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);

#ifdef Q_OS_WIN

    this->windowBorderless();

#endif
}

#ifdef Q_OS_WIN

void SkyFlies::windowBorderless()
{
    if(this->isVisible())
    {
        SetWindowLongPtr((HWND)winId(), GWL_STYLE, WS_POPUP | WS_CAPTION | WS_THICKFRAME | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
        this->windowShadow();
        SetWindowPos((HWND)winId(), 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
    }
}

void SkyFlies::windowShadow()
{
    const MARGINS shadow={1, 1, 1, 1};
    HRESULT hr = S_OK;
    hr = DwmExtendFrameIntoClientArea((HWND)winId(), &shadow);
}

#endif

Please, how can I resolve the LNK2019 issue? I tried to run QMake without any success. Here is my .pro file:

QT += widgets

SOURCES += \
    main.cpp \
    SkyFlies.cpp

HEADERS += \
    SkyFlies.h \
    SkyWord.h

The SkyWord file is empty. Thanks

As another update, I just read the last answer, I fixed the linker issue few hours ago by adding

#pragma comment (lib,"Dwmapi.lib")

in the header file. In definitive, I got a window extended through the title bar. Now I'm struggling to find a way to change the color of the title bar. But I don't see any satisfactory solution. I thought that I could handle the WM_DWMCOLORIZATIONCHANGED message but no.

And the MSDN example about custom title bar(http://msdn.microsoft.com/en-us/library/bb688195%28VS.85%29.aspx#appendixb) do not talk about changing colors. But maybe there are things to do with the WM_NCPAINT message.

Upvotes: 5

Views: 15722

Answers (2)

Dmitry Sazonov
Dmitry Sazonov

Reputation: 9004

First: you don't need to call nativeEvent method directly. It is a callback that is called by Qt. You may override it.

Second. There are known bugs in Qt5 with processing nativeEvent. So be careful with it. But, as I know, there are problemd only with native child widgets.

Third. Solution: create your own QAbstractNativeEventFilter. Hint, how to use it (because it is not well-documented):

QAbstractEventDispatcher::instance()->installNativeEventFilter(yourFilter);

class MyEventFilter
    : public QAbstractNativeEventFilter
{
public:
    virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *) Q_DECL_OVERRIDE
    {
        MSG *msg = static_cast< MSG * >( message );
        // TODO: filter out or modify msg struct here
        // ...
        return false;
    }
};

Upvotes: 10

Patrik
Patrik

Reputation: 413

After looking for a solution to my problem, I finally find this solution. It is a very good way to build borderless windows using Qt that looks the way many softwares looks today just like (Adobe softwares or MS Office). Thanks for you support.

Upvotes: 2

Related Questions