
具体效果如上图:
实现方法:
1.使用windows HOOK,获取全局鼠标位置,通过信号传递给qwidget调整窗口位置
2.设置鼠标事件穿透,屏蔽窗口的点击事件
3.绘制半透明背景色
4.使用windows hook将鼠标的点击事件,通过qt信号槽函数传递给窗口,实时更换点击时背景色
5.不显示状态栏图标,使用小图标退出程序
1. hookutil.h
- // MIT License
-
- // Copyright (c) 2022 hooy
-
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
-
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
-
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
-
- #ifndef HOOKUTIL_H
- #define HOOKUTIL_H
-
- #ifdef _WIN32
- #include <windows.h>
- #endif
-
- int startMouseHook();
-
- bool stopMouseHook();
-
- #endif // HOOKUTIL_H
2. hoolutil.cpp
- // MIT License
-
- // Copyright (c) 2022 hooy
-
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
-
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
-
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
-
- #include "hookutil.h"
- #include <mousehistory.h>
- #include <QDebug>
-
- static HHOOK hMouseHook = NULL;
-
- HMODULE ModuleFromAddress(PVOID pv)
- {
- MEMORY_BASIC_INFORMATION mbi;
- if (VirtualQuery(pv, &mbi, sizeof(mbi)) != 0)
- {
- return (HMODULE)mbi.AllocationBase;
- }
- else
- {
- return NULL;
- }
- }
-
- bool stopMouseHook()
- {
- if (hMouseHook == NULL)
- {
- return FALSE;
- }
- UnhookWindowsHookEx(hMouseHook);
- hMouseHook = NULL;
- return TRUE;
- }
- LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam)
- {
- if(HC_ACTION == nCode){
- if (WM_LBUTTONDOWN == wParam || WM_RBUTTONDOWN == wParam
- || WM_MBUTTONDOWN == wParam)
- {
- if (MouseHistory::instance())
- {
- MouseHistory::instance()->setPressEvent(1);
- }
- }
-
- if (WM_LBUTTONUP == wParam || WM_RBUTTONUP == wParam
- || WM_MBUTTONUP == wParam)
- {
- if (MouseHistory::instance())
- {
- MouseHistory::instance()->setPressEvent(2);
- }
- }
-
-
- if (MouseHistory::instance())
- {
- PMSLLHOOKSTRUCT p = (PMSLLHOOKSTRUCT)lParam;
- MouseHistory::instance()->setPosValue(p->pt.x, p->pt.y);
- }
- }
- return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
- }
-
- BOOL startMouseHook()
- {
- if (hMouseHook != NULL)
- {
- return FALSE;
- }
- hMouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseProc, ModuleFromAddress((PVOID)MouseProc), NULL);
- if (NULL == hMouseHook)
- {
- qDebug() << "regiter hook for mouse failed";
- return FALSE;
- }
- return TRUE;
- }
3. mainwindow.h
- // MIT License
-
- // Copyright (c) 2022 hooy
-
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
-
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
-
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
-
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
-
- #include <QMainWindow>
- #include <QPaintEvent>
- #include <QMouseEvent>
-
- class QSystemTrayIcon;
- class QMenu;
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class MainWindow; }
- QT_END_NAMESPACE
-
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
- MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
-
- protected:
- void paintEvent(QPaintEvent *event);
-
- private:
- void InitTrayIcon();
-
- private:
- Ui::MainWindow *ui;
-
- QSystemTrayIcon *_trayIcon{nullptr};
- QMenu *_trayMenu{nullptr};
-
- //鼠标点击事件
- bool pressed_{false};
- };
- #endif // MAINWINDOW_H
4. mainwindow.cpp
- // MIT License
-
- // Copyright (c) 2022 hooy
-
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
-
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
-
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
-
- #include "mainwindow.h"
- #include "./ui_mainwindow.h"
- #include <hookutil.h>
- #include <mousehistory.h>
- #include <QPainter>
- #include <QDebug>
- #include <QMenu>
- #include <QSystemTrayIcon>
-
- MainWindow::MainWindow(QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
-
- InitTrayIcon();
-
- setAttribute(Qt::WA_TransparentForMouseEvents, true);
- setFixedSize(QSize(50,50));
- setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::SplashScreen);
- setAttribute(Qt::WA_TranslucentBackground, true);
-
- connect(MouseHistory::instance(), &MouseHistory::getPos, [=](long x, long y){
- move(x-25, y-25);
- });
-
- connect(MouseHistory::instance(), &MouseHistory::getPress, [=](int key){
- if(key == 1)
- pressed_ = true;
- else{
- pressed_ = false;
- }
- update();
- });
-
- startMouseHook();
- }
-
- void MainWindow::InitTrayIcon()
- {
- _trayIcon = new QSystemTrayIcon(this);
- _trayIcon->setIcon(QIcon(":/res/cat.ico"));
- _trayIcon->setToolTip("Shallow");
- _trayMenu = new QMenu(this);
- // _trayMenu->addAction(tr("显示Shallow窗口"),this,[=](){
- // this->show();
- // this->activateWindow();
- // });
- _trayMenu->addAction(tr("退出Shallow"),this,[=](){
- qApp->quit();
- });
- _trayIcon->setContextMenu(_trayMenu);
- _trayIcon->show();
- }
-
-
- void MainWindow::paintEvent(QPaintEvent *event)
- {
- QPainter painter(this);
- if(pressed_){
- painter.setBrush(QColor(255,200,200,100));
- }
- else{
- painter.setBrush(QColor(125,125,125,100));
- }
- painter.setPen(Qt::NoPen);
- painter.setRenderHint(QPainter::Antialiasing, true);
- painter.save();
- painter.drawEllipse(QPoint(this->rect().left()+25, this->rect().top()+25), 25, 25);
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- stopMouseHook();
- }
-
5. mousehistory.h
- // MIT License
-
- // Copyright (c) 2022 hooy
-
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
-
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
-
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
-
- #ifndef MOUSEHISTORY_H
- #define MOUSEHISTORY_H
-
- #include <QObject>
-
- class MouseHistory : public QObject
- {
- Q_OBJECT
- public:
- MouseHistory(QObject* parent = nullptr):QObject(parent){}
- virtual ~MouseHistory(){}
- static MouseHistory *&instance()
- {
- static MouseHistory *s = nullptr;
- if (s == nullptr)
- {
- s = new MouseHistory();
- }
- return s;
- }
-
- public:
- void setPosValue(long x, long y)
- {
- emit getPos(x,y);
- }
-
- void setPressEvent(int key){
- emit getPress(key);
- }
-
- signals:
- void getPos(long, long);
- void getPress(int);
- };
-
- #endif // MOUSEHISTORY_H
6. main.cpp
- // MIT License
-
- // Copyright (c) 2022 hooy
-
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
-
- // The above copyright notice and this permission notice shall be included in all
- // copies or substantial portions of the Software.
-
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- // SOFTWARE.
-
- #include "mainwindow.h"
-
- #include <QApplication>
-
- #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
-
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- app.setWindowIcon(QIcon(":/res/cat.ico"));
- MainWindow w;
- w.show();
- return app.exec();
- }
具体代码地址在github