具體效果如下:
實(shí)現(xiàn)步驟方法:
1.使用windows HOOK谎倔,獲取全局鼠標(biāo)位置趁蕊,通過信號(hào)傳遞給qwidget調(diào)整窗口位置
2.設(shè)置鼠標(biāo)事件穿透环揽,屏蔽窗口的點(diǎn)擊事件
3.繪制半透明背景色
4.使用windows hook將鼠標(biāo)的點(diǎn)擊事件,通過qt信號(hào)槽函數(shù)傳遞給窗口夏哭,實(shí)時(shí)更換點(diǎn)擊時(shí)背景色
5.不顯示狀態(tài)欄圖標(biāo),使用小圖標(biāo)退出程序
完整代碼地址:shadow
1.hookutil.h
#ifndef HOOKUTIL_H
#define HOOKUTIL_H
#ifdef _WIN32
#include <windows.h>
#endif
int startMouseHook();
bool stopMouseHook();
#endif // HOOKUTIL_H
2. hookutil.cpp
#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
#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};
? ? //鼠標(biāo)點(diǎn)擊事件
? ? bool ? ? ? ? ? ?pressed_{false};
};
#endif // MAINWINDOW_H
4.mainwindow.cpp
#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
#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
#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();
}