Skip to content

Instantly share code, notes, and snippets.

@d1manson
Last active November 11, 2018 17:19
Show Gist options
  • Save d1manson/51aec9e2395478e775d8 to your computer and use it in GitHub Desktop.
Save d1manson/51aec9e2395478e775d8 to your computer and use it in GitHub Desktop.

This seems to be a rare example of painting to non-client area from a Qt application (on windows). I've mirrored it here because the original files were hidden behind an annoying sign-up process thing. I actually want to do this in PyQt - see also this SO question which is where I found the link to the qtforum posting.

Dear Qt Developers/Experts

My goal is to draw tabbar in titlebar (only in Windows) similar to firefox/chrome.
I am using some DWM apis to achieve that as mentioned in
http://msdn.microsoft.com/en-us/libr...=vs.85%29.aspx
Basically I make the entire area as nonclientarea and tabbar is drawn at the top automatically.

I know these DWM apis only work with Windows Aero enabled, and I am fine with tabbar
not shown in titlebar with DWM disabled.

I am facing two issues.
1. When the application is maximized, part of the left, top window portion 
gets clipped. See the attached image.
2. If I enable 'Auto hide taskbar' property in Windows, I would expect the
taskbar to popup when mouse is moved down near the taskbar with application 
maximized. That is not happening as well.

I have attached a sample project that creates the issue.
Can somebody help with this.
Any suggestions are welcome.

I can perfectly solve issue (1) with setContentsMargins() if I know the
exact amount of pixels that are being clipped.

Thanks
Rajendran
#include <QApplication>
#include <QTabWidget>
#include <QLineEdit>
#include <QDebug>
#include "mainwindow.h"
#include "Windows.h"
#include "WinUser.h"
#include "windowsx.h"
#include "dwmapi.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setAttribute(Qt::WA_TranslucentBackground, true);
QTabWidget *t = new QTabWidget(this);
t->setTabsClosable(true);
t->setMovable(true);
t->setDocumentMode(true);
t->addTab(new QLineEdit("1234"), "tab 1");
t->addTab(new QLineEdit, "tab 2");
t->addTab(new QLineEdit, "tab 3");
t->addTab(new QLineEdit, "tab 4");
this->setCentralWidget(t);
resize(400,200);
// Handle window creation.
RECT rcClient;
GetWindowRect(this->winId(), &rcClient);
// Inform application of the frame change.
SetWindowPos(this->winId(),
NULL,
rcClient.left, rcClient.top,
rcClient.right - rcClient.left,
rcClient.bottom - rcClient.top,
SWP_FRAMECHANGED);
}
bool MainWindow::winEvent(MSG *msg, long *result)
{
bool fCallDWP = true;
BOOL fDwmEnabled = FALSE;
LRESULT lRet = 0;
HRESULT hr = S_OK;
HWND hWnd = msg->hwnd;
UINT message = msg->message;
WPARAM wParam = msg->wParam;
LPARAM lParam = msg->lParam;
// Winproc worker for custom frame issues.
hr = DwmIsCompositionEnabled(&fDwmEnabled);
if (!SUCCEEDED(hr) || !fDwmEnabled)
{
qDebug() << "DWM not enabled";
return false;
}
fCallDWP = !DwmDefWindowProc(hWnd, message, wParam, lParam, &lRet);
// Handle window activation.
if (message == WM_ACTIVATE)
{
// Extend the frame into the client area.
MARGINS margins;
margins.cxLeftWidth = 8; // 8
margins.cxRightWidth = 8; // 8
margins.cyBottomHeight = 20; // 20
margins.cyTopHeight = 27; // 27
hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
if (!SUCCEEDED(hr))
{
// Handle error.
}
fCallDWP = true;
lRet = 0;
}
// Handle the non-client size message.
if ((message == WM_NCCALCSIZE) && (wParam == TRUE))
{
qDebug() << "WM_NCCALCSIZE";
// Calculate new NCCALCSIZE_PARAMS based on custom NCA inset.
NCCALCSIZE_PARAMS *pncsp = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
pncsp->rgrc[0].left = pncsp->rgrc[0].left + 0;
pncsp->rgrc[0].top = pncsp->rgrc[0].top + 0;
pncsp->rgrc[0].right = pncsp->rgrc[0].right - 0;
pncsp->rgrc[0].bottom = pncsp->rgrc[0].bottom - 0;
lRet = 0;
// No need to pass the message on to the DefWindowProc.
fCallDWP = false;
}
if (!fCallDWP)
*result = lRet;
return !fCallDWP;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
protected:
bool winEvent(MSG *msg, long *result);
};
#endif // MAINWINDOW_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment