[win-linux] add feature: thin window frame

This commit is contained in:
SimplestStudio
2024-04-04 11:38:35 +03:00
parent ceddd8b423
commit 1d804c9d76
12 changed files with 315 additions and 104 deletions

View File

@ -298,8 +298,6 @@ core_windows {
build_xp {
DEFINES += __OS_WIN_XP
} else {
LIBS += -ldwmapi
}
}

View File

@ -1018,6 +1018,25 @@ namespace WindowHelper {
::AttachThreadInput(frgID, appID, FALSE);
}
auto getColorizationColor(bool isActive) -> QColor
{
QColor color = GetColorByRole(ecrWindowBorder);
QSettings reg("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\DWM", QSettings::NativeFormat);
if (isActive && reg.value("ColorPrevalence", 0).toInt() != 0) {
DWORD dwcolor = 0;
BOOL opaque = TRUE;
static HRESULT(WINAPI *DwmGetColorizationColor)(DWORD*, BOOL*) = NULL;
if (!DwmGetColorizationColor) {
if (HMODULE module = GetModuleHandleA("dwmapi"))
*(FARPROC*)&DwmGetColorizationColor = GetProcAddress(module, "DwmGetColorizationColor");
}
if (DwmGetColorizationColor && SUCCEEDED(DwmGetColorizationColor(&dwcolor, &opaque))) {
color = QColor((dwcolor & 0xff0000) >> 16, (dwcolor & 0xff00) >> 8, dwcolor & 0xff);
}
}
return color;
}
auto toggleLayoutDirection(HWND hwnd) -> void
{
LONG exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);

View File

@ -162,6 +162,7 @@ namespace WindowHelper {
auto correctModalOrder(HWND windowhandle, HWND modalhandle) -> void;
auto adjustWindowRect(HWND, double, LPRECT) -> void;
auto bringToTop(HWND) -> void;
auto getColorizationColor(bool isActive = true) -> QColor;
auto toggleLayoutDirection(HWND hwnd) -> void;
#endif

View File

@ -459,7 +459,7 @@ public:
border = GetColorValueByRole(ecrWindowBorder);
}
window->setWindowColors(QColor(QString::fromStdWString(background)), QColor(QString::fromStdWString(border)));
window->setWindowColors(QColor(QString::fromStdWString(background)), QColor(QString::fromStdWString(border)), window->isActiveWindow());
}
void changeTheme(const std::wstring& theme)

View File

@ -73,6 +73,9 @@ CWindowBase::CWindowBase(const QRect& rect)
{
setWindowIcon(Utils::appIcon());
m_window_rect = startRect(rect, m_dpiRatio);
#ifdef __linux__
setGeometry(m_window_rect); // for Windows is set in CWindowPlatform
#endif
}
CWindowBase::~CWindowBase()
@ -95,7 +98,11 @@ QSize CWindowBase::expectedContentSize(const QRect &rc, bool extended)
{
double dpi = 1.0;
QRect win_rc = startRect(rc, dpi);
#ifdef _WIN32
int brd = Utils::getWinVersion() < Utils::WinVer::Win10 ? MAIN_WINDOW_BORDER_WIDTH * dpi : 0;
#else
int brd = MAIN_WINDOW_BORDER_WIDTH * dpi;
#endif
return win_rc.adjusted(brd, extended ? brd : TITLE_HEIGHT * dpi + brd, -brd, -brd).size();
}
@ -118,15 +125,30 @@ void CWindowBase::updateScaling(bool resize)
}
}
void CWindowBase::setWindowColors(const QColor& background, const QColor& border)
void CWindowBase::setWindowColors(const QColor& background, const QColor& border, bool isActive)
{
m_brdColor = border;
setStyleSheet(QString("QMainWindow{border:1px solid %1;"
m_bkgColor = background;
#ifdef _WIN32
"border-bottom:2px solid %1;"
QString css;
if (Utils::getWinVersion() <= Utils::WinVer::Win7) {
css = QString("QMainWindow{background-color: %1;}").arg(background.name());
} else
if (Utils::getWinVersion() < Utils::WinVer::Win10) {
css = QString("QMainWindow{border:1px solid %1; background-color: %2;}").arg(border.name(), background.name());
} else
if (Utils::getWinVersion() == Utils::WinVer::Win10) {
int brdWidth = 0;
SystemParametersInfo(SPI_GETBORDER, 0, &brdWidth, 0);
QColor brdColor = WindowHelper::getColorizationColor(isActive);
css = QString("QMainWindow{border-top: %1px solid %2; background-color: %3;}").arg(QString::number(brdWidth), brdColor.name(), background.name());
} else {
css = QString("QMainWindow{background-color: %1;}").arg(background.name());
}
#else
QString css = QString("QMainWindow{border:1px solid %1; background-color: %2;}").arg(border.name(), background.name());
#endif
"background-color: %2;"
"}").arg(border.name(), background.name()));
setStyleSheet(css);
}
void CWindowBase::applyTheme(const std::wstring& theme)
@ -134,7 +156,7 @@ void CWindowBase::applyTheme(const std::wstring& theme)
Q_UNUSED(theme)
QColor background = GetColorByRole(ecrWindowBackground);
QColor border = GetColorByRole(ecrWindowBorder);
setWindowColors(background, border);
setWindowColors(background, border, isActiveWindow());
}
/** Protected **/
@ -298,7 +320,6 @@ void CWindowBase::showEvent(QShowEvent *event)
QMainWindow::showEvent(event);
if (!m_windowActivated) {
m_windowActivated = true;
setGeometry(m_window_rect);
adjustGeometry();
applyTheme(GetCurrentTheme().id());
}

View File

@ -42,7 +42,7 @@
#define EDITOR_WINDOW_MIN_WIDTH 920
#define BUTTON_MAIN_WIDTH 112
#define MAIN_WINDOW_BORDER_WIDTH 4
#define MAIN_WINDOW_BORDER_WIDTH 3
#define WINDOW_TITLE_MIN_WIDTH 200
#define TOOLBTN_HEIGHT 28
#define TOOLBTN_WIDTH 40
@ -58,12 +58,6 @@
#include <memory>
#include "components/celipsislabel.h"
#ifdef _WIN32
# include <windows.h>
# include <windowsx.h>
# include <dwmapi.h>
#endif
class CWindowBase : public QMainWindow
{
@ -77,7 +71,7 @@ public:
bool isCustomWindowStyle();
void updateScaling(bool resize = true);
virtual void adjustGeometry() = 0;
virtual void setWindowColors(const QColor&, const QColor& border = QColor());
virtual void setWindowColors(const QColor&, const QColor& border = QColor(), bool isActive = false);
virtual void applyTheme(const std::wstring&);
protected:
@ -105,14 +99,15 @@ protected:
*m_boxTitleBtns = nullptr,
*m_pMainView = nullptr;
double m_dpiRatio;
QColor m_brdColor;
QColor m_brdColor,
m_bkgColor;
QRect m_window_rect;
virtual void showEvent(QShowEvent *);
private:
class CWindowBasePrivate;
std::unique_ptr<CWindowBasePrivate> pimpl;
QRect m_window_rect;
bool m_windowActivated;
};

View File

@ -91,11 +91,11 @@ void CWindowPlatform::show(bool maximized)
}
}
void CWindowPlatform::setWindowColors(const QColor& background, const QColor& border)
void CWindowPlatform::setWindowColors(const QColor& background, const QColor& border, bool isActive)
{
Q_UNUSED(border)
if (!CX11Decoration::isDecorated()) {
CWindowBase::setWindowColors(background, border);
CWindowBase::setWindowColors(background, border, isActive);
}
}

View File

@ -45,7 +45,7 @@ public:
void bringToTop();
void show(bool);
virtual void setWindowColors(const QColor&, const QColor& border = QColor()) final;
virtual void setWindowColors(const QColor&, const QColor& border = QColor(), bool isActive = false) final;
virtual void adjustGeometry() final;
protected:

View File

@ -31,6 +31,7 @@
*/
#include "cx11decoration.h"
#include "windows/cwindowbase.h"
#include "utils.h"
#include <QX11Info>
#include <QTimer>
@ -40,7 +41,7 @@
#include <X11/Xutil.h>
#include "platform_linux/xcbutils.h"
#define CUSTOM_BORDER_WIDTH 4
#define CUSTOM_BORDER_WIDTH MAIN_WINDOW_BORDER_WIDTH
#define MOTION_TIMER_MS 250
const int k_NET_WM_MOVERESIZE_SIZE_TOPLEFT = 0;

View File

@ -42,6 +42,8 @@
#include <QCoreApplication>
#include "utils.h"
#define RESIZE_AREA_PART 0.14
class Caption: public QWidget
{
@ -63,6 +65,14 @@ private:
return (arranging == TRUE);
}
bool isResizingAvailable() {
return Utils::getWinVersion() >= Utils::WinVer::Win10 && !IsZoomed(hwnd_root);
}
bool isPointInResizeArea(int posY) {
return posY <= RESIZE_AREA_PART * height();
}
QPoint cursorPos() {
POINT pt;
::GetCursorPos(&pt);
@ -85,7 +95,7 @@ private:
QPoint pos = mapFromGlobal(QPoint(int(pt.x), int(pt.y)));
if (!buttonAtPos(pos)) {
::ReleaseCapture();
::PostMessage(hwnd_root, cmd, HTCAPTION, POINTTOPOINTS(pt));
::PostMessage(hwnd_root, cmd, isResizingAvailable() && isPointInResizeArea(pos.y()) ? HTTOP : HTCAPTION, POINTTOPOINTS(pt));
QCoreApplication::postEvent(parent(), new QEvent(QEvent::MouseButtonPress));
return true;
}
@ -112,6 +122,13 @@ private:
return true;
break;
}
case WM_MOUSEMOVE: {
if (isResizingAvailable()) {
int y = GET_Y_LPARAM(msg->lParam);
setCursor(!buttonAtPos(QPoint(GET_X_LPARAM(msg->lParam), y)) && isPointInResizeArea(y) ? Qt::SizeVerCursor : Qt::ArrowCursor);
}
break;
}
case WM_NCLBUTTONDOWN: {
if (Utils::getWinVersion() < Utils::WinVer::Win11)
break;

View File

@ -39,11 +39,91 @@
#include <QWindow>
#include <QScreen>
#include <QJsonObject>
#include <windowsx.h>
#include <shellapi.h>
//#define UM_SNAPPING 0x02
#define DCX_USESTYLE 0x00010000
#define NC_AREA_WIDTH 3
#define SKIP_EVENTS_QUEUE(callback) QTimer::singleShot(0, this, callback)
using WinVer = Utils::WinVer;
static double GetLogicalDpi(QWidget *wgt)
{
#ifdef __OS_WIN_XP
HDC hdc = GetDC(NULL);
double dpi = (double)GetDeviceCaps(hdc, LOGPIXELSX)/96;
ReleaseDC(NULL, hdc);
return dpi;
#else
auto scr = wgt->windowHandle()->screen();
return scr ? scr->logicalDotsPerInch()/96 : 1.0;
#endif
}
static void GetFrameMetricsForDpi(FRAME &frame, double dpi, bool maximized = false)
{
WinVer ver = Utils::getWinVersion();
int row = ver == WinVer::WinXP ? 0 :
ver <= WinVer::Win7 ? 1 :
ver <= WinVer::Win8_1 ? 2 :
ver <= WinVer::Win10 ? 3 : 4;
int column = dpi <= 1.0 ? 0 :
dpi <= 1.25 ? 1 :
dpi <= 1.5 ? 2 :
dpi <= 1.75 ? 3 :
dpi <= 2.0 ? 4 :
dpi <= 2.25 ? 5 :
dpi <= 2.5 ? 6 :
dpi <= 3.0 ? 7 :
dpi <= 3.5 ? 8 :
dpi <= 4.0 ? 9 :
dpi <= 4.5 ? 10 :
dpi <= 5.0 ? 11 : 12;
const int left[5][13] = { // Left margin for scales 100-500%
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2}, // WinXp: for NC width 3px
{4, 5, 7, 8, 9, 10, 12, 14, 17, 19, 22, 24, 29}, // WinVista - Win7: for NC width 3px
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // Win8 - Win8.1
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win10
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Win11
};
frame.left = left[row][column];
const int top[5][13] = { // Top margin for scales 100-500%
{0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 2}, // WinXp: for NC width 3px
{4, 5, 7, 8, 9, 10, 12, 14, 17, 19, 22, 24, 29}, // WinVista - Win7: for NC width 3px
{7, 8, 10, 11, 12, 13, 15, 17, 20, 22, 25, 27, 32}, // Win8 - Win8.1
{31, 38, 45, 52, 58, 65, 72, 85, 99, 112, 126, 139, 167}, // Win10
{30, 37, 43, 50, 56, 63, 69, 82, 95, 108, 121, 134, 161} // Win11
};
frame.top = top[row][column];
if (!maximized)
return;
const int left_ofs[5][13] = { // Left offset for scales 100-500%
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinXp
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinVista - Win7
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win8 - Win8.1
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win10
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} // Win11
};
frame.left -= left_ofs[row][column];
const int top_ofs[5][13] = { // Top offset for scales 100-500%
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinXp
{-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, // WinVista - Win7
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // Win8 - Win8.1
{8, 9, 11, 12, 13, 14, 16, 18, 21, 24, 27, 30, 36}, // Win10
{7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 21, 23, 28} // Win11
};
frame.top -= top_ofs[row][column];
}
static bool isTaskbarAutoHideOn()
{
APPBARDATA ABData;
@ -51,8 +131,19 @@ static bool isTaskbarAutoHideOn()
return (SHAppBarMessage(ABM_GETSTATE, &ABData) & ABS_AUTOHIDE) != 0;
}
static bool isThemeActive()
{
static BOOL(WINAPI *IsThemeActive)() = NULL;
if (!IsThemeActive) {
if (HMODULE module = GetModuleHandleA("uxtheme"))
*(FARPROC*)&IsThemeActive = GetProcAddress(module, "IsThemeActive");
}
return IsThemeActive ? (bool)IsThemeActive() : true;
}
CWindowPlatform::CWindowPlatform(const QRect &rect) :
CWindowBase(rect),
m_dpi(1.0),
m_hWnd(nullptr),
m_resAreaWidth(MAIN_WINDOW_BORDER_WIDTH),
m_borderless(true),
@ -60,21 +151,17 @@ CWindowPlatform::CWindowPlatform(const QRect &rect) :
m_isResizeable(true)
// m_allowMaximize(true)
{
m_isThemeActive = isThemeActive();
m_isTaskbarAutoHideOn = isTaskbarAutoHideOn();
m_borderless = isCustomWindowStyle();
if (AscAppManager::isRtlEnabled())
setLayoutDirection(Qt::RightToLeft);
setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint
| Qt::WindowSystemMenuHint | Qt::WindowMaximizeButtonHint
|Qt::WindowMinimizeButtonHint | Qt::MSWindowsFixedSizeDialogHint);
m_borderless = isCustomWindowStyle();
setGeometry(m_window_rect);
m_hWnd = (HWND)winId();
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE);
style &= ~(WS_CAPTION | WS_SYSMENU | WS_THICKFRAME);
style |= (WS_CLIPCHILDREN | WS_MAXIMIZEBOX | WS_MINIMIZEBOX);
style |= (Utils::getWinVersion() > Utils::WinVer::Win7) ? WS_OVERLAPPEDWINDOW : WS_POPUP;
::SetWindowLong(m_hWnd, GWL_STYLE, style);
connect(this->window()->windowHandle(), &QWindow::screenChanged, this, [=]() {
SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
});
if (m_borderless && Utils::getWinVersion() < WinVer::Win10) {
LONG style = ::GetWindowLong(m_hWnd, GWL_STYLE) & ~WS_CAPTION;
::SetWindowLong(m_hWnd, GWL_STYLE, style);
}
setProperty("stabilized", true);
m_propertyTimer = new QTimer(this);
@ -83,6 +170,11 @@ CWindowPlatform::CWindowPlatform(const QRect &rect) :
connect(m_propertyTimer, &QTimer::timeout, this, [=]() {
setProperty("stabilized", true);
});
m_isMaximized = IsZoomed(m_hWnd);
m_dpi = GetLogicalDpi(this);
GetFrameMetricsForDpi(m_frame, m_dpi, m_isMaximized);
SetWindowPos(m_hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
CWindowPlatform::~CWindowPlatform()
@ -120,36 +212,36 @@ void CWindowPlatform::show(bool maximized)
void CWindowPlatform::adjustGeometry()
{
if (windowState().testFlag(Qt::WindowMinimized) || windowState().testFlag(Qt::WindowNoState)) {
const int border = int(MAIN_WINDOW_BORDER_WIDTH * m_dpiRatio);
setContentsMargins(border, border, border, border+1);
m_resAreaWidth = border;
} else
if (windowState().testFlag(Qt::WindowMaximized)) {
QTimer::singleShot(25, this, [=]() {
auto rc = QApplication::desktop()->availableGeometry(this);
const QSize offset(0, !isTaskbarAutoHideOn() ? 0 : 2);
SetWindowPos(m_hWnd, NULL, rc.x(), rc.y(), rc.width(), rc.height() - offset.height(),
SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
#ifdef __OS_WIN_XP
setContentsMargins(0, 0, 0, 0);
#else
int border = 0;
if (!isTaskbarAutoHideOn() && Utils::getWinVersion() > Utils::WinVer::Win7) {
double dpi = qApp->screenAt(geometry().center())->logicalDotsPerInch()/96;
border = (dpi <= 1.0) ? 8 :
(dpi == 1.25) ? 9 :
(dpi == 1.5) ? 11 :
(dpi == 1.75) ? 12 :
(dpi == 2.0) ? 13 :
(dpi == 2.25) ? 14 :
(dpi == 2.5) ? 16 : 6 * dpi;
}
setContentsMargins(border, border, border, border);
#endif
});
QMargins mrg;
if (!m_borderless) {
setContentsMargins(mrg);
return;
}
if (isMaximized()) {
if (Utils::getWinVersion() < WinVer::Win10) {
QTimer::singleShot(25, this, [=]() {
auto rc = QApplication::desktop()->availableGeometry(this);
int offset = 0;
if (Utils::getWinVersion() > WinVer::WinXP && isTaskbarAutoHideOn())
offset += 2;
SetWindowPos(m_hWnd, NULL, rc.x(), rc.y(), rc.width(), rc.height() - offset, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOSENDCHANGING);
});
}
} else {
if (Utils::getWinVersion() < WinVer::Win10) {
int border = qRound(MAIN_WINDOW_BORDER_WIDTH * m_dpiRatio);
if (Utils::getWinVersion() <= WinVer::Win7)
border -= NC_AREA_WIDTH;
mrg = QMargins(border, border, border, border);
} else
if (Utils::getWinVersion() == WinVer::Win10) {
int brdWidth = 0;
SystemParametersInfo(SPI_GETBORDER, 0, &brdWidth, 0);
mrg = QMargins(0, brdWidth, 0, 0);
}
m_resAreaWidth = mrg.top();
}
setContentsMargins(mrg);
}
/** Protected **/
@ -193,40 +285,15 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
switch (msg->message)
{
case WM_ACTIVATE: {
#ifndef __OS_WIN_XP
MARGINS mrg = {4, 4, 29, 4};
if (Utils::getWinVersion() > Utils::WinVer::Win10) {
mrg.cxLeftWidth = 1;
mrg.cxRightWidth = 0;
mrg.cyBottomHeight = 0;
mrg.cyTopHeight = 0;
}
DwmExtendFrameIntoClientArea(m_hWnd, &mrg);
#endif
break;
}
case WM_DPICHANGED: {
setMinimumSize(0,0);
if (AscAppManager::IsUseSystemScaling()) {
if (WindowHelper::isLeftButtonPressed() || (m_scaleChanged && !isMaximized())) {
RECT *prefRect = (RECT*)msg->lParam;
setGeometry(prefRect->left, prefRect->top, prefRect->right - prefRect->left, prefRect->bottom - prefRect->top);
}
SKIP_EVENTS_QUEUE([=]() {
updateScaling(false);
});
} else
if (m_scaleChanged && !isMaximized()) {
RECT *prefRect = (RECT*)msg->lParam;
setGeometry(prefRect->left, prefRect->top, prefRect->right - prefRect->left, prefRect->bottom - prefRect->top);
}
m_scaleChanged = false;
break;
}
case WM_DISPLAYCHANGE: {
m_scaleChanged = true;
m_dpi = (double)HIWORD(msg->wParam)/96;
GetFrameMetricsForDpi(m_frame, m_dpi, m_isMaximized);
if (AscAppManager::IsUseSystemScaling())
updateScaling(false);
break;
}
@ -243,8 +310,17 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
if (!m_borderless || !msg->wParam)
break;
NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS*)msg->lParam;
params->rgrc[0].bottom += 1;
*result = WVR_ALIGNLEFT | WVR_ALIGNTOP | WVR_REDRAW;
if (!m_isThemeActive) {
*result = m_isMaximized ? 0 : DefWindowProc(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
return true;
}
*result = DefWindowProc(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
params->rgrc[0].left -= m_frame.left;
params->rgrc[0].top -= m_frame.top;
params->rgrc[0].right += m_frame.left;
params->rgrc[0].bottom += m_frame.left;
if (m_isMaximized && m_isTaskbarAutoHideOn && (Utils::getWinVersion() >= WinVer::Win10))
params->rgrc[0].bottom -= 2;
return true;
}
@ -311,9 +387,9 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
SystemParametersInfoW(SPI_GETWORKAREA, 0, &workArea, 0);
if (!EqualRect(&oldWorkArea, &workArea)) {
oldWorkArea = workArea;
QTimer::singleShot(200, this, [=]() {
m_isTaskbarAutoHideOn = isTaskbarAutoHideOn();
if (Utils::getWinVersion() < WinVer::Win10)
adjustGeometry();
});
}
} else if (msg->wParam == 0) {
const std::wstring param{(wchar_t*)msg->lParam};
@ -401,20 +477,72 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
// m_allowMaximize = false;
// break;
case WM_SIZING:
if (m_borderless)
RedrawWindow(msg->hwnd, NULL, NULL, RDW_INVALIDATE | RDW_NOERASE | RDW_INTERNALPAINT);
break;
case WM_PAINT:
return false;
case WM_NCPAINT: {
if (Utils::getWinVersion() > WinVer::Win7 || !m_borderless)
break;
if (HDC hdc = ::GetDCEx(msg->hwnd, 0, DCX_WINDOW | DCX_USESTYLE)) {
RECT rcc, rcw;
::GetClientRect(msg->hwnd, &rcc);
::GetWindowRect(msg->hwnd, &rcw);
POINT pt;
pt.x = rcw.left;
pt.y = rcw.top;
::MapWindowPoints(0, msg->hwnd, (LPPOINT)&rcw, (sizeof(RECT)/sizeof(POINT)));
::OffsetRect(&rcc, -rcw.left, -rcw.top);
::OffsetRect(&rcw, -rcw.left, -rcw.top);
HRGN rgntemp = NULL;
if (msg->wParam == NULLREGION || msg->wParam == ERROR) {
::ExcludeClipRect(hdc, rcc.left, rcc.top, rcc.right, rcc.bottom);
} else {
rgntemp = ::CreateRectRgn(rcc.left + pt.x, rcc.top + pt.y, rcc.right + pt.x, rcc.bottom + pt.y);
if (::CombineRgn(rgntemp, (HRGN)msg->wParam, rgntemp, RGN_DIFF) == NULLREGION) {
// nothing to paint
}
::OffsetRgn(rgntemp, -pt.x, -pt.y);
::ExtSelectClipRgn(hdc, rgntemp, RGN_AND);
}
HBRUSH hbrushBkg = ::CreateSolidBrush(RGB(m_bkgColor.red(), m_bkgColor.green(), m_bkgColor.blue()));
::FillRect(hdc, &rcw, hbrushBkg);
::DeleteObject(hbrushBkg);
// HRGN hrgn = CreateRectRgn(0, 0, 0, 0);
// GetWindowRgn(msg->hwnd, hrgn);
HBRUSH hbrushBrd = ::CreateSolidBrush(RGB(m_brdColor.red(), m_brdColor.green(), m_brdColor.blue()));
::FrameRect(hdc, &rcw, hbrushBrd); // Drawing NC border when using ~WS_CAPTION
// ::FrameRgn(hdc, hrgn, hbrushBrd, 1, 1); // Drawing NC border when using WS_CAPTION
::DeleteObject(hbrushBrd);
// ::DeleteObject(hrgn);
::ReleaseDC(msg->hwnd, hdc);
if (rgntemp != 0)
::DeleteObject(rgntemp);
return true;
}
break;
}
case WM_ERASEBKGND:
return true;
case WM_NCACTIVATE: {
// Prevent the title bar from being drawn when the window is restored or maximized
if (m_borderless) {
if (!LOWORD(msg->wParam)) {
*result = TRUE;
break;
if (Utils::getWinVersion() > WinVer::WinXP && Utils::getWinVersion() < WinVer::Win10) {
// Prevent drawing of inactive system frame (needs ~WS_CAPTION or temporary ~WS_VISIBLE to work)
*result = DefWindowProc(msg->hwnd, WM_NCACTIVATE, msg->wParam, -1);
return true;
} else
if (Utils::getWinVersion() == WinVer::Win10) {
CWindowBase::setWindowColors(m_bkgColor, m_brdColor, LOWORD(msg->wParam));
repaint();
}
return true;
}
break;
}
@ -431,6 +559,22 @@ bool CWindowPlatform::nativeEvent(const QByteArray &eventType, void *message, lo
}
break;
case WM_GETMINMAXINFO: {
bool isMaximized = (bool)IsZoomed(msg->hwnd);
if (m_isMaximized != isMaximized) {
m_isMaximized = isMaximized;
GetFrameMetricsForDpi(m_frame, m_dpi, isMaximized);
}
break;
}
case WM_THEMECHANGED: {
bool _isThemeActive = isThemeActive();
if (m_isThemeActive != _isThemeActive)
m_isThemeActive = _isThemeActive;
break;
}
default:
break;
}

View File

@ -37,6 +37,16 @@
#include <QtWidgets/QApplication>
struct FRAME {
FRAME() : left(0), top(0)
{}
FRAME(FRAME &frame) {
left = frame.left;
top = frame.top;
}
int left, top;
};
class CWindowPlatform : public CWindowBase
{
public:
@ -59,12 +69,17 @@ private:
virtual bool nativeEvent(const QByteArray&, void*, long*) final;
QTimer *m_propertyTimer;
double m_dpi;
HWND m_hWnd;
int m_resAreaWidth;
FRAME m_frame;
bool m_borderless,
m_closed,
m_isResizeable,
// m_allowMaximize,
m_isMaximized = false,
m_isThemeActive = true,
m_isTaskbarAutoHideOn = false,
m_scaleChanged = false,
m_isSessionInProgress = true;
};