用QT实现Windows定时关机功能

      目前网上定时关机的小工具很多,但是按照个人使用经验来说,网上很多小工具都是有毒或者带有恶意代码或者流氓代码的。因为平时经常下载东西,需要使用定时关机,所以干脆自己写了个定时关机的软件,简单易用。

      截图基于WIN7系统,顺便说一句,WIN7下的小软件很漂亮。

      首先,软件需要最小化托盘运行,并且显示倒计时悬浮窗。这里设置为在右下角显示。代码如下:

     


 SusWidget.h

#ifndef SUSWIDGET_H
#define SUSWIDGET_H

#include <QtGui/QWidget>
#include <QDateTime>
#include <QtGui/QLineEdit>
#include <QtCore/QTextCodec>
#include <QtGui/QApplication>
#include <QDesktopWidget>

#ifndef    REMAIN_TIME
#define   REMAIN_TIME            0
#endif

#ifndef    TO_SHUTDOWN
#define   TO_SHUTDOWN         1
#endif

#ifndef    SHUTDOWN_ERROR
#define   SHUTDOWN_ERROR  2
#endif

class SusWidget : public QWidget
{
	Q_OBJECT

public:
	SusWidget(QWidget *parent = 0, Qt::WFlags flags = 0);
	~SusWidget();

private:
	QLineEdit  *timeEdit;

public slots:
	void SetRemainTime(const QTime &time, int type);
};

#endif // SUSWIDGET_H

 

 SusWidget.cpp

#include "suswidget.h"

SusWidget::SusWidget(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
	setFixedSize(170, 20);
	QTextCodec::setCodecForTr(QTextCodec::codecForName("gb18030"));
	setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool);
	QRect   screenSize;
	screenSize = QApplication::desktop()->rect();
	setGeometry(screenSize.width()-180, screenSize.height()-70, 170, 20);
	timeEdit = new QLineEdit(this);
	timeEdit->setGeometry(rect());
	QPalette palette;
	QBrush brush(QColor(255, 255, 0, 255));
	brush.setStyle(Qt::SolidPattern);
	QBrush brush1(QColor(85, 0, 0, 255));
	brush1.setStyle(Qt::SolidPattern);
	palette.setBrush(QPalette::Active, QPalette::Text, brush);
	palette.setBrush(QPalette::Active, QPalette::Base, brush1);
	palette.setBrush(QPalette::Inactive, QPalette::Text, brush);
	palette.setBrush(QPalette::Inactive, QPalette::Base, brush1);
	palette.setBrush(QPalette::Disabled, QPalette::Text, brush);
	palette.setBrush(QPalette::Disabled, QPalette::Base, brush1);
	timeEdit->setPalette(palette);
	QFont font;
	font.setFamily(QString::fromUtf8("\351\273\221\344\275\223"));
	font.setBold(true);
	font.setWeight(75);
	timeEdit->setFont(font);
	timeEdit->setAlignment(Qt::AlignCenter);
	timeEdit->setText(tr("正在统计关机剩余时间..."));
	timeEdit->setReadOnly(true);
}

SusWidget::~SusWidget()
{

}


void SusWidget::SetRemainTime(const QTime &time, int type)
{
	if ( type == REMAIN_TIME )
	{
		timeEdit->setText( tr("离关机还有:") + time.toString(tr("hh时mm分ss秒")) );
	}
	if ( type == TO_SHUTDOWN )
	{
		timeEdit->setText( tr("正在关机...") );
	}
	if ( type == SHUTDOWN_ERROR )
	{
		timeEdit->setText( tr("关机失败...") );
	}
}



     定时关机需要一个后台线程来实现计时功能:


TimeThread.h

#ifndef TIMETHREAD_H
#define TIMETHREAD_H

#include <QDateTime>
#include <QThread>
#include <Windows.h>

#define   REMAIN_TIME            0
#define   TO_SHUTDOWN         1
#define   SHUTDOWN_ERROR  2

class TimeThread : public QThread
{
	Q_OBJECT

public:
	QTime m_time;
	bool m_start;

public:
	TimeThread(QObject *parent = 0);
	void SetCountTime(QTime time, bool start);
	bool MySystemShutdown();

signals:
	void RemainTimeChanged(const QTime &time, int type);

protected:
	void run();
};

#endif

 

TimeThread.cpp

#include "TimeThread.h"

TimeThread::TimeThread(QObject *parent) : QThread(parent)
{
	m_time = QTime(1, 0, 0);
	m_start = false;
}

void TimeThread::SetCountTime(QTime time, bool start)
{
	m_time = time;
	m_start = start;
}

void TimeThread::run()
{
	QTime  oldTime, newTime;
	oldTime.setHMS(QTime::currentTime().hour(), QTime::currentTime().minute(), QTime::currentTime().second(), 0);
	while(m_start)
	{
		msleep(250);
		newTime.setHMS(QTime::currentTime().hour(), QTime::currentTime().minute(), QTime::currentTime().second(), 0);
		if ( oldTime != newTime )
		{
			oldTime = newTime;
			m_time = m_time.addSecs(-1);
		}
		emit  RemainTimeChanged(m_time, REMAIN_TIME);
		if ( m_time == QTime(0, 0, 0) )
		{
			emit  RemainTimeChanged(m_time, TO_SHUTDOWN);
			if ( !MySystemShutdown() )
			{
				emit  RemainTimeChanged(m_time, SHUTDOWN_ERROR);
			}
			break;
		}
	}
}

bool TimeThread::MySystemShutdown()
{
	HANDLE hToken; 
	TOKEN_PRIVILEGES tkp; 

	//获取进程标志
	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) 
		return false; 

	//获取关机特权的LUID
	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, 	&tkp.Privileges[0].Luid); 
	tkp.PrivilegeCount = 1; 
	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 

	//获取这个进程的关机特权
	AdjustTokenPrivileges(hToken, false, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0); 
	if (GetLastError() != ERROR_SUCCESS) return false; 

	// 强制关闭计算机 
	if (  !ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 
    	 SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE |	SHTDN_REASON_FLAG_PLANNED)) 
		 return false; 
	return true;
} 

 


       一般的定时关机软件还需要显示当前系统时间:


SystemTimeThread.h

#ifndef SYSTEMTIMETHREAD_H
#define SYSTEMTIMETHREAD_H

#include <QDateTime>
#include <QThread>

class SystemTimeThread : public QThread
{
	Q_OBJECT

public:
	QTime m_time;

public:
	SystemTimeThread(QObject *parent = 0);

signals:
	void CurrentTimeChanged(const QTime &time);

protected:
	void run();
};

#endif


 

SystemTimeThread.cpp

#include "SystemTimeThread.h"

SystemTimeThread::SystemTimeThread(QObject *parent) :  QThread(parent)
{
	m_time = m_time.currentTime();
}

void SystemTimeThread::run()
{
	while(1)
	{
		msleep(500);
		m_time = m_time.currentTime();
		emit CurrentTimeChanged(m_time);
	}
}



      好了,上面的主要部分都已经编写完成,接下来就是主要界面了。定时关机只是一个小软件,所以尽量的简单易用,不要加入过多不必要的功能。代码如下:


 shutdown.h

#ifndef SHUTDOWN_H
#define SHUTDOWN_H

#include <QtCore/QVariant>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QButtonGroup>
#include <QtGui/QDialog>
#include <QtGui/QGroupBox>
#include <QtGui/QLabel>
#include <QtGui/QLineEdit>
#include <QtGui/QPushButton>
#include <QtGui/QRadioButton>
#include <QtGui/QTimeEdit>
#include <QRegExpValidator>
#include <QString>
#include <QDateTime>
#include <QSystemTrayIcon>

#include "TimeThread.h"
#include "SusWidget.h"
#include "SystemTimeThread.h"

class ShutDown : public QDialog
{
	Q_OBJECT

public:
	ShutDown(QWidget *parent = 0, Qt::WFlags flags = 0);
	~ShutDown();

private:
	QGroupBox *chooseGroup;
	QRadioButton *countDownRadio;
	QRadioButton *timerRadio;
	QTimeEdit *countEdit;
	QTimeEdit *timeEdit;
	QLabel *remainText;
	QLineEdit *remainTimeLine;
	QLineEdit *systemTimeLine;
	QLabel *currentTimeText;
	QPushButton *startButton;
	QPushButton *exitButton;

	QAction *susAction;
	QAction *restoreAction;
	QAction *quitAction;
	QSystemTrayIcon *trayIcon;
	QMenu *trayIconMenu;

	QTime    m_time;
	bool       m_start;
	bool       m_countDown;
	bool       m_mini;
	bool       m_suspend;
	TimeThread  m_timeThread;
	SystemTimeThread  m_systemTimeThread;
	SusWidget *swidget;

//protected:
//	void closeEvent(QCloseEvent *event);

public:
	void createActions();
	void createTrayIcon();
	void SetSusTime(const QTime &time, int type);

signals:
	void RemainTimeChanged(const QTime &time, int type);

private slots:
	void  CountTimeChanged(const QTime &time);
	void  ClickedCountDownRadio();
	void  doTimeChanged(const QTime &time);
	void  ClickedTimerRadio();
	void  ClickedStartButton();
	void  SetRemainTime(const QTime &time, int type);
	void  SetCurrentTime(const QTime &time);
	void  ShowDialog();
	void  ClikedTrayIcon(QSystemTrayIcon::ActivationReason reason);
	void  ShowSusWidget();
	void  HideOrExit();
};

#endif // SHUTDOWN_H

 

shutdown.cpp

#include "shutdown.h"
#include <QtGui>

ShutDown::ShutDown(QWidget *parent, Qt::WFlags flags)
: QDialog(parent, flags)
{
	if (objectName().isEmpty())  setObjectName(QString::fromUtf8("ShutDown"));
	setFixedSize(264, 261);

	setWindowFlags(Qt::WindowMinimizeButtonHint);

	QIcon icon;
	icon.addPixmap(QPixmap(QString::fromUtf8("Resources/shutdown.png")), QIcon::Normal, QIcon::Off);
	setWindowIcon(icon);

	createActions();
	createTrayIcon();

	chooseGroup = new QGroupBox(this);
	chooseGroup->setGeometry(QRect(20, 10, 221, 191));
	chooseGroup->setAlignment(Qt::AlignCenter);
	countDownRadio = new QRadioButton(chooseGroup);
	countDownRadio->setGeometry(QRect(20, 30, 101, 21));
	timerRadio = new QRadioButton(chooseGroup);
	timerRadio->setGeometry(QRect(20, 70, 101, 21));
	countEdit = new QTimeEdit(chooseGroup);
	countEdit->setGeometry(QRect(120, 30, 81, 22));
	countEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
	countEdit->setTime(QTime(1, 0, 0));
	timeEdit = new QTimeEdit(chooseGroup);
	timeEdit->setGeometry(QRect(120, 70, 81, 22));
	timeEdit->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter);
	remainText = new QLabel(chooseGroup);
	remainText->setGeometry(QRect(20, 110, 81, 21));
	remainTimeLine = new QLineEdit(chooseGroup);
	remainTimeLine->setGeometry(QRect(110, 110, 91, 20));
	remainTimeLine->setAlignment(Qt::AlignCenter);
	remainTimeLine->setReadOnly(true);
	systemTimeLine = new QLineEdit(chooseGroup);
	systemTimeLine->setGeometry(QRect(110, 150, 91, 20));
	systemTimeLine->setAlignment(Qt::AlignCenter);
	systemTimeLine->setReadOnly(true);
	currentTimeText = new QLabel(chooseGroup);
	currentTimeText->setGeometry(QRect(20, 150, 81, 21));
	startButton = new QPushButton(this);
	startButton->setGeometry(QRect(30, 220, 101, 23));
	exitButton = new QPushButton(this);
	exitButton->setGeometry(QRect(140, 220, 91, 23));

	countDownRadio->setChecked(true);
	timerRadio->setChecked(false);
	m_time = countEdit->time();
	remainTimeLine->setText(m_time.toString(tr("hh时mm分ss秒")));
	m_start = false;
	m_countDown = true;
	m_mini = false;
	m_suspend = true;

	connect(&m_timeThread, SIGNAL(RemainTimeChanged(const QTime &, int)), this, SLOT(SetRemainTime(const QTime &, int)));
	connect(&m_systemTimeThread, SIGNAL(CurrentTimeChanged(const QTime &)), this, SLOT(SetCurrentTime(const QTime &)));
	m_systemTimeThread.start();
	swidget = new SusWidget(0);

	connect(exitButton, SIGNAL(clicked()), this, SLOT(HideOrExit()));    //reject()
	connect(countEdit, SIGNAL(timeChanged(const QTime &)), this, SLOT(CountTimeChanged(const QTime &)));
	connect(countDownRadio, SIGNAL(clicked()), this, SLOT(ClickedCountDownRadio()));
	connect(timeEdit, SIGNAL(timeChanged(const QTime &)), this, SLOT(doTimeChanged(const QTime &)));
	connect(timerRadio, SIGNAL(clicked()), this, SLOT(ClickedTimerRadio()));
	connect(startButton, SIGNAL(clicked()), this, SLOT(ClickedStartButton()));
	connect(this, SIGNAL(RemainTimeChanged(const QTime &, int)), swidget, SLOT(SetRemainTime(const QTime &, int)));

	setWindowTitle(QApplication::translate("ShutDown", "\351\243\230\344\272\221\345\256\232\346\227\266\345\205\263\346\234\272\347\250\213\345\272\217", 0, QApplication::UnicodeUTF8));
	chooseGroup->setTitle(QApplication::translate("ShutDown", "\350\256\276\345\256\232\345\205\263\346\234\272\346\226\271\345\274\217", 0, QApplication::UnicodeUTF8));
	countDownRadio->setText(QApplication::translate("ShutDown", "\350\256\276\345\256\232\345\200\222\350\256\241\346\227\266\357\274\232", 0, QApplication::UnicodeUTF8));
	timerRadio->setText(QApplication::translate("ShutDown", "\350\256\276\345\256\232\345\205\263\346\234\272\346\227\266\351\227\264\357\274\232", 0, QApplication::UnicodeUTF8));
	remainText->setText(QApplication::translate("ShutDown", "\345\205\263\346\234\272\345\211\251\344\275\231\346\227\266\351\227\264\357\274\232", 0, QApplication::UnicodeUTF8));
	currentTimeText->setText(QApplication::translate("Dialog", "\345\275\223\345\211\215\347\263\273\347\273\237\346\227\266\351\227\264\357\274\232", 0, QApplication::UnicodeUTF8));
	startButton->setText(QApplication::translate("ShutDown", "\345\274\200\345\247\213\345\256\232\346\227\266\345\205\263\346\234\272", 0, QApplication::UnicodeUTF8));
	exitButton->setText(QApplication::translate("ShutDown", "\351\232\220\350\227\217\346\210\226\351\200\200\345\207\272", 0, QApplication::UnicodeUTF8));
}

ShutDown::~ShutDown()
{
	m_systemTimeThread.terminate();
	m_systemTimeThread.wait();
}

/*
void ShutDown::closeEvent(QCloseEvent *event)
{
	int choose = QMessageBox::question(this, tr("最小化到托盘或退出程序"),	tr("飘云温情提示:\n      是否将程序最小化到托盘?最小化请点击Yes,退出程序请点击No。\n最小化后如需退出程序,请在托盘图标上点击右键,选择退出!") ,
		QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
	if( choose == QMessageBox::Yes )
	{
		hide();
		event->ignore();
		trayIcon->show();
		m_mini = true;
		if(m_start)  trayIcon->setToolTip(tr("定时关机程序正在运行"));
		else trayIcon->setToolTip(tr("定时关机程序已经停止运行"));
		m_suspend = true;
		if(m_start) swidget->show();
	}
	else
	{
		reject();
	}
}*/


void  ShutDown::HideOrExit()
{
	int choose = QMessageBox::question(this, tr("最小化到托盘或退出程序"),	tr("飘云温情提示:\n      是否将程序最小化到托盘?最小化请点击Yes,退出程序请点击No。\n最小化后如需退出程序,请在托盘图标上点击右键,选择退出!") ,
		                                     QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
	if( choose == QMessageBox::Yes )
	{
		hide();
		trayIcon->show();
		m_mini = true;
		if(m_start)  trayIcon->setToolTip(tr("定时关机程序正在运行"));
		else trayIcon->setToolTip(tr("定时关机程序已经停止运行"));
		m_suspend = true;
		if(m_start) swidget->show();
	}
	else
	{
		reject();
	}
}

void ShutDown::createActions()
{
	susAction = new QAction(tr("隐藏悬浮窗"), this);
	connect(susAction, SIGNAL(triggered()), this, SLOT(ShowSusWidget()));
	restoreAction = new QAction(tr("还原窗口"), this);
	connect(restoreAction, SIGNAL(triggered()), this, SLOT(ShowDialog()));
	quitAction = new QAction(tr("退出程序"), this);
	connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
	QIcon icon;
	icon.addPixmap(QPixmap(QString::fromUtf8("Resources/sus.png")), QIcon::Normal, QIcon::Off);
	susAction->setIcon(icon);
	QIcon icon1;
	icon1.addPixmap(QPixmap(QString::fromUtf8("Resources/restore.png")), QIcon::Normal, QIcon::Off);
	restoreAction->setIcon(icon1);
	QIcon icon2;
	icon2.addPixmap(QPixmap(QString::fromUtf8("Resources/exit.png")), QIcon::Normal, QIcon::Off);
	quitAction->setIcon(icon2);
}

void ShutDown::createTrayIcon()
{
	trayIconMenu = new QMenu(this);
	trayIconMenu->addAction(susAction);
	trayIconMenu->addAction(restoreAction);
	trayIconMenu->addSeparator();
	trayIconMenu->addAction(quitAction);
	trayIcon = new QSystemTrayIcon(this);
	trayIcon->setContextMenu(trayIconMenu);
	QIcon icon;
	icon.addPixmap(QPixmap(QString::fromUtf8("Resources/shutdown.png")), QIcon::Normal, QIcon::Off);
	trayIcon->setIcon(icon);
	connect(trayIcon, SIGNAL(activated (QSystemTrayIcon::ActivationReason)), this, SLOT(ClikedTrayIcon(QSystemTrayIcon::ActivationReason)));
	susAction->setEnabled(false);
}

void  ShutDown::ShowDialog()
{
	showNormal();
	m_mini = false;
	trayIcon->hide();
	swidget->hide();
}

void  ShutDown::ShowSusWidget()
{
	if ( m_suspend )
	{
		swidget->hide();
		susAction->setText(tr("显示悬浮窗"));
		m_suspend = false;
	}
	else
	{
		swidget->show();
		susAction->setText(tr("隐藏悬浮窗"));
		m_suspend = true;
	}
}
void ShutDown::ClikedTrayIcon(QSystemTrayIcon::ActivationReason reason)
{
	if ( reason == QSystemTrayIcon::Trigger )  ShowDialog();
}

void ShutDown::CountTimeChanged(const QTime &time)
{
	countDownRadio->setChecked(true);
	timerRadio->setChecked(false);
	m_time = countEdit->time();
	remainTimeLine->setText( m_time.toString(tr("hh时mm分ss秒")) );
	m_countDown = true;
}

void ShutDown::ClickedCountDownRadio()
{
	QTime  time = countEdit->time();
	CountTimeChanged(time);
}

void ShutDown::doTimeChanged(const QTime &time)
{
	countDownRadio->setChecked(false);
	timerRadio->setChecked(true);
	QTime systemTime;
	systemTime = systemTime.currentTime();
	QTime setTime = timeEdit->time();
	m_time = setTime.addSecs(-systemTime.hour()*60*60-systemTime.minute()*60-systemTime.second());
	remainTimeLine->setText( m_time.toString(tr("hh时mm分ss秒")) );
	m_countDown = false;
}

void ShutDown::ClickedTimerRadio()
{
	QTime  time;
	time = timeEdit->time();
	doTimeChanged(time);
}

void ShutDown::ClickedStartButton()
{
	if ( m_countDown )
	{
		m_time = countEdit->time();
		remainTimeLine->setText( m_time.toString(tr("hh时mm分ss秒")) );
		remainTimeLine->setText( m_time.toString(tr("hh时mm分ss秒")) );
	}
	else
	{
		QTime systemTime;
		systemTime = systemTime.currentTime();
		QTime setTime = timeEdit->time();
		m_time = setTime.addSecs(-systemTime.hour()*60*60-systemTime.minute()*60-systemTime.second());
		remainTimeLine->setText( m_time.toString(tr("hh时mm分ss秒")) );
	}
	if ( m_start )
	{
		//停止计时
		countDownRadio->setEnabled (true);
		timerRadio->setEnabled(true);
		timeEdit->setEnabled(true);
		countEdit->setEnabled(true);
		susAction->setEnabled(false);
		startButton->setText(tr("开始定时关机"));
		m_start = false;
		m_timeThread.SetCountTime(m_time, m_start);
		m_timeThread.terminate();
		m_timeThread.wait();
	}
	else
	{
		//开始计时
		countDownRadio->setEnabled (false);
		timerRadio->setEnabled(false);
		timeEdit->setEnabled(false);
		countEdit->setEnabled(false);
		susAction->setEnabled(true);
		startButton->setText(tr("取消定时关机"));
		m_start = true;
		m_timeThread.SetCountTime(m_time, m_start);
		m_timeThread.start();
	}
}

void  ShutDown::SetSusTime(const QTime &time, int type)
{
	emit RemainTimeChanged(time, type);
	if ( type == SHUTDOWN_ERROR )
	{
		countDownRadio->setEnabled (true);
		timerRadio->setEnabled(true);
		timeEdit->setEnabled(true);
		countEdit->setEnabled(true);
		susAction->setEnabled(false);
		startButton->setText(tr("开始定时关机"));
		m_start = false;
	}
}

void ShutDown::SetRemainTime(const QTime &time, int type)
{
	if ( !m_mini )
	{
		if ( type == REMAIN_TIME )
		{
			remainTimeLine->setText( time.toString(tr("hh时mm分ss秒")) );
		}
		if ( type == TO_SHUTDOWN )
		{
			remainTimeLine->setText( tr("正在关机...") );
		}
		if ( type == SHUTDOWN_ERROR )
		{
			remainTimeLine->setText( tr("关机失败...") );
			countDownRadio->setEnabled (true);
			timerRadio->setEnabled(true);
			timeEdit->setEnabled(true);
			countEdit->setEnabled(true);
			susAction->setEnabled(false);
			startButton->setText(tr("开始定时关机"));
			m_start = false;
		}
	}
	if ( m_mini && m_suspend )
	{
		SetSusTime(time, type);
	}
}

void ShutDown::SetCurrentTime(const QTime &time)
{
	systemTimeLine->setText( time.toString(tr("hh时mm分ss秒")) );
}



     对于QT,还有个主函数:


main.cpp

#include <QtGui/QApplication>
#include <QtCore/QTextCodec>
#include "shutdown.h"

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	QTextCodec::setCodecForTr(QTextCodec::codecForName("gb2312"));
	ShutDown w;
	w.show();
	return a.exec();
}



     至此一个简单的定时关机程序就编写完了。我也是个QT初学者,代码可能有些生涩,只是分享一下初次使用QT编程序的经验而已。

 

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值