Qt--無邊框窗口完美(FrameLess)實現,包含縮放和移動功能重寫。

前言

  1. Qt原本的窗口雖然可以通過QSS樣式進行美化,但是隻是對客戶區有用,對於客戶區是無效的。所以想做出一個比較好看的程序,還得自己重寫實現無邊框窗口。
  2. Qt實現無邊框其實一句代碼就可以,但是窗口自帶的縮放,移動功和關閉功能都會沒有,需要自己重寫。
    setWindowFlags(Qt::FramelessWindowHint);

重寫無邊框窗口

1.效果如下

2.由於無邊框窗口沒有了標題欄和最小化,最大化,關閉的按鈕,所以需要自己佈局相對應的控件,並重寫事件。我的佈局如下

3.事件對應代碼

展開
//窗口關閉事件
void MainWindow::windowClose()
{
    qApp->exit();
}

//窗口最小化
void MainWindow::windowMin()
{
    this->showMinimized();
}
//窗口最大化
void MainWindow::windowMax()
{
    isMaxWin=!isMaxWin; 
    if(isMaxWin)    //根據是否最大化窗口,改變對應的圖標
    {
        ui->btnMax->setIcon(QIcon(":/icons/normal.png"));
        this->showMaximized();
    }
    else
    {
        ui->btnMax->setIcon(QIcon(":/icons/maxsize.png"));
        this->showNormal();
    }
}
4.窗口移動事件,需要重寫鼠標的點擊事件和移動事件
展開
void MainWindow::mousePressEvent(QMouseEvent*event)
{
    if(event->button()==Qt::LeftButton) //如果鼠標左鍵按下
    {
        isPressed=true;         
        curPos=event->pos();    //記錄當前的點擊座標
    }
}

void MainWindow::mouseMoveEvent(QMouseEvent*event)
{
    if(isPressed) //如果鼠標左鍵按下           
    {
        this->move(event->pos()-curPos+this->pos());    //窗口移動
    }
}

//鼠標釋放
void MainWindow::mouseReleaseEvent(QMouseEvent*event)
{
    isPressed=false;    
}

3.窗口的縮放功能比較麻煩,需要用到windows的消息機制.代碼如下
展開
//需要包含頭文件
/*
    #include <qt_windows.h>
    #include <Windowsx.h>
*/
//消息處理
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
    int m_nBorder = 5;  //邊界寬度
    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();


        *result = HTCAPTION;

        //判斷鼠標位置是否位於窗口邊界
        if ((nX > 0) && (nX < m_nBorder))
            *result = HTLEFT;

        if ((nX > this->width() - m_nBorder) && (nX < this->width()))
            *result = HTRIGHT;

        if ((nY > 0) && (nY < m_nBorder))
            *result = HTTOP;

        if ((nY > this->height() - m_nBorder) && (nY < this->height()))
            *result = HTBOTTOM;

        if ((nX > 0) && (nX < m_nBorder) && (nY > 0)
                && (nY < m_nBorder))
            *result = HTTOPLEFT;

        if ((nX > this->width() - m_nBorder) && (nX < this->width())
                && (nY > 0) && (nY < m_nBorder))
            *result = HTTOPRIGHT;

        if ((nX > 0) && (nX < m_nBorder)
                && (nY > this->height() - m_nBorder) && (nY < this->height()))
            *result = HTBOTTOMLEFT;

        if ((nX > this->width() - m_nBorder) && (nX < this->width())
                && (nY > this->height() - m_nBorder) && (nY < this->height()))
            *result = HTBOTTOMRIGHT;

        if (*result == HTCAPTION)
        {
            return false;
        }
        return true;
    }
    }
    return QMainWindow::nativeEvent(eventType, message, result);
}

4.要實現窗口的正常功能,還需要對窗口的Flags進行一些設置,同時也要給父類設置,要不然會有問題的.

其中 Qt::FramelessWindowHint設置窗口爲無邊框,Qt::Window表示widegt爲窗口,Qt::WindowMinimizeButtonHint 程序在任務欄被點擊時能夠顯示/隱藏.

一些問題

1.把以上那些功能實現了,無邊框窗口基本可以用了,至於如何用Qss美化,界面如何佈局,那就看每個人了,反正可以自己進行定製
2.由於用到了windows下的消息機制,所以該實現只適用於Windows系統.雖然我在GitHub上找到不少可以跨平臺的無邊框窗口實現,但是都不是很完美,有興趣的自己可以去GitHub上去看看.
3.目前的實現方法都會有一些問題,沒有原本的好,但基本不影響使用,如果有需要自己也可以進行優化,所以問題不大.

完整項目代碼

github: QtFrameLess

星期五女孩

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章