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

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.csdn.net/liulihuo_gyh/article/details/78129248

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是使用Qt代码实现遮罩实现等待加载效果的示例代码: ```python from PyQt5.QtCore import QSize, Qt, QThread, pyqtSignal from PyQt5.QtGui import QMovie from PyQt5.QtWidgets import QApplication, QWidget, QLabel class LoadingMask(QWidget): def __init__(self, parent): super().__init__(parent) self.setFixedSize(parent.size()) self.setStyleSheet('background-color: rgba(0, 0, 0, 128);') self.movie = QMovie('loading.gif') self.movie.setScaledSize(QSize(100, 100)) label = QLabel(self) label.setMovie(self.movie) label.move(self.width() // 2 - 50, self.height() // 2 - 50) def start(self): self.movie.start() def stop(self): self.movie.stop() self.hide() class WorkerThread(QThread): finished = pyqtSignal() def run(self): # 模拟耗时操作 import time time.sleep(5) self.finished.emit() class MainWindow(QWidget): def __init__(self): super().__init__() self.setWindowTitle('遮罩实现等待加载效果') self.resize(500, 500) self.loading_mask = LoadingMask(self) self.worker_thread = WorkerThread(self) self.worker_thread.finished.connect(self.on_finished) def on_finished(self): self.loading_mask.stop() def do_something(self): self.loading_mask.start() self.worker_thread.start() if __name__ == '__main__': import sys app = QApplication(sys.argv) window = MainWindow() window.show() window.do_something() sys.exit(app.exec_()) ``` 这个示例代码中,首先定义了一个LoadingMask类,它继承自QWidget,用于实现遮罩层和等待加载动画的显示和隐藏。在LoadingMask的构造函数中,设置其大小和背景颜色,并创建一个QMovie用于加载动画gif,然后将QMovie放置在遮罩层中央。start和stop方法用于启动和停止动画和遮罩层的显示。 MainWindow继承自QWidget,是主窗口类。它包含了一个LoadingMask实例和一个WorkerThread实例。do_something方法用于启动等待加载的操作,它首先调用LoadingMask的start方法显示遮罩层和加载动画,然后启动WorkerThread执行耗时操作。WorkerThread是QThread的子类,用于模拟耗时操作,它执行完成后会发送一个finished信号。MainWindow的on_finished方法用于接收WorkerThread发送的finished信号,并调用LoadingMask的stop方法隐藏遮罩层和动画。 在主函数中,创建一个QApplication实例和MainWindow实例,然后调用MainWindow的show方法显示主窗口,并调用do_something方法启动等待加载的操作。最后调用QApplication的exec_方法进入Qt事件循环。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值