您的位置:首页 > 编程语言 > Qt开发

用QT实现Windows定时关机功能

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

截图基于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编程序的经验而已。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: