2023-12-11 23:47:03 +08:00
|
|
|
#include "FluFrameless.h"
|
|
|
|
|
|
|
|
#include <QGuiApplication>
|
|
|
|
|
2023-12-13 21:28:21 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
#pragma comment(lib, "user32.lib")
|
|
|
|
#include <windows.h>
|
|
|
|
static inline QByteArray qtNativeEventType()
|
|
|
|
{
|
|
|
|
static const auto result = "windows_generic_MSG";
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
FramelessEventFilter::FramelessEventFilter(QQuickWindow* window){
|
|
|
|
_window = window;
|
|
|
|
_current = window->winId();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FramelessEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, QT_NATIVE_EVENT_RESULT_TYPE *result){
|
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
if ((eventType != qtNativeEventType()) || !message || !result || !_window) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const auto msg = static_cast<const MSG *>(message);
|
|
|
|
const HWND hWnd = msg->hwnd;
|
|
|
|
if (!hWnd) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const qint64 wid = reinterpret_cast<qint64>(hWnd);
|
|
|
|
if(wid != _current){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const UINT uMsg = msg->message;
|
|
|
|
if (!msg || !msg->hwnd)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if(uMsg == WM_WINDOWPOSCHANGING){
|
|
|
|
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(msg->lParam);
|
|
|
|
if (wp != nullptr && (wp->flags & SWP_NOSIZE) == 0)
|
|
|
|
{
|
|
|
|
wp->flags |= SWP_NOCOPYBITS;
|
|
|
|
*result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2023-12-15 11:25:54 +08:00
|
|
|
}else if(uMsg == WM_NCCALCSIZE){
|
2023-12-15 16:04:00 +08:00
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
2023-12-15 11:25:54 +08:00
|
|
|
NCCALCSIZE_PARAMS& sz = *reinterpret_cast<NCCALCSIZE_PARAMS*>(msg->lParam);
|
|
|
|
if (sz.rgrc[0].top != 0)
|
|
|
|
sz.rgrc[0].top -= 1;
|
|
|
|
*result = WVR_REDRAW;
|
|
|
|
return true;
|
2023-12-15 16:04:00 +08:00
|
|
|
#endif
|
2023-12-13 21:28:21 +08:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
#endif
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-11 23:47:03 +08:00
|
|
|
FluFrameless::FluFrameless(QObject *parent)
|
|
|
|
: QObject{parent}
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void FluFrameless::classBegin(){
|
|
|
|
}
|
|
|
|
|
2023-12-13 16:20:09 +08:00
|
|
|
void FluFrameless::updateCursor(int edges){
|
2023-12-11 23:47:03 +08:00
|
|
|
switch (edges) {
|
|
|
|
case 0:
|
2023-12-13 23:43:01 +08:00
|
|
|
_window->setCursor(Qt::ArrowCursor);
|
2023-12-11 23:47:03 +08:00
|
|
|
break;
|
|
|
|
case Qt::LeftEdge:
|
|
|
|
case Qt::RightEdge:
|
2023-12-13 23:43:01 +08:00
|
|
|
_window->setCursor(Qt::SizeHorCursor);
|
2023-12-11 23:47:03 +08:00
|
|
|
break;
|
|
|
|
case Qt::TopEdge:
|
|
|
|
case Qt::BottomEdge:
|
2023-12-13 23:43:01 +08:00
|
|
|
_window->setCursor(Qt::SizeVerCursor);
|
2023-12-11 23:47:03 +08:00
|
|
|
break;
|
|
|
|
case Qt::LeftEdge | Qt::TopEdge:
|
|
|
|
case Qt::RightEdge | Qt::BottomEdge:
|
2023-12-13 23:43:01 +08:00
|
|
|
_window->setCursor(Qt::SizeFDiagCursor);
|
2023-12-11 23:47:03 +08:00
|
|
|
break;
|
|
|
|
case Qt::RightEdge | Qt::TopEdge:
|
|
|
|
case Qt::LeftEdge | Qt::BottomEdge:
|
2023-12-13 23:43:01 +08:00
|
|
|
_window->setCursor(Qt::SizeBDiagCursor);
|
2023-12-11 23:47:03 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool FluFrameless::eventFilter(QObject *obj, QEvent *ev){
|
2023-12-13 16:20:09 +08:00
|
|
|
if (!_window.isNull() && _window->flags()& Qt::FramelessWindowHint) {
|
|
|
|
static int edges = 0;
|
2023-12-11 23:47:03 +08:00
|
|
|
const int margin = 8;
|
|
|
|
switch (ev->type()) {
|
|
|
|
case QEvent::MouseButtonPress:
|
2023-12-13 16:20:09 +08:00
|
|
|
if(edges!=0){
|
|
|
|
updateCursor(edges);
|
|
|
|
_window->startSystemResize(Qt::Edges(edges));
|
|
|
|
}
|
2023-12-11 23:47:03 +08:00
|
|
|
break;
|
|
|
|
case QEvent::MouseButtonRelease:
|
2023-12-13 21:28:21 +08:00
|
|
|
edges = 0;
|
2023-12-11 23:47:03 +08:00
|
|
|
updateCursor(edges);
|
|
|
|
break;
|
|
|
|
case QEvent::MouseMove: {
|
2023-12-13 16:20:09 +08:00
|
|
|
if(_window->visibility() == QWindow::Maximized || _window->visibility() == QWindow::FullScreen){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(_window->width() == _window->maximumWidth() && _window->width() == _window->minimumWidth() && _window->height() == _window->maximumHeight() && _window->height() == _window->minimumHeight()){
|
|
|
|
break;
|
|
|
|
}
|
2023-12-11 23:47:03 +08:00
|
|
|
QMouseEvent *event = static_cast<QMouseEvent*>(ev);
|
|
|
|
QPoint p =
|
|
|
|
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
|
|
|
|
event->pos();
|
|
|
|
#else
|
|
|
|
event->position().toPoint();
|
|
|
|
#endif
|
2023-12-13 23:43:01 +08:00
|
|
|
if(p.x() >= margin && p.x() <= (_window->width() - margin) && p.y() >= margin && p.y() <= (_window->height() - margin)){
|
|
|
|
if(edges != 0){
|
|
|
|
edges = 0;
|
|
|
|
updateCursor(edges);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
edges = 0;
|
2023-12-11 23:47:03 +08:00
|
|
|
if ( p.x() < margin ) {
|
|
|
|
edges |= Qt::LeftEdge;
|
|
|
|
}
|
|
|
|
if ( p.x() > (_window->width() - margin) ) {
|
|
|
|
edges |= Qt::RightEdge;
|
|
|
|
}
|
|
|
|
if ( p.y() < margin ) {
|
|
|
|
edges |= Qt::TopEdge;
|
|
|
|
}
|
|
|
|
if ( p.y() > (_window->height() - margin) ) {
|
|
|
|
edges |= Qt::BottomEdge;
|
|
|
|
}
|
|
|
|
updateCursor(edges);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return QObject::eventFilter(obj, ev);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FluFrameless::componentComplete(){
|
|
|
|
auto o = parent();
|
|
|
|
while (nullptr != o) {
|
|
|
|
_window = (QQuickWindow*)o;
|
|
|
|
o = o->parent();
|
|
|
|
}
|
|
|
|
if(!_window.isNull()){
|
|
|
|
_window->setFlag(Qt::FramelessWindowHint,true);
|
|
|
|
_window->installEventFilter(this);
|
2023-12-13 21:28:21 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
_nativeEvent =new FramelessEventFilter(_window);
|
|
|
|
qApp->installNativeEventFilter(_nativeEvent);
|
2023-12-13 23:43:01 +08:00
|
|
|
HWND hWnd = reinterpret_cast<HWND>(_window->winId());
|
|
|
|
ULONG_PTR cNewStyle = GetClassLongPtr(hWnd, GCL_STYLE) | CS_DROPSHADOW;
|
|
|
|
SetClassLongPtr(hWnd, GCL_STYLE, cNewStyle);
|
2023-12-15 16:04:00 +08:00
|
|
|
SetWindowPos(hWnd,nullptr,0,0,0,0,SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE |SWP_FRAMECHANGED);
|
2023-12-13 21:28:21 +08:00
|
|
|
#endif
|
2023-12-11 23:47:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FluFrameless::~FluFrameless(){
|
|
|
|
if (!_window.isNull()) {
|
|
|
|
_window->setFlag(Qt::FramelessWindowHint,false);
|
2023-12-13 16:20:09 +08:00
|
|
|
_window->removeEventFilter(this);
|
2023-12-13 21:28:21 +08:00
|
|
|
#ifdef Q_OS_WIN
|
|
|
|
qApp->removeNativeEventFilter(_nativeEvent);
|
|
|
|
#endif
|
2023-12-11 23:47:03 +08:00
|
|
|
}
|
|
|
|
}
|