Qt实现遮罩窗口系统全屏锁定或应用程序界面锁定

文章介绍了QMaskDialog类的实现,这是一个基于Qt的全屏透明遮罩对话框,用于锁定屏幕或显示提示信息。QMaskDialog使用了无边框窗口、透明背景和自定义绘画来创建遮罩效果。此外,还涉及到了键盘和鼠标钩子的使用,以屏蔽特定的键盘组合键,如Ctrl+Alt+Del,以及修改注册表来控制任务管理器的访问。文章提到的一个小问题是,遮罩窗口需要点击后才能响应Ctrl+U关闭,这可能是一个待解决的交互问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.QMaskDialog

qmaskdialog.h

#ifndef QMASKDIALOG_H
#define QMASKDIALOG_H

#include <QDialog>
#include <QPainter>
#include <QDebug>
#include <QMovie>
#include <QKeyEvent>
#include <QStyleOption>
#include <QLineEdit>
#include "qhook.h"
namespace Ui {
class QMaskDialog;
}

class QMaskDialog : public QDialog
{
    Q_OBJECT

public:
    explicit QMaskDialog(const QString& tips, QWidget *parent = nullptr);
    ~QMaskDialog();

private:
    Ui::QMaskDialog *ui;
    QHook m_hook;
    QString m_tips;
protected:
    void paintEvent(QPaintEvent* event);
    bool eventFilter(QObject *, QEvent *);
};

#endif // QMASKDIALOG_H


qmaskdialog.cpp

#include "qmaskdialog.h"
#include "ui_qmaskdialog.h"

QMaskDialog::QMaskDialog(const QString &tips, QWidget *parent) :
    QDialog(parent),m_tips(tips),
    ui(new Ui::QMaskDialog)
{
    ui->setupUi(this);


//        setWindowFlags(Qt::Tool);		//当前窗口的构造函数下调用
//        setWindowFlags(Qt::ToolTip); 	//同时隐藏任务栏图标和标题栏图标

        //子窗口在父窗口之上,但仍可以对父窗口进行操作
//        this->setWindowFlags(Qt::WindowStaysOnTopHint);		//当前窗口置于顶部
        //如果要求只能操作子窗口,不能操作父窗口可以增加以下代码
//        this->setWindowModality(Qt::ApplicationModal); 		//阻塞除当前窗体之外的所有的窗体


//        //单击任务栏图标,对窗口进行显示/隐藏
//        this->setWindowFlags(Qt::WindowMinimizeButtonHint|Qt::WindowMaximizeButtonHint);
#if 1
    //系统所有窗口的顶层包括桌面
//    setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
    setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint|Qt::X11BypassWindowManagerHint);
    setAttribute(Qt::WA_TranslucentBackground, true);
//    showMaximized();
    showFullScreen();
#else
    //当前应用程序的顶层窗口,exec调用,模态,无法关闭    show调用非模态,主窗口可接受close事件
    setWindowFlags(Qt::FramelessWindowHint);
    setAttribute(Qt::WA_TranslucentBackground, true);
    showMaximized();
#endif
//    qDebug()<< QMovie::supportedFormats();
//    QMovie *movie=new QMovie("E:\\qt64test\\untitled2\\gif\\progress\\22222.gif");
//    movie->setScaledSize(QSize(50,50));
//    movie->start();
//    ui->label->setMovie(movie);
//    ui->label->move(1000,500);
    installEventFilter(this);
//    setAttribute(Qt::WA_DeleteOnClose);
    m_hook.hook(true);
    m_hook.enableTaskManager(true);
}

QMaskDialog::~QMaskDialog()
{
    delete ui;
    m_hook.hook(false);
    m_hook.enableTaskManager(false);
}
void QMaskDialog::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    QPainter painter(this);
    painter.fillRect(rect(),QColor(0,0,255,20));
    QFont font = this->font();
    font.setBold(true);
    font.setPixelSize(80);
    painter.setFont(font);
    painter.drawText(rect(), Qt::AlignCenter, m_tips);
}

bool QMaskDialog::eventFilter(QObject *obj, QEvent *e)
{
    switch (e->type()) {
    case QEvent::KeyPress:{
        QKeyEvent* ev = static_cast<QKeyEvent*>(e);
        if(ev->modifiers() == Qt::ControlModifier){
            if(ev->key() == Qt::Key_U){
                close();
                return true;
            }
        }
    }
        break;
    default:
        break;
    }
    return QDialog::eventFilter(obj,e);
}


showFullScreen:全屏遮罩
showMaximized:除任务栏外,全屏

qhook.h

#ifndef QHOOK_H
#define QHOOK_H

#include <QObject>
#include <Windows.h>
#include <QDebug>
#include <QSettings>
//在注册表该目录下增加新内容
#define TASKMANAGERSystem "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System"
#define TASKMANAGERExplorer "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer"


class QHook : public QObject
{
    Q_OBJECT
public:
    explicit QHook(QObject *parent = nullptr);
    ~QHook();
    void hook(bool flag); //功能键
    void showTaskWindow(bool flag); //显示任务栏
    void enableTaskManager(bool flag); //任务管理器
private:
    HWND task;
signals:

};

#endif // QHOOK_H

qhook.cpp

#include "qhook.h"
#pragma comment(lib, "User32.lib")

HHOOK keyHook = NULL;
HHOOK mouseHook = NULL;

QHook::QHook(QObject *parent)
    : QObject{parent}
{

}

//键盘钩子过程
LRESULT CALLBACK keyProc(int nCode,WPARAM wParam,LPARAM lParam )
{
    //在WH_KEYBOARD_LL模式下lParam 是指向KBDLLHOOKSTRUCT类型地址
    KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam;
    //如果nCode等于HC_ACTION则处理该消息,如果小于0,则钩子子程就必须将该消息传递给 CallNextHookEx
    if(nCode == HC_ACTION)
    {
        if((pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL)& 0x8000 && GetAsyncKeyState(VK_SHIFT)&0x8000)|| //"Ctrl+Shift+Esc"
            (pkbhs->vkCode == VK_ESCAPE && GetAsyncKeyState(VK_CONTROL) & 0x8000) || //"Ctrl+Esc"
            (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN )|| //"Alt+Tab"
            (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags &LLKHF_ALTDOWN )|| //"Alt+Esc"
            (pkbhs->vkCode == VK_LWIN || pkbhs->vkCode == VK_RWIN )||	// "LWIN/RWIN"
            (pkbhs->vkCode == VK_F4 && pkbhs->flags & LLKHF_ALTDOWN )|| //"Alt+F4"
            (pkbhs->vkCode == VK_ESCAPE))
        {
            qDebug()<<"屏蔽";
            return 1;//返回1表示截取消息不再传递,返回0表示不作处理,消息继续传递
        }

        // 		if(pkbhs->vkCode == VK_F12)
        // 		{
        // 			void unHook();
        // 			qApp->quit();
        // 		}
    }
    return CallNextHookEx(keyHook, nCode, wParam, lParam);
}
//鼠标钩子过程
LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam )
{

    return 1;

}

QHook::~QHook()
{

}

//安装钩子,调用该函数即安装钩子
void QHook::hook(bool flag)
{
    if (flag)
    {
        //这两个底层钩子,不要DLL就可以全局
        //底层键盘钩子
        keyHook =SetWindowsHookEx( WH_KEYBOARD_LL,keyProc,GetModuleHandle(NULL),0);
        //底层鼠标钩子
        //    mouseHook =SetWindowsHookEx( WH_MOUSE_LL,mouseProc,GetModuleHandle(NULL),0);
    }
    else
    {
        UnhookWindowsHookEx(keyHook);
        //  UnhookWindowsHookEx(mouseHook);
    }
}

//添加注册屏蔽Ctrl+Alt+del
void QHook::enableTaskManager(bool flag)
{
    // 屏蔽ctrl + alt +del 需要修改注册表的值, 取得管理员权限, 关闭360等杀毒软件
    int value = flag ? 0x00000001 : 0x00000000;
    QSettings *settings = new QSettings(TASKMANAGERSystem, QSettings::NativeFormat);
    settings->setValue("DisableTaskMgr", value); //任务管理器
    settings->setValue("DisableChangePassword", value); //更改密码
    settings->setValue("DisableLockWorkstation", value); //锁定计算机
    settings->setValue("DisableSwitchUserOption", value); //切换用户

    QSettings *settings2 = new QSettings(TASKMANAGERExplorer, QSettings::NativeFormat);
    settings2->setValue("NoLogOff", value); //注销

    delete settings;
    delete settings2;

}

//屏蔽任务栏
void QHook::showTaskWindow(bool flag)
{
    if(flag)
        ShowWindow(task,SW_SHOW);
    else
    {
        task=FindWindow(L"Shell_TrayWnd",NULL);
        ShowWindow(task,SW_HIDE);
    }
}

2.使用


    QMaskDialog *_maskdlg=new QMaskDialog(QString("锁定中,请勿关机"));
//    setFocusProxy(_maskdlg);
    _maskdlg->setWindowFlag(Qt::Tool);
    _maskdlg->raise();
//    _maskdlg->setGeometry(frameGeometry());
    _maskdlg->exec();
    _maskdlg->deleteLater();
    _maskdlg=nullptr;
    

若仅为应用程序主界面,则设置父窗口,并调用以下函数,盖住主界面

m_maskdlg->setGeometry(frameGeometry());

若要遮罩窗口跟随主界面自动拉伸,需重写主界面(MainWindow)的ResizeEvent,如果为全屏遮罩,则不需要,

void MainWindow::resizeEvent(QResizeEvent *event)
{
    if(m_maskdlg) m_maskdlg->setGeometry(frameGeometry());
}

3.效果图

在这里插入图片描述

4、说明

目前的效果是仅屏蔽了鼠标按键,全屏范围不接受鼠标点击,如需屏蔽键盘按键,需要安装系统钩子,屏蔽特定的组合键(ALT+TAB,ESC,CTRL+ALT+DEL等等),并且修改注册表来实现,具体可以查看下面这位老哥的博文。

另外有个小bug,这个透明的全屏遮罩窗口,必须点击一下,才能响应ctrl+U关闭,即便调用setFocus()也无济于事,如有解决方法,欢迎评论留言

参考博文:https://blog.youkuaiyun.com/liulihuo_gyh/article/details/78129248

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值