原理: 利用定时器去检查,如输入的是多少分钟后关机,就根据输入的分钟数产生一个COUNT计数器,计数器一直递减,直到1,然后执行关机。如输入的是几时几分关机,那么定时器会每次都检查系统的时间和你输入的时间是否一直,如果是就执行关机。
MFC做界面还真的是(可能是水平不行吧),怎么弄都是这个样,不好看...
为了防止多个程序同时运行,就限制系统只运行一个程序运行,如下(放到InitInstance中即可):
HANDLE hSem=CreateSemaphore(NULL,1,1,m_pszExeName);//创建一个新的信号量 if(GetLastError()==ERROR_ALREADY_EXISTS)//因为已经存在一个,所以创建失败 { MessageBox(NULL,_T("程序已运行!!!"),NULL,0); exit(2); }
主要实现如下:
void CShutDownDlg::OnOK() { // TODO: Add extra validation here CString str4,str3,str2,str1,StrOut,s,t; int a,b; CTime Time=CTime::GetCurrentTime();//以下GetHour()函数需要先在这里得到当前时间对整个CTime结构体进行初始化 int temp=0; flag0=0;//使用多少分钟后关机标志位 flag1=0;//使用几时几分关机标志位 m_Edit2.GetWindowText(str2); m_Edit3.GetWindowText(str3); m_Edit4.GetWindowText(str4); if(atoi(str2)>0){//检查输入数据的有效性 flag0=1; temp=atoi(str2); count=temp*60;//转换为秒 int Hour = Time.GetHour(); int Min = Time.GetMinute(); a=(Hour+(Min+temp)/60)%24; b=(Min+temp)%60; s.Format("%d",a); t.Format("%d",b); StrOut="系统将在"+s+"时"+t+"分自动关闭计算机,请注意保存文件!"; MessageBox(StrOut,NULL,0); SetTimer(1,1000,NULL); } else if(atoi(str3)>0&&atoi(str4)>0) {//检查输入数据的有效性 flag1=1; StrOut="系统将在"+str3+"时"+str4+"分自动关闭计算机,请注意保存文件!"; h=atoi(str3); m=atoi(str4); MessageBox(StrOut,NULL,0); SetTimer(1,1000,NULL); } else {MessageBox("关机时间设置不正确,请检查!",NULL,MB_OK);return;} MessageBox("我隐藏在进程里了哦:-)!",NULL,MB_OK); ShowWindow(SW_HIDE);//懒得做任务栏小图标了,直接隐藏主程序吧,嘿嘿 }
定时器
void CShutDownDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default CTime tm=CTime::GetCurrentTime(); CString str,strt; str=tm.Format("%m月%d日 %X"); m_Edit1.SetWindowText(str); int hour = tm.GetHour(); int min = tm.GetMinute(); if(1==flag0) { count--; if(1==count) { if(0==SystemShutdown()) { sndPlaySound ("c:\sound\music.wav ",SND_ASYNC);//加个声音提醒哈,怕你睡着了,需要导入winmm.lib库才能使用 MessageBox("关机失败"); } exit(0);} } else if (1==flag1) { if(hour==h&&min==m) { if(0==SystemShutdown()) { sndPlaySound ("c:\sound\music.wav ",SND_ASYNC);//加个声音提醒哈,怕你睡着了,需要导入winmm.lib库才能使用 MessageBox("关机失败"); exit(0);} } } } CDialog::OnTimer(nIDEvent); }
关机实现函数SystemShutdown
bool SystemShutdown(){ HANDLE hToken; TOKEN_PRIVILEGES tkp;//设置访问特权变量 //OpenProcessToken 获取进程的访问令牌 if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken)) { MessageBox(NULL,"获取访问令牌失败!",NULL,0); return FALSE; } // LookupPrivilegeValue查看系统的特权值 LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; // 指定特权数组个数1 tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;//启用特权 // AdjustTokenPrivileges的作用是通知Windows NT修改本进程的权利 AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,(PTOKEN_PRIVILEGES)NULL, 0);//启用当前访问令牌的特权 if (GetLastError() != ERROR_SUCCESS) //失败 { MessageBox(NULL,"获取权限失败!",NULL,0); return FALSE; } if (!ExitWindowsEx(EWX_SHUTDOWN, 0)) //参数在这里设置。EWX_SHUTDOWN 为正常关机,强行退出为WINDOWSEWX_FORCE。 return FALSE; return TRUE; }
判断选择的是哪种模式的定时关机,加在OnTimer里
//更新:判断编辑框是否获得焦点,如编辑框2获得焦点,那么采用多少分钟后关机模式,则几时几分关机模式禁用 //如编辑框3或编辑框4获得焦点,那么采用几时几分关机模式,禁用多少分钟后关机模式 //如别的控件获得焦点,那么两个都可以使用 if(::GetFocus()==m_Edit2.GetSafeHwnd()) { m_Edit3.SetWindowText(NULL); m_Edit3.EnableWindow(FALSE); m_Edit4.SetWindowText(NULL); m_Edit4.EnableWindow(FALSE); } else if(::GetFocus()==m_Edit3.GetSafeHwnd()||::GetFocus()==m_Edit4.GetSafeHwnd()) { m_Edit2.SetWindowText(NULL); m_Edit2.EnableWindow(FALSE); } else { m_Edit2.EnableWindow(TRUE); m_Edit3.EnableWindow(TRUE); m_Edit4.EnableWindow(TRUE); }