赞
踩
删除qt自带的菜单栏
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
标题栏从左到右分别是
图标(粉色),标题栏标题(红色), 最小化, 最大化, 关闭;
标题栏从左到右类型分别是
QLabel,QLabel,QPushButton,QPushButton,QPushButton;
标题栏从左到右名字分别是m_pIconLabel,m_pTitleLabel,m_pMinimizeButton,m_pMaximizeButton,m_pCloseButton
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QLabel> #include <QPushButton> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); protected: //双击标题栏进行界面的最大化/还原 virtual void mouseDoubleClickEvent(QMouseEvent *event); //进行界面的拖动 virtual void mousePressEvent(QMouseEvent *event); //设置界面标题与图标 virtual bool eventFilter(QObject *obj, QEvent *event); private: //最大化/还原 void updateMaximize(); private slots: bool nativeEvent(const QByteArray &eventType, void *message, long *result); //进行最小化、最大化/还原、关闭操作 void onClicked(); private: Ui::Widget *ui; int m_nBorderWidth; //m_nBorder表示鼠标位于边框缩放范围的宽度 }; #endif // WIDGET_H
#include "widget.h" #include "ui_widget.h" #include <QEvent> #include <QMouseEvent> #include <QLabel> #include <QPushButton> //调用WIN API需要用到的头文件与库 #ifdef Q_OS_WIN #pragma comment(lib, "user32.lib") #include <qt_windows.h> #include <Windowsx.h> #endif Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); //Qt::FramelessWindowHint设置窗口标志为无边框,而Qt::WindowStaysOnTopHint使窗口位于所有界面之上 this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); //连接三个按钮的信号槽 connect(ui->m_pMinimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(ui->m_pMaximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); connect(ui->m_pCloseButton, SIGNAL(clicked(bool)), this, SLOT(onClicked())); //m_nBorder表示鼠标位于边框缩放范围的宽度,可以设置为5 m_nBorderWidth=5; } Widget::~Widget() { delete ui; } //nativeEvent主要用于进程间通信-消息传递,使用这种方式后来实现窗体的缩放 [加上了这函数,窗口也能移动了] bool Widget::nativeEvent(const QByteArray &eventType, void *message, long *result) { Q_UNUSED(eventType) MSG *param = static_cast<MSG *>(message); switch (param->message) { case WM_NCHITTEST: { int nX = GET_X_LPARAM(param->lParam) - this->geometry().x(); int nY = GET_Y_LPARAM(param->lParam) - this->geometry().y(); // 如果鼠标位于子控件上,则不进行处理 if (childAt(nX, nY) != nullptr) return QWidget::nativeEvent(eventType, message, result); *result = HTCAPTION; // 鼠标区域位于窗体边框,进行缩放 if ((nX > 0) && (nX < m_nBorderWidth)) *result = HTLEFT; if ((nX > this->width() - m_nBorderWidth) && (nX < this->width())) *result = HTRIGHT; if ((nY > 0) && (nY < m_nBorderWidth)) *result = HTTOP; if ((nY > this->height() - m_nBorderWidth) && (nY < this->height())) *result = HTBOTTOM; if ((nX > 0) && (nX < m_nBorderWidth) && (nY > 0) && (nY < m_nBorderWidth)) *result = HTTOPLEFT; if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()) && (nY > 0) && (nY < m_nBorderWidth)) *result = HTTOPRIGHT; if ((nX > 0) && (nX < m_nBorderWidth) && (nY > this->height() - m_nBorderWidth) && (nY < this->height())) *result = HTBOTTOMLEFT; if ((nX > this->width() - m_nBorderWidth) && (nX < this->width()) && (nY > this->height() - m_nBorderWidth) && (nY < this->height())) *result = HTBOTTOMRIGHT; return true; } } return QWidget::nativeEvent(eventType, message, result); } //双击标题栏进行界面的最大化/还原 void Widget::mouseDoubleClickEvent(QMouseEvent *event) { Q_UNUSED(event); //没有实质性的作用,只是用来允许event可以不使用,用来避免编译器警告 emit ui->m_pMaximizeButton->clicked(); } //进行界面的拖动 [一般情况下,是界面随着标题栏的移动而移动,所以我们将事件写在标题栏中比较合理] void Widget::mousePressEvent(QMouseEvent *event) { #ifdef Q_OS_WIN if (ReleaseCapture()) { QWidget *pWindow = this->window(); if (pWindow->isTopLevel()) { SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); } } event->ignore(); #else #endif } //使用事件过滤器监听标题栏所在的窗体,所以当窗体标题、图标等信息发生改变时,标题栏也应该随之改变 bool Widget::eventFilter(QObject *obj, QEvent *event) { switch ( event->type() ) //判断发生事件的类型 { case QEvent::WindowTitleChange: //窗口标题改变事件 { QWidget *pWidget = qobject_cast<QWidget *>(obj); //获得发生事件的窗口对象 if (pWidget) { //窗体标题改变,则标题栏标题也随之改变 ui->m_pTitleLabel->setText(pWidget->windowTitle()); return true; } } break; case QEvent::WindowIconChange: //窗口图标改变事件 { QWidget *pWidget = qobject_cast<QWidget *>(obj); if (pWidget) { //窗体图标改变,则标题栏图标也随之改变 QIcon icon = pWidget->windowIcon(); ui->m_pIconLabel->setPixmap(icon.pixmap(ui->m_pIconLabel->size())); return true; } } break; case QEvent::Resize: updateMaximize(); //最大化/还原 return true; default: return QWidget::eventFilter(obj, event); } return QWidget::eventFilter(obj, event); } //进行最小化、最大化/还原、关闭操作 void Widget::onClicked() { //QObject::Sender()返回发送信号的对象的指针,返回类型为QObject * QPushButton *pButton = qobject_cast<QPushButton *>(sender()); QWidget *pWindow = this->window(); //获得标题栏所在的窗口 if (pWindow->isTopLevel()) { //判断发送信号的对象使哪个按钮 if (pButton == ui->m_pMinimizeButton) { pWindow->showMinimized(); //窗口最小化显示 } else if (pButton == ui->m_pMaximizeButton) { pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized(); //窗口最大化/还原显示 } else if (pButton == ui->m_pCloseButton) { pWindow->close(); //窗口关闭 } } } //最大化/还原 void Widget::updateMaximize() { QWidget *pWindow = this->window(); //获得标题栏所在的窗口 if (pWindow->isTopLevel()) { bool bMaximize = pWindow->isMaximized(); //判断窗口是不是最大化状态,是则返回true,否则返回false if (bMaximize) { //目前窗口是最大化状态,则最大化/还原的toolTip设置为"Restore" ui->m_pMaximizeButton->setToolTip(tr("Restore")); //设置按钮的属性名为"maximizeProperty" ui->m_pMaximizeButton->setProperty("maximizeProperty", "restore"); } else { //目前窗口是还原状态,则最大化/还原的toolTip设置为"Maximize" ui->m_pMaximizeButton->setToolTip(tr("Maximize")); //设置按钮的属性名为"maximizeProperty" ui->m_pMaximizeButton->setProperty("maximizeProperty", "maximize"); } ui->m_pMaximizeButton->setStyle(QApplication::style()); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。