无痕客

落花无情,流水无痕……

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 

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 Code
    BOOL ExitWindowsEx
    (
      UINT uFlags, // shutdown operation 
      DWORD dwReason // shutdown reason
    );

    Advantage: Works with all Operating Systems.

  • InitiateSystemShutdown
    Collapse Copy Code
    BOOL 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:

Collapse Copy Code
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:

Collapse Copy Code
 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.

Collapse Copy Code
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:

Collapse Copy Code
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 of NotifyIconData.
  • 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 in hWnd. 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:

Collapse Copy Code
#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:

Collapse Copy Code
Shell_NotifyIcon(NIM_ADD,&m_niData);

For modifying the icon:

Collapse Copy Code
  //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:

Collapse Copy Code
  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:

Collapse Copy Code
  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.

Collapse Copy Code
        .....................
        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.

Collapse Copy Code
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.

Special Thanks

posted on 2010-06-07 21:45  无痕客  阅读(631)  评论(1编辑  收藏  举报