不同于Qt::CustomizeWindowHint,本例去除了Qt::CustomizeWindowHint状态下顶部的那一小部分边框,并且保留了功能
效果:
实现:
.h文件
#ifndef FRAMELESSWIDGET_H
#define FRAMELESSWIDGET_H
#include <QWidget>
#include <dwmapi.h>//添加阴影需要用到的系统库
class FramelessWidget : public QWidget
{
Q_OBJECT
public:
explicit FramelessWidget(QWidget *parent = 0);
protected:
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result);
private:
//边距
int padding;
HWND hwnd;
//标题栏控件
QWidget *titleBar;
Qt::WindowFlags flags;
public Q_SLOTS:
//设置标题栏控件
void setTitleBar(QWidget *titleBar);
};
#endif // FRAMELESSWIDGET_H
记得在pro文件引入dwmapi的库(不知道为什么ide会自动补全但是编译就显示不认识里面函数,估计是没有链接dll文件)
右击项目->添加库->外部库加进去就行
.cpp
#include "framelesswidget.h"
#include "qdatetime.h"
#include "qevent.h"
#include "qdebug.h"
#include "windows.h"
#include "windowsx.h"
#pragma comment (lib,"user32.lib")
FramelessWidget::FramelessWidget(QWidget *parent) : QWidget(parent)
{
padding = 8;
flags = this->windowFlags();
titleBar = 0;
this->setWindowFlags(flags | Qt::FramelessWindowHint);
hwnd = (HWND)this->winId();
DWORD style = ::GetWindowLong(hwnd, GWL_STYLE);
//设置窗口样式
SetWindowLong(hwnd, GWL_STYLE, style|WS_MAXIMIZEBOX | WS_THICKFRAME|WS_CAPTION);
//添加阴影
MARGINS margins = {-1,-1,-1,-1};
DwmExtendFrameIntoClientArea(hwnd, &margins);
}
bool FramelessWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
{
if (eventType == "windows_generic_MSG")
{
MSG *msg = static_cast<MSG *>(message);
//不同的消息类型和参数进行不同的处理
if (msg->message == WM_NCCALCSIZE)
{
*result = 0;
return true;
}
else if (msg->message == WM_SYSKEYDOWN)
{
//屏蔽alt键按下
}
else if (msg->message == WM_SYSKEYUP)
{
//屏蔽alt键松开
}
else if (msg->message == WM_NCHITTEST)
{
long x = GET_X_LPARAM(msg->lParam);
long y = GET_Y_LPARAM(msg->lParam);
QPoint cursorpos(x,y);
//注意屏幕缩放的问题
qreal scales=QGuiApplication::primaryScreen()->devicePixelRatio();
cursorpos/=scales;
QPoint pos=mapFromGlobal(cursorpos);
//判断当前鼠标位置在哪个区域
bool left = pos.x() < padding;
bool right = pos.x() > width() - padding;
bool top = pos.y() < padding;
bool bottom = pos.y() > height() - padding;
//鼠标移动到四个角,这个消息是当鼠标移动或者有鼠标键按下时候发出的
*result = 0;
if (left && top) {
*result = HTTOPLEFT;
} else if (left && bottom) {
*result = HTBOTTOMLEFT;
} else if (right && top) {
*result = HTTOPRIGHT;
} else if (right && bottom) {
*result = HTBOTTOMRIGHT;
} else if (left) {
*result = HTLEFT;
} else if (right) {
*result = HTRIGHT;
} else if (top) {
*result = HTTOP;
} else if (bottom) {
*result = HTBOTTOM;
}
//先处理掉拉伸
if (0 != *result) {
return true;
}
//识别标题栏拖动产生半屏全屏效果
if (titleBar && titleBar->rect().contains(pos)) {
QWidget *child = titleBar->childAt(pos);
if (!child)
{
*result = HTCAPTION;
return true;
}
}
}
else if (msg->wParam == PBT_APMSUSPEND && msg->message == WM_POWERBROADCAST)
{
//系统休眠的时候自动最小化可以规避程序可能出现的问题
this->showMinimized();
}
else if (msg->wParam == PBT_APMRESUMEAUTOMATIC)
{
//休眠唤醒后自动打开
this->showNormal();
}
}
return false;
}
//用于拖拽程序的区域
void FramelessWidget::setTitleBar(QWidget *titleBar)
{
this->titleBar = titleBar;
this->titleBar->installEventFilter(this);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。