专业网专业网站建设,销售管理系统哪家好,织梦在线考试网站模板,李青青做网站 公司主要做应用领域本篇博客介绍C Qt QMainWindow实现无边框窗口#xff0c;适用于win10/win11系统。
QMainWindow相对于QWidget多了dockedwidget功能#xff0c;跟多人可能更喜欢用QMainWindow做主窗口#xff0c;如果不需要dockedwidget功能#xff0c;QMainWindow与QWidget做主窗口基本无…本篇博客介绍C Qt QMainWindow实现无边框窗口适用于win10/win11系统。
QMainWindow相对于QWidget多了dockedwidget功能跟多人可能更喜欢用QMainWindow做主窗口如果不需要dockedwidget功能QMainWindow与QWidget做主窗口基本无差别。
效果图如下 自带窗口阴影、圆角、可拉伸拖拽。
具体实现过程如下
一、编写无边框窗口基类CFramelessWindowBase
CFramelessWindowBase.h
/*QMainWindow无边框窗口基类可拉伸其它QMainWindow窗口派生于该类即可*/#pragma once
#include QMainWindowclass CFramelessWindowBase : public QMainWindow
{
public:CFramelessWindowBase(QWidget* parent nullptr);~CFramelessWindowBase();protected:bool nativeEvent(const QByteArray eventType, void* message, long* result) override;private:int mouse_margin 5;
};CFramelessWindowBase.cpp
#include CFramelessWindowBase.h
#include qt_windows.h
#include windowsx.h
#include QWindow
#include windows.h
#include dwmapi.h#pragma comment(lib, dwmapi.lib)CFramelessWindowBase::CFramelessWindowBase(QWidget* parent): QMainWindow(parent)
{setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);setAttribute(Qt::WA_Hover);// 添加窗口阴影窗口圆角HWND hWnd reinterpret_castHWND(winId());DWMNCRENDERINGPOLICY ncrp DWMNCRP_ENABLED;::DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, ncrp, sizeof(ncrp));MARGINS shadow { 1, 1, 1, 1 };DwmExtendFrameIntoClientArea((HWND)winId(), shadow);
}CFramelessWindowBase::~CFramelessWindowBase()
{
}bool CFramelessWindowBase::nativeEvent(const QByteArray eventType, void* message, long* result)
{MSG* msg static_castMSG*(message);switch (msg-message){case WM_NCHITTEST:{QPoint globalPos QCursor::pos();int x globalPos.x();int y globalPos.y();//int nX GET_X_LPARAM(param-lParam) - this-geometry().x(); // bug : windows 在高分屏下坐标值不正确//int nY GET_Y_LPARAM(param-lParam) - this-geometry().y();int nX x - this-geometry().x();int nY y - this-geometry().y();// 如果鼠标位于内部子控件上则不进行处理if (nX mouse_margin nX width() - mouse_margin nY mouse_margin nY this-height() - mouse_margin){if (childAt(nX, nY) ! nullptr)return QWidget::nativeEvent(eventType, message, result);}// 鼠标区域位于窗体边框进行缩放if ((nX 0) (nX mouse_margin))*result HTLEFT;if ((nX this-width() - mouse_margin) (nX this-width()))*result HTRIGHT;if ((nY 0) (nY mouse_margin))*result HTTOP;if ((nY this-height() - mouse_margin) (nY this-height()))*result HTBOTTOM;if ((nX 0) (nX mouse_margin) (nY 0) (nY mouse_margin))*result HTTOPLEFT;if ((nX this-width() - mouse_margin) (nX this-width()) (nY 0) (nY mouse_margin))*result HTTOPRIGHT;if ((nX 0) (nX mouse_margin) (nY this-height() - mouse_margin) (nY this-height()))*result HTBOTTOMLEFT;if ((nX this-width() - mouse_margin) (nX this-width()) (nY this-height() - mouse_margin) (nY this-height()))*result HTBOTTOMRIGHT;return true;}}return QWidget::nativeEvent(eventType, message, result);
}代码解释 1在CFramelessWindowBase类设置窗口标志去掉窗口边框设置最大最小显示效果。
setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);2增加windows窗口阴影与圆角
// 添加窗口阴影窗口圆角
HWND hWnd reinterpret_castHWND(winId());
DWMNCRENDERINGPOLICY ncrp DWMNCRP_ENABLED;
::DwmSetWindowAttribute(hWnd, DWMWA_NCRENDERING_POLICY, ncrp, sizeof(ncrp));
MARGINS shadow { 1, 1, 1, 1 };
DwmExtendFrameIntoClientArea((HWND)winId(), shadow);这里使用的是DWM API实现窗口阴影和圆角圆角是windows窗口的圆角不需要手动设置圆角大小。 3重写nativeEvent实现无边框窗口
bool CFramelessWindowBase::nativeEvent(const QByteArray eventType, void* message, long* result)
{MSG* msg static_castMSG*(message);switch (msg-message){case WM_NCHITTEST:{QPoint globalPos QCursor::pos();int x globalPos.x();int y globalPos.y();//int nX GET_X_LPARAM(param-lParam) - this-geometry().x(); // bug : windows 在高分屏下坐标值不正确//int nY GET_Y_LPARAM(param-lParam) - this-geometry().y();int nX x - this-geometry().x();int nY y - this-geometry().y();// 如果鼠标位于内部子控件上则不进行处理if (nX mouse_margin nX width() - mouse_margin nY mouse_margin nY this-height() - mouse_margin){if (childAt(nX, nY) ! nullptr)return QWidget::nativeEvent(eventType, message, result);}// 鼠标区域位于窗体边框进行缩放if ((nX 0) (nX mouse_margin))*result HTLEFT;if ((nX this-width() - mouse_margin) (nX this-width()))*result HTRIGHT;if ((nY 0) (nY mouse_margin))*result HTTOP;if ((nY this-height() - mouse_margin) (nY this-height()))*result HTBOTTOM;if ((nX 0) (nX mouse_margin) (nY 0) (nY mouse_margin))*result HTTOPLEFT;if ((nX this-width() - mouse_margin) (nX this-width()) (nY 0) (nY mouse_margin))*result HTTOPRIGHT;if ((nX 0) (nX mouse_margin) (nY this-height() - mouse_margin) (nY this-height()))*result HTBOTTOMLEFT;if ((nX this-width() - mouse_margin) (nX this-width()) (nY this-height() - mouse_margin) (nY this-height()))*result HTBOTTOMRIGHT;return true;}}return QWidget::nativeEvent(eventType, message, result);
}二、实现主窗口 派生于上面的CFramelessWindowBase代码如下 FramelessWindow.h
#pragma once#include QtWidgets/QMainWindow
#include CFramelessWindowBase.h
#include TitleBar.h
#include ContentWidget.h
#include LeftBar.h
#include CustomStatusBar.hclass FramelessWindow : public CFramelessWindowBase
{Q_OBJECTpublic:FramelessWindow(QWidget *parent nullptr);~FramelessWindow();private slots:void OnClose();private:TitleBar* m_pTitleBar nullptr;ContentWidget* m_pContentWidget nullptr;LeftBar* m_pLeftBar nullptr;CustomStatusBar* m_pStatusBar nullptr;
};FramelessWindow.cpp
/*主窗口*/#include FramelessWindow.h
#include QVBoxLayout
#include QMessageBoxFramelessWindow::FramelessWindow(QWidget *parent): CFramelessWindowBase(parent)
{this-resize(800, 600);QWidget* pWidget new QWidget(this);this-setCentralWidget(pWidget);m_pTitleBar new TitleBar(pWidget);m_pTitleBar-SetTitleText(tr(QMainWindow Custom Title));QString logo_qss R(QLabel{background-image:url(:/TitleBar/Resources/TitleBar/logo32.svg);background-position:center; background-repeat: no-repeat;border:none});m_pTitleBar-SetTitleIcon(logo_qss);m_pContentWidget new ContentWidget(pWidget);m_pLeftBar new LeftBar(pWidget);m_pStatusBar new CustomStatusBar(pWidget);QVBoxLayout* pVLay new QVBoxLayout(pWidget);pVLay-setSpacing(0);pVLay-setContentsMargins(0, 0, 0, 0);pVLay-addWidget(m_pTitleBar);QHBoxLayout* pHLay new QHBoxLayout(pWidget);pHLay-setSpacing(0);pHLay-addWidget(m_pLeftBar);pHLay-addWidget(m_pContentWidget);pVLay-addLayout(pHLay);pVLay-addWidget(m_pStatusBar);pWidget-setLayout(pVLay);connect(m_pTitleBar, TitleBar::sig_Close, this, FramelessWindow::OnClose);
}FramelessWindow::~FramelessWindow()
{
}void FramelessWindow::OnClose()
{QMessageBox::StandardButton resBtn QMessageBox::question(this, tr(Tips),tr(Are you sure you want to close the window?),QMessageBox::Cancel | QMessageBox::Yes,QMessageBox::Yes);if (resBtn QMessageBox::Yes) {close();}
}本篇博客源码下载 https://download.csdn.net/download/yao_hou/89211306?spm1001.2014.3001.5501