Introduction
Before going in detail about the application, let me tell you what this application will do? As the name suggests, it is used for shutdown, log off or restarting of the computer at a user defined time.
So what is its use?
Today, the world is going digitized. Every thing is running day & night, but not human body; it needs rest. Think of a situation when at night, you want to download your favorite song or favorite software, or you want to defragment your hard disk or burn a CDR, or do some time consuming work, where your sitting for it is not required, But you have to sit, waiting for the task to complete so that you can switch off your PC, as if it is left open, it will waste precious net usage, electricity, and electrical component life of your PC.
So one day, me and my friend came up with a solution: Shutdown Timer/Alarm, that will shutdown your computer at a user defined time. It provides both IN and AT option; means, for e.g., you can shutdown your computer in 2 hrs or you can shutdown your computer at 1.00 PM. Me and my friend decided to release the software with source code so that other users get benefited with it and also we can find bugs in our application.
So how am I achieving it? (What is the code behind it?)
Basic power behind this software is some Win32 APIs, that provide support for shutdown of the computer. There are two APIs to achieve it; these are:
ExitWindowEx
Collapse Copy CodeBOOL ExitWindowsEx ( UINT uFlags, // shutdown operation DWORD dwReason // shutdown reason );
Advantage: Works with all Operating Systems.
InitiateSystemShutdown
Collapse Copy CodeBOOL InitiateSystemShutdown ( LPTSTR lpMachineName, // computer name LPTSTR lpMessage, // message to display DWORD dwTimeout, // length of time to display BOOL bForceAppsClosed, // force closed option BOOL bRebootAfterShutdown // reboot option );
Disadvantage: No support for Windows 9x/ME.
To provide backward sompatibility, I have written this software using the ExitWindowEx
API.
Some Code Snippets
To shutdown the computer in Windows 9x/ME is very simple. Just call the ExitWindowEx
with required parameters to perform system command. I.e., this way:
ExitWindowEx(EWX_SHUTDOWN,0);
Oh, I forgot to tell you about the various flags provided to perform different tasks by ExitWindowEx
. Here are the options:
EWX_LOGOFF
: Logoff the current user.EWX_RESTART
: Simply restart the computer.EWX_SHUTDOWN
: Shut down but 'AT' style.EWX_POWEROFF
: Shut down but 'ATX' style.
For forcibly shutting off your computer, you can use EWX_FORCE
in combination with above four flags. Now, it is not that easy to shut down your computer under Windows multi-user systems like Window 2000 and XP (built on NT technology); you have to acquire the security privilege know as SE_SHUTDOWN_NAME
to provide successful shutdown action.
Here is a code snippet to achieve that:
HANDLE hToken; // handle to process token TOKEN_PRIVILEGES tkp; // pointer to token structure OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken); // Get the LUID for shutdown privilege. LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1; // one privilege to set // Get shutdown privilege for this process. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken,FALSE, &tkp,(PTOKEN_PRIVILEGES) NULL, 0); // Cannot test the return value of AdjustTokenPrivileges. if(GetLastError() != ERROR_SUCCESS) { MessageBox("AdjustTokenPrivileges enable failed."); return; }
Note: if you don�t enable SE_SHUTDOWN_NAME
privilege, your computer will just logoff after ExitWindowEx
or InitiateSystemShutdown
API is called.
About System Tray Interface
This software has system tray interface, i.e., it can be operated from system tray. If you don�t know where system tray is, here I locate that for you:
System Tray
Now you are wondering how to achieve that. It is very simple using the simple API names Shell_NotifyIcon
. Here is the function declaration for Shell_NotifyIcon
API.
BOOL Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA lpdata);
Here are possible value of dwMessage
:
NIM_ADD
: add icon to system tray.NIM_DELETE
: delete icon from system tray.NIM_MODIFY
: modify the system tray icon.
(For e.g., when you connect to Yahoo! chat using Yahoo! messenger, the icon becomes active. And when you logoff, the icon becomes inactive).
And for parameter two, i.e., lpData
, it is a pointer to the NOTIFYICONDATA
structure which is some thing like this:
typedef struct _NOTIFYICONDATA { DWORD cbSize; HWND hWnd; UINT uID; UINT uFlags; UINT uCallbackMessage; HICON hIcon; #if (_WIN32_IE < 0x0500) TCHAR szTip[64]; #else TCHAR szTip[128]; #endif ) DWORD dwState; } NOTIFYICONDATA,*PNOTIFYICONDATA;
Here is a little information for each:
cbSize
: this variable is created to provide compatibility with other versions ofNotifyIconData
.hIcon
: icon for the system tray.hWnd
: handle to window which will handle the system tray icon message.szTip
: show tip when mouse hovers over icon.CallbackMessage
: application-defined message identifier. The system uses this identifier to send notifications to the window identified inhWnd
. These notifications are sent when a mouse event occurs in the bounding rectangle of the icon, or when the icon is selected or activated with the keyboard.uFlag
: this flag notifies the system which of the above variables are to be used or not.uID
: any unique ID for icon.
Now, how to use that! That�s very simple. Just fill the required details and give the proper handle of the icon to the hIcon
parameter to successfully plant an icon in the system bar. Let's say you have two handles for the icon: hIconSleep
, hIconWake
.
Now, here I initialize the structure:
#define MY_MESSAGE WM_APP+75 .... NOTIFYICONDATA m_niData; //handling the ICON at System Tray Icon m_niData.cbSize=sizeof(NOTIFYICONDATA); m_niData.hIcon= hIconSleep; m_niData.hWnd=this->m_hWnd; sprintf(m_niData.szTip,"Shut Down Alarm :My Father Software inc @ 2003"); m_niData.uCallbackMessage=MY_MESSAGE; m_niData.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP; m_niData.uID=10001; ......
For adding the icon to system tray:
Shell_NotifyIcon(NIM_ADD,&m_niData);
For modifying the icon:
//now I am planting new Icon just Like Yahoo // does by showing Online and Offline status m_niData.hIcon= hIconWake; Shell_NotifyIcon(NIM_MODIFY,&m_niData);
For deleting the icon from system tray:
Shell_NotifyIcon(NIM_DELETE,&m_niData);
Now, many of you must be wondering: when we click or right click the icon of any application on the system tray, a menu becomes visible; now how to get that menu? If you read the above source code, one member of the NotifyIcon
structure helps in this case, which is:
m_niData.uCallbackMessage=MY_MESSAGE;
That means, you have to handle MY_MESSAGE
window message to handle the message by your system tray icon. Now, it's very important to note that to receive the message, it is essential to pass NIF_MESSAGE
flag in m_niData.uFlags
.
..................... BEGIN_MESSAGE_MAP(you class, you parent class) ON_MESSAGE(MY _MESSAGE,OnSystemTrayMessage) END_MESSAGE_MAP() ......................
Now to show popup menu or for doing some other task, here is a function that will handle that prerequisite: a menu IDR_MENU1
in your resource file.
void DlgShutDown::OnSystemBarMessage(WPARAM wParam, LPARAM lParam) { //check for window Message which come in LPARAM parameter Switch(lParam) { case WM_LBUTTONDOWN: this->ShowWindow(SW_RESTORE); bMiniShow=FALSE; break; case WM_RBUTTONDOWN: { //Now we are showing the menu on Right Click CMenu mnu; //load the Menu from resource mnu.LoadMenu(IDR_MENU1); CMenu *PopUpMenu; //get the popup menu form the Menu PopUpMenu=mnu.GetSubMenu(0); CPoint pt; //get the current cursor position GetCursorPos(&pt); //show the popup menu PopUpMenu->TrackPopupMenu(TPM_RIGHTALIGN, pt.x,pt.y,this); break; } } }
You can handle the popup menu messages in your current dialog class.
How to Use it?
Using in �AT �way:-
Here is a graphic which shows how to use it in �at� way:
Figure Showing 'AT' Way
Here are the steps:
- Step 1: Choose 'AT' way, i.e., Alarm.
- Step 2: Set time.
- Step 3: Set option for logoff, restart or shutdown.
- Step 4: Click on button Set Timer to activate the timer.
Using �IN� way
Here is a graphic that shows in way:
Figure Showing 'IN' Way
Here are the steps:
- Step 1: Choose 'IN' way, i.e., Time Out option.
- Step 2: Set time.
- Step 3: Set option for logoff, restart or shutdown.
- Step 4: Click on button Set Timer to activate timer.
Update History
- Version 1.1: Some bugs fixed. Minimize is now working without problem. Force option added.
- Version 1.0: First release.