具体效果如上图:
实现方法:
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
#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
#include
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
#include
#include
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
#include
#include
#include
#include
#include
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
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
#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