有些窗口在自身最小化時要在桌面上顯示一個小浮標,讓用戶利用這個小浮標進行各種操作(例如迅雷的懸浮窗一樣),我試著用QT實現一下這個功能。
PS:本來以為這個功能很簡單,卻搞了我兩個晚上,淚奔。。。
思路:
1:制作一個由一個小圖標組成的,可點擊,可拖動,背景透明的Widget
2:重載主窗口(在此例子中是QLabel)的changeEvent(詳情見代碼)
截圖:(淺綠色的部分是桌面背景)
主窗體:
小浮標:
代碼:
- #include <QtGui>
- #include <Windows.h>
-
- //
- class MinIconWidget : public QWidget
- {
- Q_OBJECT
- private:
- QPoint m_CurrentPos;
- QPixmap m_Pixmap;
- protected:
- void mousePressEvent(QMouseEvent *event);
- void mouseMoveEvent(QMouseEvent *event);
- void paintEvent(QPaintEvent *event);
- void enterEvent(QEvent *event);
- void leaveEvent(QEvent *event);
- void mouseDoubleClickEvent(QMouseEvent *event);
- public:
- MinIconWidget(QWidget *parent = 0);
- void SetPixmap(const QPixmap &pixmap);
- signals:
- void DoubleClickedSignal();
- };
-
- MinIconWidget::MinIconWidget(QWidget *parent)
- : QWidget(parent)
- {
- //將浮標Widget設置為:頂層窗口;無標題欄;工具條模式;背景透明;無輸入焦點
- setWindowFlags( Qt::FramelessWindowHint
- | Qt::WindowStaysOnTopHint | Qt::Tool );
- setAttribute(Qt::WA_TranslucentBackground, true);
- setFocusPolicy(Qt::NoFocus);
- }
-
- void MinIconWidget::mousePressEvent(QMouseEvent *event)
- {
- //按住左鍵移動可以拖動窗口
- if(event->button() == Qt::LeftButton)
- {
- m_CurrentPos = event->globalPos() - frameGeometry().topLeft();
- event->accept();
- }
- }
-
- void MinIconWidget::mouseMoveEvent(QMouseEvent *event)
- {
- if (event->buttons() && Qt::LeftButton)
- {
- move(event->globalPos() - m_CurrentPos);
- event->accept();
- }
- }
-
- void MinIconWidget::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- painter.drawPixmap(0, 0, m_Pixmap);
- }
-
- void MinIconWidget::leaveEvent(QEvent *event)
- {
- //鼠標離開窗口時是普通的指針
- setCursor(Qt::ArrowCursor);
- }
-
- void MinIconWidget::enterEvent(QEvent *event)
- {
- //鼠標留在窗口上時是一個手指
- setCursor(Qt::PointingHandCursor);
- }
-
- void MinIconWidget::mouseDoubleClickEvent(QMouseEvent *event)
- {
- emit DoubleClickedSignal();
- }
-
- void MinIconWidget::SetPixmap(const QPixmap &pixmap)
- {
- m_Pixmap = pixmap;
- update();
- }
-
-
- class MyLabel : public QLabel
- {
- Q_OBJECT
- private:
- MinIconWidget *m_minIcon;
- protected:
- void changeEvent(QEvent *event);
- public:
- MyLabel(QWidget *parent = 0);
- public slots:
- void ShowMainWindow();
- void HideMainWindow();
- };
-
- MyLabel::MyLabel(QWidget *parent /* = 0 */)
- : QLabel(parent)
- {
-
- m_minIcon = new MinIconWidget;
- m_minIcon->SetPixmap( QPixmap("delete.png") );
- setWindowFlags( Qt::WindowStaysOnTopHint );
- //雙擊浮動時,隱藏浮標,還原主窗口(這裡是一個LABEL)
- connect(m_minIcon, SIGNAL(DoubleClickedSignal()), this, SLOT(ShowMainWindow()));
- }
-
- void MyLabel::changeEvent(QEvent *event)
- {
- //重點,窗口最小化時最小化窗口(廢話),顯示浮標
- //窗口還原時,隱藏浮標,還原主窗口(這裡是一個LABEL)
- if(event->type()==QEvent::WindowStateChange)
- {
- //changeEvent會在窗口最小化之前調用,如果不加QTimer,
- //我們把窗口隱藏了,但是Qt還以為窗口正要最小化,這樣就會出錯
- if(windowState() & Qt::WindowMinimized)
- QTimer::singleShot(0, this, SLOT(HideMainWindow()));
- else if(windowState() & Qt::WindowNoState)
- QTimer::singleShot(0, this, SLOT(ShowMainWindow()));
- }
- QLabel::changeEvent(event);
- }
-
- void MyLabel::ShowMainWindow()
- {
- m_minIcon->hide();
- move( m_minIcon->pos() );
- show();
- setWindowState(Qt::WindowNoState);
- }
-
- void MyLabel::HideMainWindow()
- {
- hide();
- m_minIcon->move( pos() );
- m_minIcon->show();
- setWindowState(Qt::WindowMinimized);
- }
-
-
- #include "main.moc"
-
- int main(int argc, char **argv)
- {
- QApplication app(argc, argv);
- MyLabel label;
- label.setStyleSheet("QLabel{font-size:30px;color:red;}");
- label.resize(400, 200);
- label.setText("This is a simple demo.");
- label.show();
- return app.exec();
- }