本文最后更新于 121 天前,其中的信息可能已经有所发展或是发生改变。
前言
由于本次更新在使用某些功能时,原版本QT5.12.8与MSVC2017的编译器会出现一些报错,因此我将版本换至了QT5.12.12与MinGW7.2.0编译器
在本次更新中添加了
- 注册码功能,用户需要输入特定的注册码才能够使用此文本编辑器
- 查看历史记录功能,用户可在文件栏查看自己最近打开的文件,同时可以清除历史打开记录
- Base64编码与解码,作为一名CTFer,我加上了这种很常见的编码格式,后续计划添加更多
安装包在这->Xm's Notepad_2_0
程序运行结果
打开程序时会出现以下界面
输入正确注册码之后
点击yes进入程序
进入程序之后点击文件就可以看见最近打开功能了,同时还加上了加解密功能,不过里面现在只有Base64
项目文件
相较于上一版的文件,我在其中新建了一个register文件,也就是login注册窗口,在其中实现了一些功能:
- 对注册码输入是否正确的判断
- 每个按钮控件所对应的输出结果
- 禁用关闭该窗口控件,无法通过右上角×号关闭该窗口
- 禁用任务管理器中关闭该窗口,无法使用任务管理器杀死该窗口进程
代码实现
mainwindow.h
正常的槽函数定义
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_new_file_triggered();
void on_open_file_triggered();
void on_save_file_triggered();
void on_save_as_triggered();
void on_paste_triggered();
void on_cut_triggered();
void on_copy_triggered();
void on_italics_triggered(bool italics);
void on_underline_triggered(bool underline);
void on_bolder_triggered(bool bolder);
void on_font_triggered();
void on_about_triggered();
void on_undo_triggered();
void on_redo_triggered();
void on_exit_triggered();
void on_print_triggered();
void on_clear_history_triggered();
void on_actionBase64_triggered();
void on_tobase64_triggered();
private:
Ui::MainWindow *ui;
QString currentFile;
void initMenu();
void on_open_recent_file();
};
#endif // MAINWINDOW_H
register.h
定义了一个protected的nativeEvent
方法,以便于后面使用
#ifndef REGISTER_H
#define REGISTER_H
#include <QDialog>
#include <windows.h>
namespace Ui {
class Register;
}
class Register : public QDialog
{
Q_OBJECT
public:
explicit Register(QWidget *parent = nullptr);
~Register();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Register *ui;
protected:
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
};
#endif // REGISTER_H
main.cpp
显示窗口
#include "mainwindow.h"
#include "register.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
主要功能实现部分
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include "QFileDialog"
#include "QMessageBox"
#include "QFontDialog"
#include "QSettings"
#include "QList"
#include "QByteArray"
#include "register.h"
#if defined(QT_PRINTSUPPORT_LIB)
#include <QtPrintSupport/qtprintsupportglobal.h>
#if QT_CONFIG(printer)
#if QT_CONFIG(printdialog)
#include <QPrintDialog>
#endif
#include <QPrinter>
#endif
#endif
QSettings * mSettings;
//获取历史记录
QList<QString> getHistory();
//保存打开历史记录
void saveHistory(QString path);
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
Register *pRes = new Register();
pRes->exec();
ui->setupUi(this);
this->setCentralWidget(ui->textEdit);
if(mSettings==NULL){
mSettings = new QSettings("settings.ini",QSettings::IniFormat);
}
initMenu();
#if !QT_CONFIG(printer)
ui->print->setEnabled(false);
#endif
}
MainWindow::~MainWindow()
{
delete ui;
}
//初始化菜单
void MainWindow::initMenu()
{
//获取menu
QMenu * recent = this->findChild<QMenu *>("recent");
//获取Action
QSet<QObject *> chLists = recent->children().toSet();
foreach(QObject * ch,chLists){
QAction *action = (QAction *)ch;
//清空子菜单Action
recent->removeAction(action);
}
QList<QString> lists = getHistory();
for(int i = lists.size()-1;i>=0;i--){
//生成子菜单Action
recent->addAction(lists[i],this,&MainWindow::on_open_recent_file);
}
/*
foreach(QString str,lists){
//生成子菜单Action
recent->addAction(str,this,&MainWindow::on_open_recent_file);
}
*/
if(lists.size()>0){
recent->addAction("清除历史记录",this,&MainWindow::on_clear_history_triggered,QKeySequence("Ctrl+Alt+Shift+C"));
}
}
//获取历史记录
QList<QString> getHistory(){
//打开开始读
int size = mSettings->beginReadArray("history");
//创建返回对象
QList<QString> lists;
for(int i = 0;i<size;i++){
mSettings->setArrayIndex(i);
QString path = mSettings->value("path").toString();
lists.append(path);
qDebug() << i << ":" << path;
}
//关闭读
mSettings->endArray();
return lists;
}
//保存打开历史记录
void saveHistory(QString path){
//获取历史
QList<QString> lists = getHistory();
foreach(QString str,lists){
if(str==path){
lists.removeOne(str);
}
}
lists.append(path);
//打开开始写入
mSettings->beginWriteArray("history");
for (int i = 0; i<lists.size() ;i++ ) {
mSettings->setArrayIndex(i);
//保存字符串
mSettings->setValue("path",lists[i]);
}
//关闭开始写入
mSettings->endArray();
}
//新建文件
void MainWindow::on_new_file_triggered()
{
qDebug()<<"Start Create New File ...";
currentFile.clear();
ui->textEdit->setText("");
}
//打开文件
void MainWindow::on_open_recent_file()
{
QAction * action = (QAction *)sender();
QString fileName = action->text();
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法打开此文件"+file.errorString());
return;
}
currentFile = fileName;
setWindowTitle(fileName);
QTextStream in(&file);
QString text = in.readAll();
ui->textEdit->setText(text);
file.close();
saveHistory(currentFile);
initMenu();
}
//打开文件
void MainWindow::on_open_file_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this,"打开文件");
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法打开此文件:"+file.errorString());
return;
}
currentFile = fileName;
setWindowTitle(fileName);
QTextStream in(&file);
QString text = in.readAll();
ui->textEdit->setText(text);
file.close();
saveHistory(currentFile);
initMenu();
}
//保存文件
void MainWindow::on_save_file_triggered()
{
QString fileName;
if(currentFile.isEmpty()){
fileName =QFileDialog::getSaveFileName(this,"保存文件");
currentFile =fileName;
}else{
fileName =currentFile;
}
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法保存文件:"+file.errorString());
return;
}
setWindowTitle(fileName);
QTextStream out(&file);
QString text =ui->textEdit->toHtml();
out<<text;
file.close();
saveHistory(currentFile);
initMenu();
}
//另存为
void MainWindow::on_save_as_triggered()
{
QString fileName=QFileDialog::getSaveFileName(this,"另存文件");
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly|QFile::Text)){
QMessageBox::warning(this,"警告","无法保存文件:"+file.errorString());
return;
}
currentFile =fileName;
setWindowTitle(fileName);
QTextStream out(&file);
QString text =ui->textEdit->toHtml();
out<<text;
file.close();
saveHistory(currentFile);
}
//复制
void MainWindow::on_copy_triggered()
{
ui->textEdit->copy();
}
//粘贴
void MainWindow::on_paste_triggered()
{
ui->textEdit->paste();
}
//剪切
void MainWindow::on_cut_triggered()
{
ui->textEdit->cut();
}
//斜体
void MainWindow::on_italics_triggered(bool italics)
{
ui->textEdit->setFontItalic(italics);
}
//下划线
void MainWindow::on_underline_triggered(bool underline)
{
ui->textEdit->setFontUnderline(underline);
}
//加粗
void MainWindow::on_bolder_triggered(bool bolder)
{
ui->textEdit->setFontWeight(bolder?QFont::Bold:QFont::Normal);
}
//撤销
void MainWindow::on_undo_triggered()
{
ui->textEdit->undo();
}
//取消撤销
void MainWindow::on_redo_triggered()
{
ui->textEdit->redo();
}
//字体
void MainWindow::on_font_triggered()
{
bool fontSelected;
QFont font = QFontDialog::getFont(&fontSelected,this);
if(fontSelected){
ui->textEdit->setFont(font);
}
}
//打印
void MainWindow::on_print_triggered()
{
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
QPrinter printDev;
#if QT_CONFIG(printdialog)
QPrintDialog dialog(&printDev,this);
if(dialog.exec()==QDialog::Rejected)
return;
#endif
ui->textEdit->print(&printDev);
#endif
}
//关于
void MainWindow::on_about_triggered()
{
QMessageBox::about(this,"Welcome to C++Qt!","这是晓梦ovo的Notepad哦");
}
//退出
void MainWindow::on_exit_triggered()
{
QCoreApplication::exit();
}
void MainWindow::on_clear_history_triggered()
{
qDebug() << "on_clear_history_triggered clickde...";
mSettings->remove("history");
initMenu();
}
void MainWindow::on_actionBase64_triggered()
{
QString frombase64 = ui->textEdit->toPlainText();
QByteArray text = QByteArray::fromBase64(frombase64.toLocal8Bit());
//qDebug() << text;
ui->textEdit->setPlainText(text);
}
void MainWindow::on_tobase64_triggered()
{
QString tobase64 = ui->textEdit->toPlainText();
QByteArray text = tobase64.toLocal8Bit().toBase64();
//qDebug() << text;
ui->textEdit->setPlainText(text);
}
register.cpp
实现了限制窗口缩放与关闭与注册码功能
#include "register.h"
#include "ui_register.h"
#include "QMessageBox"
Register::Register(QWidget *parent) :
QDialog(parent),
ui(new Ui::Register)
{
ui->setupUi(this);
setWindowFlags(Qt::CustomizeWindowHint |
Qt::WindowMinimizeButtonHint
);
setFixedSize(this->width(), this->height());
}
Register::~Register()
{
delete ui;
}
void Register::on_pushButton_clicked()
{
if(ui->lineEdit->text()==tr("123456")){
QMessageBox::information(this,tr("Ciallo~(∠・ω< )⌒★"),tr("居然被你猜出来了"),QMessageBox::Yes);
accept();
}
else{
QMessageBox::warning(this,tr("不知道注册码你瞎点什么"),tr("注册码不对哦"),QMessageBox::Yes);
exit(0);
}
}
void Register::on_pushButton_2_clicked()
{
QMessageBox::warning(this,tr("注册码呢注册码呢"),tr("怎么不试试注册码是什么"),QMessageBox::Yes);
exit(0);
}
bool Register::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
MSG *msg = (MSG *)message;
if (msg->message == WM_SYSCOMMAND)
{
if (61536 == msg->wParam)//禁止任务栏"关闭窗口"
{
QMessageBox::warning(this,tr("别乱点"),tr("不是,谁让你点这了?"),QMessageBox::Yes);
return true;
}
if (61587 == msg->wParam)//禁用单击
{
return true;
}
if (61539 == msg->wParam)//禁用双击
{
return true;
}
}
return QDialog::nativeEvent(eventType, message, result);
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Xm's Notepad</string>
</property>
<property name="windowIcon">
<iconset resource="images.qrc">
<normaloff>:/images/images/pencil.png</normaloff>:/images/images/pencil.png</iconset>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTextEdit" name="textEdit">
<property name="geometry">
<rect>
<x>13</x>
<y>10</y>
<width>131</width>
<height>111</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>23</height>
</rect>
</property>
<widget class="QMenu" name="menu">
<property name="title">
<string>文件</string>
</property>
<widget class="QMenu" name="recent">
<property name="title">
<string>最近打开</string>
</property>
</widget>
<addaction name="new_file"/>
<addaction name="open_file"/>
<addaction name="recent"/>
<addaction name="separator"/>
<addaction name="save_file"/>
<addaction name="save_as"/>
<addaction name="separator"/>
<addaction name="print"/>
<addaction name="separator"/>
<addaction name="exit"/>
</widget>
<widget class="QMenu" name="menu_2">
<property name="title">
<string>编辑</string>
</property>
<addaction name="copy"/>
<addaction name="paste"/>
<addaction name="cut"/>
<addaction name="separator"/>
<addaction name="bolder"/>
<addaction name="italics"/>
<addaction name="underline"/>
<addaction name="separator"/>
<addaction name="font"/>
</widget>
<widget class="QMenu" name="menu_3">
<property name="title">
<string>关于</string>
</property>
<addaction name="about"/>
</widget>
<widget class="QMenu" name="menu_4">
<property name="title">
<string>加解密</string>
</property>
<addaction name="tobase64"/>
<addaction name="actionBase64"/>
</widget>
<addaction name="menu"/>
<addaction name="menu_2"/>
<addaction name="menu_3"/>
<addaction name="menu_4"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="new_file"/>
<addaction name="open_file"/>
<addaction name="print"/>
<addaction name="save_file"/>
<addaction name="save_as"/>
</widget>
<widget class="QToolBar" name="toolBar_2">
<property name="windowTitle">
<string>toolBar_2</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="copy"/>
<addaction name="paste"/>
<addaction name="cut"/>
</widget>
<widget class="QToolBar" name="toolBar_3">
<property name="windowTitle">
<string>toolBar_3</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="bolder"/>
<addaction name="italics"/>
<addaction name="underline"/>
<addaction name="font"/>
</widget>
<widget class="QToolBar" name="toolBar_4">
<property name="windowTitle">
<string>toolBar_4</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="undo"/>
<addaction name="redo"/>
</widget>
<widget class="QToolBar" name="toolBar_5">
<property name="windowTitle">
<string>toolBar_5</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="about"/>
<addaction name="exit"/>
</widget>
<action name="new_file">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/new.png</normaloff>:/images/images/new.png</iconset>
</property>
<property name="text">
<string>新建文件</string>
</property>
<property name="shortcut">
<string>Ctrl+N</string>
</property>
</action>
<action name="open_file">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/open.png</normaloff>:/images/images/open.png</iconset>
</property>
<property name="text">
<string>打开文件</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="save_file">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/save.png</normaloff>:/images/images/save.png</iconset>
</property>
<property name="text">
<string>保存文件</string>
</property>
<property name="shortcut">
<string>Ctrl+S</string>
</property>
</action>
<action name="save_as">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/save_as.png</normaloff>:/images/images/save_as.png</iconset>
</property>
<property name="text">
<string>另存为</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+S</string>
</property>
</action>
<action name="paste">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/paste.png</normaloff>:/images/images/paste.png</iconset>
</property>
<property name="text">
<string>粘贴</string>
</property>
<property name="shortcut">
<string>Ctrl+V</string>
</property>
</action>
<action name="cut">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/cut.png</normaloff>:/images/images/cut.png</iconset>
</property>
<property name="text">
<string>剪切</string>
</property>
<property name="shortcut">
<string>Ctrl+X</string>
</property>
</action>
<action name="copy">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/copy.png</normaloff>:/images/images/copy.png</iconset>
</property>
<property name="text">
<string>复制</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
</action>
<action name="bolder">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/bold.png</normaloff>:/images/images/bold.png</iconset>
</property>
<property name="text">
<string>加粗</string>
</property>
<property name="shortcut">
<string>Ctrl+B</string>
</property>
</action>
<action name="italics">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/italic.png</normaloff>:/images/images/italic.png</iconset>
</property>
<property name="text">
<string>斜体</string>
</property>
<property name="shortcut">
<string>Ctrl+I</string>
</property>
</action>
<action name="underline">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/underline.png</normaloff>:/images/images/underline.png</iconset>
</property>
<property name="text">
<string>下划线</string>
</property>
<property name="shortcut">
<string>Ctrl+U</string>
</property>
</action>
<action name="font">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/font.png</normaloff>:/images/images/font.png</iconset>
</property>
<property name="text">
<string>字体</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+F</string>
</property>
</action>
<action name="about">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/info.png</normaloff>:/images/images/info.png</iconset>
</property>
<property name="text">
<string>关于</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+I</string>
</property>
</action>
<action name="undo">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/edit_undo.png</normaloff>:/images/images/edit_undo.png</iconset>
</property>
<property name="text">
<string>撤回</string>
</property>
<property name="shortcut">
<string>Ctrl+Z</string>
</property>
</action>
<action name="redo">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/edit_redo.png</normaloff>:/images/images/edit_redo.png</iconset>
</property>
<property name="text">
<string>取消撤回</string>
</property>
<property name="shortcut">
<string>Ctrl+Shift+Z</string>
</property>
</action>
<action name="exit">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/exit.png</normaloff>:/images/images/exit.png</iconset>
</property>
<property name="text">
<string>退出</string>
</property>
<property name="shortcut">
<string>Esc</string>
</property>
</action>
<action name="print">
<property name="icon">
<iconset resource="images.qrc">
<normaloff>:/images/images/print.png</normaloff>:/images/images/print.png</iconset>
</property>
<property name="text">
<string>打印</string>
</property>
<property name="shortcut">
<string>Ctrl+P</string>
</property>
</action>
<action name="clear_history">
<property name="text">
<string>清除打开历史记录</string>
</property>
<property name="shortcut">
<string>Ctrl+Alt+Shift+C</string>
</property>
</action>
<action name="actionBase64">
<property name="text">
<string>Base64解码</string>
</property>
</action>
<action name="tobase64">
<property name="text">
<string>base64编码</string>
</property>
</action>
</widget>
<resources>
<include location="images.qrc"/>
</resources>
<connections/>
</ui>
register.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Register</class>
<widget class="QDialog" name="Register">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>login</string>
</property>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>70</y>
<width>351</width>
<height>141</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>请输入注册码:</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>确定</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>返回</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>